三.希尔排序/缩小增量排序
基于直接插入排序,从部分有序到全局有序
(一)步骤
设置增量d.以下按
d
1
=
n
/
2
,
d_1=n/2,
d1=n/2,
d
i
+
1
d_{i+1}
di+1=⌊
d
i
d_i
di/2⌋,最后一个增量等于1计算
代码表示:for (dk = n / 2; dk >= 1; dk /= 2)
n=8,d依次取4,2,1
1.第一轮d=4(代码中为dk)
每隔4个取一个元素。对每个子表,按第一个元素自身有序,其余依次往前执行直接插入排序
完成
代码分析:从第1+dk个(第5个)元素起,依次和同子表上一个元素比较,进行直接插入
if (a[i] < a[i-dk]) //判断
{
a[0] = a[i];//哨兵暂存
for (j = i-dk; j >= 1&&a[0]<a[j]; j = j - dk)//从上一个元素起,当前元素和前面所有相距为dk的元素比较,进行直接插入
a[j + dk] = a[j];//后移
a[j + dk] = a[0];//多减了dk
}
第一轮结束
2.第二轮d=2
完成
即
3.第三轮d=1
此时包含所有元素
直接进行直接插入排序
结束
总
注:每个子表元素个数不一定相同
如d=3
(二)完整代码
#include<stdio.h>
#include<iostream>
using namespace std;
void ShellSort(int a[], int n)
{
int dk,i,j;
for (dk = n / 2; dk >= 1; dk /= 2)
{
for (i = dk+1; i <= n; i++)
{
if (a[i] < a[i-dk])
{
a[0] = a[i];
for (j = i-dk; j >= 1&&a[0]<a[j]; j = j - dk)
a[j + dk] = a[j];
a[j + dk] = a[0];
}
}
}
}
int main()
{
int a[6] = { 0,34,23,12,87,45 };
ShellSort(a, 5);
for (int i = 1; i <= 5; i++)
{
cout << a[i] << " ";
}
}
(三)性能分析
1.空间复杂度:O(1)
2.时间复杂度:当d=1时退化为直接插入排序,最坏O(n²),平均和最好约为O(
n
1.3
n^{1.3}
n1.3)
3.稳定性
可以看出,49和
49
‾
\underline{\text{49}}
49的位置发生了颠倒,因此是不稳定的
(四)总结