梳排序

梳排序（Comb sort）是一种由弗拉基米尔·多博舍维奇（Wlodzimierz Dobosiewicz）于1980年所发明的不稳定排序算法，并由史蒂芬·莱西（Stephen Lacey）和理查德·博克斯（Richard Box）于1991年四月号的中推广。梳排序是改良自泡沫排序和快速排序，其要旨在于消除「乌龟」，亦即在阵列尾部的小数值，这些数值是造成泡沫排序缓慢的主因。相对地，「兔子」，亦即在阵列前端的大数值，不影响泡沫排序的效能。
在泡沫排序中，只比较阵列中相邻的二项，即比较的二项的间距（Gap）是1，梳排序提出此间距其实可大于1，改自插入排序的希尔排序同样提出相同观点。梳排序中，开始时的间距设定为阵列长度，并在回圈中以固定比率递减，通常递减率设定为1.3。在一次回圈中，梳排序如同泡沫排序一样把阵列从首到尾扫描一次，比较及交换两项，不同的是两项的间距不固定于1。如果间距递减至1，梳排序假定输入阵列大致排序好，并以泡沫排序作最后检查及修正。
递减率.
递减率的设定影响著梳排序的效率，原作者以随机数作实验，得到最有效递减率为1.3的。如果此比率太小，则导致一回圈中有过多的比较，如果比率太大，则未能有效消除阵列中的乌龟。
亦有人提议用formula_1作递减率，同时增加换算表协助于每一回圈开始时计算新间距。
因为程式语言中乘法比除法快，故会取递减率倒数与间距相乘，formula_2
变异形式.
梳排序-11.
设定递减率为1.3时，最后只会有三种不同的间距组合：(9, 6, 4, 3, 2, 1)、(10, 7, 5, 3, 2, 1)、或 (11, 8, 6, 4, 3, 2, 1)。实验证明，如果间距变成9或10时一律改作11，则对效率有明显改善，原因是如果间距曾经是9或10，则到间距变成1时，数值通常不是递增序列，故此要进行几次泡沫排序回圈修正。加入此指定间距的变异形式称为"梳排序-11(Combsort11)"。
混合梳排序和其他排序算法.
如同快速排序和合并排序，梳排序的效率在开始时最佳，接近结束时最差。如果间距变得太小时(例如小于10)，改用插入排序或希尔排序等算法，可提升整体效能。
此方法最大好处是不需要检查是否进行过交换程序以将排序回圈提早结束。
实作范例.
C语言.
<syntaxhighlight lang="c">
void comb_sort(int arr[], int len) {
 double shrink_factor = 0.8;
 int gap = len, swapped = 1, i;
 int temp;
 while (gap > 1 || swapped) {
 if (gap > 1)
 gap *= shrink_factor;
 swapped = 0;
 for (i = 0; gap + i < len; i++)
 if (arr> arr[i + gap) {
 temp = arr;
 arr= arr[i + gap;
 arr+ gap = temp;
 swapped = 1;
</syntaxhighlight>
C++.
<syntaxhighlight lang="cpp">
template<typename T> //整数或浮点数皆可使用，若要使用物件（class）时必须设定大于（>）的运算子功能
void comb_sort(T arr[], int len) {
 double shrink_factor = 0.8;
 int gap = len, swapped = 1, i;
 while (gap > 1 || swapped) {
 if (gap > 1)
 gap = (int) ((double) gap * shrink_factor);
 swapped = 0;
 for (i = 0; gap + i < len; i++)
 if (arr> arr[i + gap) {
 swap(arrarr[i + gap);
 swapped = 1;
</syntaxhighlight>
Java.
<syntaxhighlight lang="java">
public static <E extends Comparable<? super EÂ» void sort(E[] input) {
</syntaxhighlight>
JavaScript.
<syntaxhighlight lang="javascript">
Array.prototype.comb_sort = function() {
 var shrink_factor = 0.8;
 var gap = this.length, swapped = 1, i;
 var temp;
 while (gap > 1 || swapped) {
 if (gap > 1)
 gap = Math.floor(gap * shrink_factor);
 swapped = 0;
 for (i = 0; gap + i < this.length; i++)
 if (this> this[i + gap) {
 temp = this;
 this= this[i + gap;
 this+ gap = temp;
 swapped = 1;
 return this;
</syntaxhighlight>
PHP.
<syntaxhighlight lang="php">
function swap(&$x, &$y) {
 $t = $x;
 $x = $y;
 $y = $t;
function comb_sort(&$arr) {//php的阵列视为基本型别，所以必须用传参考才能修改原阵列
 $shrink_factor = 0.8;
 $gap = count($arr);
 $swapped = 1;
 while ($gap > 1 || $swapped) {
 if ($gap > 1)
 $gap = floor($gap * $shrink_factor);
 $swapped = 0;
 for ($i = 0; $gap + $i < count($arr); $i++)
 if ($arr[$i] > $arr[$i + $gap]) {
 swap($arr[$i], $arr[$i + $gap]);
 $swapped = 1;
</syntaxhighlight>
Go.
<syntaxhighlight lang="go">
func comb_sort(data sort.Interface) {
 n := data.Len()
 shrinkFactor := 0.8
 gap := n
 swapped := true
 for gap > 1 || swapped {
 if gap > 1 {
 gap = int(float64(gap) * shrinkFactor)
 // 冒泡排序
 swapped = false
 for i := 0; i < n - gap; i++ {
 if data.Less(i + gap, i) {
 data.Swap(i + gap, i)
 swapped = true
</syntaxhighlight>
Julia (程式语言).
<syntaxhighlight lang="julia">
function CombSort(A)
 gap,swapped = length(A),1
 while (gap>1) || (swapped==1)
 gap = floor(Int,gap/1.25)
 swapped=0
 for i=1:(length(A)-gap)
 if A>A[i+gap]
 A= A[i+gap,A
 swapped=1
 end
 end
 end
 return A
end
A = [16,586,1,31,354,43,3]
println(A) # Original Array
println(CombSort(A)) # Comb Sort Array
</syntaxhighlight>
动作原理.
假设输入为
目标为将之变成递增排序。因为输入长度=8，开始时设定间距为8/1.3≒6，则比较8和2、4和1，并作交换两次。
第二次回圈，更新间距为6/1.3≒4。比较2和6、1和5，直至7和4，此回圈中只须交换一次。
接下来的每次回圈，间距依次递减为3 → 2 → 1，
间距=3时，不须交换
间距=2时，不须交换
间距h=1时，交换三次
上例中，共作了六次交换以完成排序。