基本思想:希尔排序是把序列按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量的逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个序列恰好被分为一组,算法便终止。
算法实现:选定一个增量k,按照增量k作为数据分组的依据,对数据进行分组;对分好组的每一组数据完成插入排序;减小增长量,最小减为1,重复上一步操作。这里是用k=k/3+1;的方式来选取增量的,这个增量序列并不是最优的。可是怎样选取最好的增量,目前还是一个数学难题,还没有人找到一种最好的增量序列。
代码实现:
//希尔排序
void shell(sqlist_t *l)
{
int i,j;
int k = l->last;
do {
k = k / 3 + 1;//定义变化增量
for(i = k ; i <= l->last; i++)
if(l->data[i - k] > l->data[i])//判断第一个数和第i个数的值大小
{
int temp = l -> data[i];//暂存值
for(j = i- k; j >= 0 && l->data[j] > temp; j-=k)
{
l->data[j + k] = l->data[j];//记录后移,寻找插入位置
}
l->data[j + k] = temp;//插入
}
}
}while(k>1);
}
1、时间复杂度
增量的选择是希尔排序的重要部分,只要最终增量为1任何增量序列都可以工作。
算法最开始以一定的增量进行排序。然后会继续以一定增量进行排序,最终算法以增量为1进行排序。当增量为1时,算法变为插入排序,这就保证了数据一定会被排序。
增量序列的不同,会导致最坏的时间复杂度情况的不同。本文中最坏时间复杂度为N^2。
用这样增量序列的希尔排序比插入排序要快,甚至在小数组中比快速排序和堆排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。
2、算法稳定性
希尔排序中相等数据可能会交换位置,所以希尔排序是不稳定的算法。