经典算法08 希尔排序
活动地址:CSDN21天学习挑战赛
*学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。
简介
希尔排序是基于插入排序进行的优化,在进行直接插入排序时,如果数组中元素原本就有序,或者基本有序,直接插入排序效率就很可观。所以希尔排序就是基于这样的思路。
算法思想:
先追求表中元素部分有序,再逐渐逼近全局有序。即先将待排序的表分割成若干形如L[i,i+d,i+2d,....,i+kd]的“特殊”子表,对各子表进行直接插入排序。缩小增量d,直至d=1为止
分析:
假设一个表中有8个元素
第一趟:
我们取d为n/2即d=4
(图片来自王道考研)
此时我们将数组中,49和76放在一个子表中,38和13,65和27,97和49放在同一个子表中。
(图片来自王道考研)
接下来,我们将对子表进行直接插入排序,49和76原本就有序,38大于13,所以交换位置,剩下两组同理可得,即可得出第一趟排序完后的数组
(图片来自王道考研)
第二趟:
此时的d2=d/2=4/2=2 ,和之前一样,划分子表,即49,27,76,65为一个子表,13,49,38,97为一个子表
(图片来自王道考研)
然后对每个子表进行直接插入排序,可以得出下图结果
(图片来自王道考研)
第三趟:
d3=2/2=1,此时就是对整个3数组进行直接插入排序,整个数组就成了开头所说的 基本有序的状态
(图片来自王道考研)
最后对所有的数组进行直接插入排序,最终得出结果
(图片来自王道考研)
总过程:
(图片来自王道考研)
代码实现;
//希尔排序
void ShellSort(int All, int n) {
int d,i, j;
//A[J]只是暂存单元,不是哨兵,当j<=0时,插入位置已到
for (d= n/2; d>=1; d=d/2) //步长变化
for(i=d+1; i<=n;++i)
if(A[i]<A[i-d]){ //需将A[i]插入有序增量子表
A[O]=A[i]; //暂存在Are]
for(j= i-d; j>0 && A[0]<A[j]; j-=d)
A[j+d]=A[i]; //记录后移、查找插入的位置
Alj+d]=A[0]; //插入
}//if
算法性能分析:
空间复杂度:O(1)
时间复杂度:在外面对d取值不同时,时间复杂度会受到影响,即时间复杂度和增量序列d1,d2,d3…的选择有关,目前无法用属性手段证明确切的时间复杂度,最坏的时间复杂度为O(n2),在n在某个范围内时,可达O(n1.3)
稳定性:不稳定
适用性:仅适用于顺序表,不适用于链表
总结:
(图片来自王道考研)