希尔排序也叫做缩小增量排序(diminishing increment sort), 它的核心思想即利用插入排序在序列已经排好序或者大部分有序的情况下有接近线性时间的时间复杂度,通过不断地缩小增量来使得这个序列在局部上是有序的,最后不断地通过插入排序把整个序列变成有序的。源代码如下
//insertion sort sublist
void Sort::shellInsert(int n, int incree)
{
int key;
//the last position of the sublist
//march down the adjacent sublists
for (int i = n - 1; i >= incree; i -= incree) {
//insertion sort each element of the sublist
//march down sublist from tail to head
int j;
//insertion sort
for (j = i - incree; j >= 0; j -= incree) {
key = a[j];
int k;
//march down the elements after the present element
//if march down the sublist from head to tail
//march down elemets after the present element
for (k = j; k < i; k += incree) {
//if the previous element is smaller than the present element
//the present element was set to the previous element
//ascend, if >, descend
if (a[k+incree] < key) {
a[k] = a[k + incree];
}
//if not, break;
else
break;
}
a[k] = key;
cout << "Sorting: ";
Print();
}
}
}
void Sort::shellSort(int n)
{
for (int i = n / 2; i > 2; i /= 2) {
for (int j = 0; j < i; j++) {
cout << "i = " << i << ": " << endl;
cout << "j = " << j << ": " << endl;
shellInsert(n - j, i);
}
}
//the last sort for the whole array
cout << "i = " << 2 << ": " << endl;
shellInsert(n, 1);
}
在函数shellSort里面,首先通过for循环用增量除以2得到每次循环的增量,通过n-j来控制每次用shellInsert函数排序的子序列的位置。最后用一个插入排序对整个序列进行排序,得到一个排好序的序列。
增量的取值也会有所差异,shell主张使用n/2的增量,但是这样,在最后一次的插入排序时才会进行奇数位和偶数位上的排序,可能会影响性能,因此knuth提出使用n/3的增量