希尔排序:基于插入算法的改进版本
希尔排序:基于插入算法的改进版本
平均时间复杂度:O(n log n)
最好时间复杂度:O(n log^2 n)
最坏时间复杂度:O(n log n)
稳定性:不稳定
特点:1.处理基本有序的效率较高
2.数据量比较小时效率较高
希尔排序,又名缩小增量排序,是基于插入排序的一种改进算法,解决了插入排序一次只能移动一个元素造成的低效问题。
原理
1.设定一个增量整型gap = len / 2,向下取整,根据gap分组。
2.对每一组进行插入排序。
3.更新gap = gap / 2,继续以上操作。
4.知道gap == 1停止,对所有元素执行插入排序。
代码实现
1 |
|
代码解释
假设有 {4, 2, 7, 0, 5, 8}这个数组,len = 6,首先,初始的 gap = len >> 1 也就是 6 >> 1 = 3(这里的 “>>” 是右移操作符,相当于除以 2 向下取整)。此时数组根据 gap 的值被分为了两组,分别是 {4, 0} 和 {2, 5} 以及 {7, 8}。
对于第一组 {4, 0},进入内层的插入排序循环(也就是第三层循环),因为 4 > 0,所以会将 4 往后移动(通过 arr [j + gap] = arr [j] 语句),然后把 0 放到合适的位置,即 arr [0] 的位置,这一组就排好了序。同样地,对 {2, 5} 和 {7, 8} 这两组也会进行类似的插入排序操作。
接着,更新 gap = gap >> 1,此时 gap 变为 1。这意味着现在要对整个数组当作一组来进行插入排序了。
从第二个元素开始遍历整个数组(第二层循环保证了这个遍历过程),比如对于元素 2,先把它存到临时变量 temp 中,然后通过第三层循环,与前面已经排好序的元素依次比较(这里是和 4 比较,因为 j = i - gap,此时 i 是对应元素 2 的索引,gap 为 1),如果前面的元素大于它,就把前面的元素往后移(同样是通过 arr [j + gap] = arr [j] 语句),直到找到合适的位置,再把 temp(也就是 2)放到那个位置。就这样依次对数组中的每个元素进行这样的插入排序操作,直到整个数组都排好序为止。
改进点
增量大时,分组多,组内元素比较少,效率较高。
随着增量逐渐减小,虽然组内元素越来越多,但整体越来越有序,所以效率越来越高。
不稳定性
希尔排序会改变排序前相同元素的相对位置。
例如:数组 [5*, 4, 5, 2, 8, 1],(对不同的5加星号标记)希尔排序之后会改变两个5的相对位置,排序后的星号5出现在5的后面。
所有希尔排序具有不稳定性。