简介:
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。
算法思想:
倘若待排序列基本有序以及序列个数较少,则可以减少插入排序的比较次数,从而从整体上提高排序的效率。希尔排序就是基于这两点(待排序列元素较少以及序列元素基本有序)来实现的。
希尔排序实质上是采用分组插入的方法。先将整个待排序列分割成若干组,从而减少参与直接插入排序的数据量,对每组分别进行直接插入排序。然后增加每组的数据量,重新分组。这样经过若干次排序,整个序列中的记录变得基本有序时,再对整体序列进行一次插入排序。
例如上图:
- 按增量为5划分为5组,每组仅两个元素,从而减少了插入排序的比较次数
- 按增量为2划分为2组,每组5个元素,但是经过上一轮的排序,此次序列有序对明显增多
- 按增量为1划分,直接进行一次插入排序
代码示例:
#include<bits/stdc++.h>
using namespace std;
void shell_insert(int *ars, int k, int n){
for(int i = k+1, j; i <= n; i++){
if(ars[i] < ars[i-k]){
ars[0] = ars[i];//数组[0]暂存数据
for(j = i-k; j > 0 && ars[0] < ars[j]; j -= k)
ars[j+k] = ars[j];
ars[j+k] = ars[0];
}
}
}
void shell_sort(int *ars, int n){
int k[] = {5, 3, 1};
for(int i = 0; i < 3; i++)
shell_insert(ars, k[i], n);
}
int main(){
int n = 10;
int ars[11];
for(int i = 1; i <= 10; i++)
ars[i] = rand() % n;
shell_sort(ars, n);
for(int i = 1; i <= 10; i++)
cout << ars[i] << " ";
return 0;
}
时间复杂度:
当增量大于1时,关键字较小的记录就不是一步一步地挪动,而是跳跃式地移动,从而使得在进行最后一次增量为1的插入排序中,序列已基本有序,只要做记录的少量排序和移动即可完成排序,因此希尔排序的时间复杂度低于插入排序。但具体分析,希尔排序的时间复杂度与选择的增量序列的函数有关。有关实验证明,当增量取2 ^ (t-k+1)时,希尔排序的时间复杂度为O(n ^ 3/2),其中t为排序的趟数。若n趋向无穷大时,则可以见到n(log2n)^ 2。