一、希尔排序(插入排序)
又称缩小增量排序
不稳定排序
方法:
希尔排序在序列中进行跳跃式分组,通过某个增量将原始序列分成多组,针对每组进行插入排序;再减小增量,继续分组排序;直至增量减为1,则整个序列被分为一组。
与简单插入排序相比,希尔排序通过分组排序,逐渐使得值较小的数据在前,较大的数据在后,所以到后面只需要微调;而简单插入排序每次都要从后往前一步步调。
例:原始序列 23, 6, 78, 120, 1,24
使用希尔推荐的增量,初始增量为len/2,后续增量为上一次增量的1/2
增量:d1 = 3
分成3组:23,120;6,1;78,24
分组插入排序之后:23, 1, 24, 120, 6, 78
增量:d2 = 2
分成2组:23,24,6 ; 1,120,78
分组插入排序之后:6, 1, 23,78,24,120
增量:d3 = 1
分成1组:6,1,23,78,24,120
插入排序之后:1, 6, 23,24, 78, 120
c++代码:
void ShellSort(vector<int>& sequence)
{
const int c_len = sequence.size();
int d = c_len; //增量
int key;
while(d>1)
{
d = ceil(float(d) / 2);
//分组:分成d组
for(int i=0; i<d; ++i)
//针对每个组排序
for(int j=i+d; j<c_len; j+=d)
{
key = sequence[j];
int k = j-d;
while(k>=0)
{
if(key<sequence[k])
sequence[k+d] = sequence[k];
else
break;
k -= d;
}
sequence[k+d] = key;
}
}
}
空间复杂度:除去待排序序列,只需要存储key
S(n) = θ(1)
时间复杂度:本文代码使用的不是最佳增量,所以时间复杂度不按本文代码计算
最好情况:待排序序列按正序排列
T(n) = θ(n)
最坏情况:待排序序列逆序排列
T(n) = θ(n^2)
平均情况:T(n) = θ(n^1.3)