参考:《漫画算法-小灰的算法之旅》
目录
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,在排序之后改变了次序,由此可见希尔排序是一个 不稳定排序。