[算法]希尔排序——插入排序的升级

参考:《漫画算法-小灰的算法之旅》

目录

1、希尔排序的思想

2、例子

3、希尔排序代码

4、希尔排序的优化

5、希尔排序是不稳定排序


问:什么情况下插入排序的工作量会比较小呢?

答:首先,当数组元素较小时,插入排序的工作量会比较小。因为插入排序的时间复杂度是O(n^2),工作量和n^2成正比,如果n比较小,那么排序的工作量自然会小得多。 其次,当数组大部分元素有序的时候,插入排序的工作量也会相对 较小。因为在这种情况下,数组中的元素并不需要进行频繁的比较和交换。

希尔排序的思想就与上面回答的意思相似,下面来说明。

1、希尔排序的思想

将原始数组逐步分组进行粗调,在进行直接插入排序的思想。

2、例子

原始数组如下:

 首先将元素两两分组,同组两个元素之间的跨度时数组总长度的一半。在该例中分组跨度为4。

 如上图所示,元素5和元素9一组,元素8和元素2一组,元素6和元素1一组,元素3和元素7一组,一共4组。

接下来,我们让每组元素进行独立排序,排序方式用直接插入排序 即可。由于每一组的元素数量很少,只有两个,所以插入排序的工作 量很少。每组排序完成后的数组如下:

我们可以进一步缩小分组跨度,重复上述工作。把跨度缩小为原先的一半,也就是跨度为2,重新对元素进行分组:

如图所示,元素5,1,9,6一组,元素2,3,8,7一组,一共两组。 接下来,我们继续让每组元素进行独立排序,排序方式用直接插入排序即可。每组排序完成后的数组如下: 

此时,数组的有序程度进一步提高,为后续将要进行的排序铺平了 道路。 最后,我们把分组跨度进一步减小,让跨度为1,也就等同于做直 接插入排序。经过之前的一系列粗略调整,直接插入排序的工作量减 少了很多,排序结果如下:

上面示例中所使用的分组跨度(4,2,1),被称为希尔排序的增量,增量的选择可以有很多种。我们在示例中所用的逐步折半的增量 方法,是Donald Shell在发明希尔排序时提出的一种朴素方法,被称 为希尔增量

3、希尔排序代码

4、希尔排序的优化

希尔排序利用分组的粗调方式减少了直接插入排序的工 作量,使得算法的平均时间复杂度低于O(n^2)。 但是,在某些极端情况下,希尔排序的最坏时间复杂度仍然是 O(n^2),甚至比直接插入排序更慢。例如:

上面这个数组,如果我们照搬之前的分组思路,无论是以4为 增量,还是以2为增量,每组内部的元素都没有任何交换。一直到我们 把增量缩减为1,数组才会按照直接插入排序的方式进行调整。 对于这样的数组,希尔排序不但没有减少直接插入排序的工作量, 反而白白增加了分组操作的成本。 

每一轮希尔增量之间是等比的,这就导致了希尔增量存在盲区。为了避免这样的极端情况,可以选择更有效的增量方式,即保证每一轮的增量彼此"互质“。如:

  • Hibbard的增量序列如下:1, 3, 7, 15……最坏时间复杂度是O(n^3/2)。
  • Sedgewick的增量序列如下: 1, 5, 19, 41, 109……最坏时间复杂度是O(n^4/3)。

5、希尔排序是不稳定排序

希尔排序是不稳定排序,值相同的元素有可能被调换位置。例子:

 在上面的数组中,有两个元素5,黄色的5在前,橙色的5在后。 假如我们按照希尔增量分组,第1轮粗调(增量为4)之后,黄色的 元素5会和元素4交换,换到橙色的5后面:

 最终排序结果:

 相同的元素5,在排序之后改变了次序,由此可见希尔排序是一个 不稳定排序。

猜你喜欢

转载自blog.csdn.net/weixin_45922730/article/details/129430167
今日推荐