Animation | What is Shell sort?

Hill sorting property

Part written directly into the sort algorithm time complexity is O (n ^ 2), if you want to make this sort time complexity of the algorithm is lower than the O (n ^ 2), must be "remote switching element" makes it set of elements can improve the orderly degree, followed by direct insertion sort when you can reduce the workload of exchange.

What that by reducing the workload of exchange it? Shell sort can solve this problem.

Hill sorting before doing direct insertion sort, the entire original desired to be sorted can be pretreated column, the final purpose is to direct insertion sort step can reduce the exchange frequency and time, but also to reduce the consumption of time.

An initial state is assumed that the array: 5,1,9,3,7,4,8,6,2

Then the increment is set to an initial gap = length / 2 = 9/2 = 4, and comparison means between the two switching elements are from 4 (via the three elements), and will be divided into four groups, [5,7,2], [1,4], [9,8], [3,6].

These five groups were sorted directly inserted in the code, which are interspersed with direct insertion sort, will be seen in the following video animation.

End time of the four groups is then sorted to gradually narrow increment, gap = 4/2 = 2, illustrates a comparison of two elements will be exchanged and the distance is 2, divided into two groups, but also against two sorts .

Finally, the incremental reduced to 1, this time is pure direct insertion sort, because in front of a pretreatment, such that this whole sequence of "rough adjustment" in the last step when doing direct insertion sort, to be sorted if column clear and orderly, then it really reduce the number of exchanges, but also really reduces the consumption of time.

(Doing the animation process, the intermediate wrong element exchange, has been fixed, the middle part of the action when playing catch up a bit).

Video Animation: Hill sorting exchange

Code

Result

初始状态 [5, 1, 9, 3, 7, 4, 8, 6, 2]
4增量
交换 [5, 1, 8, 3, 7, 4, 9, 6, 2]
交换 [5, 1, 8, 3, 2, 4, 9, 6, 7]
交换 [2, 1, 8, 3, 5, 4, 9, 6, 7]
2增量
交换 [2, 1, 5, 3, 8, 4, 9, 6, 7]
交换 [2, 1, 5, 3, 8, 4, 7, 6, 9]
交换 [2, 1, 5, 3, 7, 4, 8, 6, 9]
1增量
交换 [1, 2, 5, 3, 7, 4, 8, 6, 9]
交换 [1, 2, 3, 5, 7, 4, 8, 6, 9]
交换 [1, 2, 3, 5, 4, 7, 8, 6, 9]
交换 [1, 2, 3, 4, 5, 7, 8, 6, 9]
交换 [1, 2, 3, 4, 5, 7, 6, 8, 9]
交换 [1, 2, 3, 4, 5, 6, 7, 8, 9]

我们为了减少交换的次数,也可以继续优化,采用移动法的方式也可以减少交换的时间消耗。

视频动画:希尔排序移动法

Code

Result

初始状态 [5, 1, 9, 3, 7, 4, 8, 6, 2]
4增量
移动 [5, 1, 9, 3, 7, 4, 9, 6, 2]
移动 [5, 1, 8, 3, 7, 4, 9, 6, 7]
移动 [5, 1, 8, 3, 5, 4, 9, 6, 7]
2增量
移动 [2, 1, 8, 3, 8, 4, 9, 6, 7]
移动 [2, 1, 5, 3, 8, 4, 9, 6, 9]
移动 [2, 1, 5, 3, 8, 4, 8, 6, 9]
1增量
移动 [2, 2, 5, 3, 7, 4, 8, 6, 9]
移动 [1, 2, 5, 5, 7, 4, 8, 6, 9]
移动 [1, 2, 3, 5, 7, 7, 8, 6, 9]
移动 [1, 2, 3, 5, 5, 7, 8, 6, 9]
移动 [1, 2, 3, 4, 5, 7, 8, 8, 9]
移动 [1, 2, 3, 4, 5, 7, 7, 8, 9]

希尔增量(Shell增量序列)

上面的过程使用的{4,2,1}被称为希尔排序的增量,是逐步折半缩小增量的过程。Shell增量序列的递推公式为:

Shell增量序列的最坏时间复杂度为 O(n^2)。

希尔排序的增量序列的选择有很多种,关于那些增量序列的选择证明和过程比较复杂,就不纠结了。本文即将给出两个案例,它们都可能比Shell增量序列要好:Hibbard增量序列和Sedgewick增量序列。

Hibbard增量序列

Hibbard增量序列的通项公式为:

Hibbard增量序列的递推公式为:

Hibbard 增量序列的最坏时间复杂度为 O(n^(3/2));平均时间复杂度约为 O(n^(5/4))。

Code

得到的,是比length小的最大初始增量。然后在下面代码中只修改获取初始增量的一步就好了,缩减方式和希尔增量一样的,不做修改。

Sedgewick增量序列

Sedgewick增量序列的通项公式为:

Sedgewick 增量序列的最坏时间复杂度为 O(n^(4/3));平均时间复杂度约为 O(n^(7/6))。

初次看这段公式的时候突然有点看不懂了,仔细看看原来是中间还有个小逗号,意思是这两个增量序列的并查集,拿到比length小的最大值(初始增量)就可以了。

Code

这过程有点复杂,因为存在两段公式的关系,不能直接求得初始增量就可以了,还要考虑到缩小增量的下一个数应该用哪个公式。采用的方式创建动态数组,在while(增量<lenght)条件下不断的加入新的元素作为增量,直到比length大才作罢,还要去除掉最有一个已经比length大的增量。

上面解释一下“<<”的运算符,它是转化成二进制然后左移几位的算法,例如9<<1,9转化成二进制1001,然后左移一位,后面补零得10010,转化为十进制就是18,相当于9*2=18。

再例如7<<2,7转化为二进制111,左移两位成11100,转化为十进制就是32,相当于7*(2^2)=32。

”>>”运算符也是同样的,相当于除以2的几次方。

下面代码获取初始增量的也要修改,增量缩减方式也要相应的修改,然后其它的代码不变。

本文介绍了希尔排序的基本思想、优化以及代码的实现,包括后面两个增量序列的选择。增列序列的选择方式对希尔排序也很重要,直接影响到希尔排序的性能。

Guess you like

Origin www.cnblogs.com/wotxdx/p/12053918.html