1.什么叫希尔排序
希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名
2.希尔排序的基本思想
先取一个小于n的整数d1作为第一个增量,把传进来的数据记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量(1<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
3.举例
输入数据为 n=8
即a[8]={48 26 22 68 46 42 36 84 66}
输出数据:
a[8]={22 26 36 42 46 48 66 68 84}
过程:
1.首先将原始数据 48 26 22 68 46 42 36 84 66以d1=8/2=4划分,
间隔为4的归为一个子序列,再对每一个子序列 用插入排序排好
2.再将上述排序结果以d2=2划分
(46 22 48 36 66)——> 22 36 46 48 66
(26 68 42 84 )——> 26 42 68 84
排序结果:22 26 36 42 46 68 48 84 66(从第一列到第二列到第x列)
3.再将上述排序结果按d3=1划分
(22 26 36 42 46 68 48 84 66)——> 22 26 36 42 46 48 66 68 84
排序结果:22 26 36 42 46 48 66 68 84 */
4.C++代码示意
/*希尔排序主要思想:
1.先选定一个整数d1作为初始间隔,将此文件记录数按照d1从第一个开始分成若干个“子序列”,
所有间隔为d1的记录为一个子序列,再各序列中用插入排序
2.选定d2<d1,以d2为间隔重复1的操作
3.直至间隔数di=1为止排好序
ps:取di的方法有很多,这里取d1=n/2,di=d(i-1)/2
*/
#include<iostream>
using namespace std;
int a[100];
//交换函数,目的是交换数组中两个元素的位置
void swap(int a[],int i,int j)
{
int temp;
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
//希尔排序
void Shell_Sort(int a[],int n)
{
int temp;
for(int d=n/2;d>=1;d=(d/2)){//减小增量,直到增量为1
//对每一轮进行插入排序
for(int i=d;i<n;i++){
if(a[i]<a[i-d]){
temp=a[i];
for(int j=i-d;j>=0&&a[j]>temp;j=j-d)
swap(a,j,j+d);
}
}
}
}
//主函数
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
Shell_Sort(a,n);
for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
/*input:
9
48 26 22 68 46 42 36 84 66
output:
22 26 36 42 46 48 66 68 84
过程:
1.首先将原始数据 48 26 22 68 46 42 36 84 66以d1=8/2=4划分,
间隔为4的归为一个子序列,再对每一个子序列 用插入排序排好序
(48,46 66)——> 46 48 66
(26,42 )——> 26 42
(22,36 )——> 22 36
(68,84 )——> 68 84
排序结果:46 26 22 68 48 42 36 84 66(从第一列到第二列到第三列)
2.再将上述排序结果以d2=2划分
(46 22 48 36 66)——> 22 36 46 48 66
(26 68 42 84 )——> 26 42 68 84
排序结果:22 26 36 42 46 68 48 84 66(从第一列到第二列到第x列)
3.再将上述排序结果按d3=1划分
(22 26 36 42 46 68 48 84 66)——> 22 26 36 42 46 48 66 68 84
排序结果:22 26 36 42 46 48 66 68 84 */
5.算法分析
通过上述分析可知,希尔排序的关键不是随便分组后各自排序,而是将相隔某个“增量”的记录组成一个子序列,实现跳跃式的移动,使得排序的效率提高。
这里的“增量”选取非常关键,但是究竟选什么增量才是最好,目前还是一个数学难题,迄今为止还没有人找到一种最好的增量序列。不过研究表明,当增量序列为dlta[k]=2^(t-k+1)-1 (0<=k<=t<=log2(n+1))时,可以获得不错的效果,其时间复杂度为O(n^1.5),要好于直接排序的O(n^2)。需要注意的是,增量序列的最后一个增量值必须等于1才行。另外由于记录是跳跃式的移动,希尔排序并不是一个稳定的排序算法。
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
希尔排序 | O(nlogn)~O(n^2) | O(n^1.3) | O(n^2) | O(1) | 不稳定 |