概述
希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
希尔排序中包含了分而治之的思想,首先将一个输入序列根据增量分成若干个子序列,然后对每个子序列分别进行插入排序。然后减少增量,然后对继续将序列根据增量分成若干个子序列,继续在每个子序列中进行插入排序。一直重复这样的动作,直到增量=1时,整个输入序列恰被分成一组,此时整个输入序列就完成了全部元素的排序。
希尔排序的增量序列的选择与证明是个数学难题,此处我们使用的希尔增量根据length生成,这种增量选择我们可以用一个序列来表示,{h,(h-1)/3,((h-1)/3-1)/3…1},称为增量序列。其中h生成算法如下:
int h=0;
while (h < length) {
h = h * 3 + 1;
}
if(h>1){
h=(h-1)/3;
}
算法描述
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:
-
选择一个增量序列t1,t2,ti, tj …,1,其中ti>tj
-
按增量序列个数k,对序列进行k 趟排序;
-
每趟排序,根据对应的增量,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。当增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
希尔排序C/C++代码实现:
/**
* 希尔排序 是插入排序的改进,效率较高
* 最差时间复杂度 根据步长序列的不同而不同。已知最好的为O(n(logn)^2)
* 最优时间复杂度 O(n)
* 平均时间复杂度 O(nlogn)
* 空间复杂度 O(1)
* 稳定性 不稳定
* 效率
* @param arr 数组
* @param n 长度
*/
void ShellSort(int arr[],int n)
{
//01 生成初始增量
int h=0;
while (h < n) {
h = h * 3 + 1;
}
if(h>1){
h=(h-1)/3;
}
//02将输入序列根据增量h分割成若干个子序列,并对每个子序列进行插入排序
//逐渐缩小增量,直到小于零
while (h>0)
{
//03 对子序列进行插入排序
for (int i = h; i < n; i++) {
int get=arr[i]; //待插入的元素
int j=i-h; //
while(j>=0 && arr[j]>get)
{
arr[j+h]=arr[j];
j=j-h; //切换到子序列中的下一个元素
}
arr[j+h]=get; //将元素插入到该位置
}
h=(h-1)/3; //递减增量
}
}