希尔排序

来源:互联网 发布:上海大剧院 座位 知乎 编辑:程序博客网 时间:2024/06/08 08:31

1.说明一点问题

  • -我们已经在上上篇博客中证明了:通过交换相邻元素进行的任何排序算法平均需要Ω( n ^ 2 )时间。

  • 这个定理对一整类只进行交换相邻元素还包括未发现的算法适用。这个下界告诉我们,为使一个算法突破这个下界,我们就不可仅交换相邻的元素,而是要通过交换相距较远的元素,使得一次交换,不再消除一个逆序,而是有可能通过一次交换,消除多个逆序。

2.算法基本思想

  • 算法使数组中任意间隔为h的元素都是有序的(满足这一条件对的数组称为 - h有序数组)。一个h有序数组就是h个互相独立的有序数组编制在一起组成的一个数组。
    (图片中用的是w表示h,且假设n / w 为整数)
  • 这里写图片描述
  • 我们要做的无非是将n个数分为w的子数组(图中每列)。我们每次对每列排序,这样可以使得数组中任意间隔为h的元素都是有序的。再减少h的值,进行同样的操作。因此我们不难看出,矩阵宽度随着h的减少也逐渐缩短。直到h减少为1,此时上图只有一列,我们要对这一列进行排序(相邻的元素间),进行的进行最后一次排序。最后一次排序,实质上依旧为”交换”相邻元素的算法,但得益于先前的排序过程,已经减少了一定数量的逆序,使得这趟排序只用进行较少次数的”交换”操作。

3.算法基本实现

void Shell_Sort( int A[] ,int N){    int h = 1;    int temp;    int i , j ;    while( h < N / 3 )        h = 3 * h + 1;/* 1 4 13 40 121 364 ....*/    while( h >= 1 )    {        for( i = h; i < N; i ++ )        {            for( j = i ; j >= h && A[ j ] < A[ j - h ]; j -=  h)            {                temp = A[ j ];                A[ j ] = A[ j - h ];                A[ j - h ] = temp;            }        }            h = h / 3;    }} 

4.算法分析

< 1 >

  • 正如前文提到的一样, 我们只需能完成对每一列的排序即可,(我们每次只需对很小的子数组排序,却使得有可能消除多个逆序),我们不必过于深究每次采用什么排序方法。我们要在意的是算法的主体框架已经固定,唯一能够让我们选择的无非是h如何变化。然而得益于插入排序的一些性质,如当待排序已基本有序情况下,插入排序可以达到线性时间,这与“希尔排序不断使待排元素有序”这一思想仿佛是地造天设的一对。
    ( 上面算法的实现使用了序列1 / 2 ( 3 ^ k - 1 ),从N / 3 开始递减至 1,我们将这个序列称为 “递增序列”。

    因此我们选择的递增序列成为影响希尔排序的主要因素。

    • 另一个希尔排序依赖的重要定理是:
当一个"h 有序"的数组按照增幅k排序后,仍是“h有序”的.
  • 希尔排序更高效的原因是它权衡了子数组的规模和有序性。

< 2 >

  • 使用希尔增量的最坏情况
    递增序列成为影响希尔排序的主要因素,为我们不难得到一个序列,来分析最坏情况下希尔排序的表现。
    • 希尔增量是希尔排序中希尔给出的增量序列ht = n / 2, h[k] = h[k+1] / 2,即{n/2, (n / 2)/2, …, 1}。
    • 我们给定一个数组(大小为N且假设N为2的幂)作为输入,他的偶数位置上有N/2个同为最大值的数(N/2个相同的数),奇数位置上有N/2个同为最小值的数(N/2个相同的数)。由于除最后的那个增量是外其余增量均为偶数,因此但我们进行最后一次排序前,数组不会发生变化。同为最大值的N/2个数依旧处于偶数位置上,同为最小值的N/2个数依旧处于奇数位置上。这使得整个数组中逆序对数没有发生变化。将第 i 个(i <= N/ 2 )最小在位置2 * i - 1 上,我们需要在数组中移动 i - 1 个间隔(如第N/2个最小的数,在位置N - 1上,要它移动到 N /2号位置上 ).这样我们仅仅将N / 2 个最小的元素移动到正确位置上,我们就需要∑ (1 →N / 2 ) (i - 1 ) = Ω( N ^ 2 ).
    • 带有增量h[ k ] 的一趟排序由h[ k ]个N / h[ k ]个插入排序组成,插入排序时间复杂度为二次的,因此一趟排序总开销是Ο( h[ k ] * ((N / h[ k ]) ^2))= Ο( N ^ 2 / h[ k ] ).对每趟排序求和的得到一个几何级数(详见《数据结构与算法分析:C语言描述》),我们可以得到总界Ο(N ^2 )。
    • 综上我们可以得到使用希尔增量时希尔排序最坏情况下运行时间为Θ(N ^2 ).

(上面关于增量序列的选择问题稍微比较简短,希望以后能继续学到更多知识,以完善这篇博客,也希望各位能继续深入理解。)

原创粉丝点击