一、算法基本思想
希尔排序的基本思想是:先将待排序表分割为若干形如【i,i+d,i+2d,......,i+kd】的“特殊”子表,即把相隔某个“增量”的元素组成一个字表,对各个子表分别进行直接插入排序,当整个表中的元素已呈“基本有序”时,再对全体元素进行一次直接插入排序。
例如:
10 | 25 | 2 | 6 | 15 | 5 |
先取一个小于n(元素个数)的增量d1,建议增量为n/2;所以此处d1=6/2=3;将所有相隔为d1的倍数的元素放在同一子表,并进行直接插入排序:
10 | 6 |
25 | 15 |
2 | 5 |
第一轮:增量为d1=3的三个子表如上所示(此处是为了直观展示各子表,所以分为三个表格),对其分别进行直接插入排序后得到结果如下:
6 | 10 |
15 | 25 |
2 | 5 |
将其重新归还为一个表为:
6 | 15 | 2 | 10 | 25 | 5 |
第二轮:增量d2=2的两个子表如下所示:
6 | 2 | 25 |
15 | 10 | 5 |
分别对其进行直接插入排序后结果如下:
2 | 6 | 25 |
5 | 10 | 15 |
将其重新归还为一个表为:
2 | 5 | 6 | 10 | 25 | 15 |
此时,该表已基本有序,
第三轮:d3=d2/2=1,即对全体元素进行依次插入排序,结果如下:
2 | 5 | 6 | 10 | 15 | 25 |
二、代码实现
1、算法代码
//希尔排序
void ShellSort(int A[],int n){
int i,j,d,temp;
for(d=n/2;d>=1;d=d/2) //增量变化(无统一规定)
for(i=d;i<n;++i){
temp=A[i];
if(temp<A[i-d]){
for(j=i-d;j>=0&&temp<A[j];j=j-d)
A[j+d]=A[j];
A[j+d]=temp;
}
}
}
2、测试结果
三、算法分析
1、性能分析
空间效率:仅使用了常数个辅助单元,所以其空间复杂度为O(1)。
时间效率:因为希尔排序的时间复杂度依赖于增量序列的函数,这涉及数学上尚未解决的难题,因此其时间复杂度分析比较困难。当n在某个特定范围时,希尔排序的时间复杂度为O(n^1.3)。在最坏情况下希尔排序的时间复杂度为O(n²)。
2、稳定性
当相同元素被划分到不同子表时,可能会改变他们之间的相对次序,因此希尔排序是一种不稳定的排序算法。
3、适用性
仅适用于顺序存储的线性表