基本思想:创造一些条件,使序列基本有序:小的关键字基本在前面,大的关键字基本在后面,不大不小的基本在中间。这样再进行直接插入排序时就会减少许多的移动操作。实现方式是将序列分成若干个子序列,此时对每个子序列进行直接插入排序,当整个序列都基本有序时,再对全体序列进行一次直接插入排序。
这里子序列的选取是通过一个跳跃分割的方式:将相距某个增量的记录组成一个子序列,(如每相距3个距离的记录组成一个子序列)。如果是这样分割:{9, 1, 5,8,3,7,4, 6, 2}分成三组{9, 1, 5},{8, 3, 7},{4,6,2},即便每个子序列排序好了以后再合并一起{1,5,9,3,7,8,2,4,6}仍然是杂乱的。所以要用增量分隔开。
#include <stdio.h>
void print(int array[], int len)
{
int i = 0;
for(i=0; i < len; i++)
{
printf("%d ", array[i]);
}
printf("\n");
}
void ShellSort(int array[], int len)
{
int i = 0;
int j = 0;
int k = -1;
int temp = -1;
int increment = len; //增量
do
{
increment = increment/3 + 1; //关键的地方
for(i=increment; i < len; i++)
{
k = i;
temp = array[i];
for(j = i-increment; (j >= 0) && (array[j] > temp); j -= increment)
{
array[j+increment] = array[j];
k = j;
}
array[k] = temp;
}
}while(increment > 1);
}
int main()
{
int array[] = {2 ,1, 4, 3, 2, 6, 8 ,5, 2};
int len = sizeof(array) / sizeof(array[0]);
ShellSort(array, len);
print(array, len);
return 0;
}
代码中用increment = increment/3 + 1;选取增量,还可以把3改成别的数,至于选哪儿最好,至今还是一个数学难题,不过大量的研究表明,当选取3时,可以获得不过的效果,其时间复杂度为O(n3/2)。要注意的是必须保证增量最后是1,这样才能执行一个全序列的直接插入排序。而且希尔排序是不稳定的。