在路上

不是专业,只会通俗

导航

排序算法_希尔排序

一、算法描述

  1. 先取一个小于n的整数d1作为第一个增量,把全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。
  2. 先在各组内进行直接插人排序;
  3. 取第二个增量d2<d1重复上述的分组和排序,
  4. 直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

二、图示

   待排序数组[13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10],如果我们以步长为5开始进行排序:

    13 14 94 33 82
    25 59 94 65 23
    45 27 73 25 39
    10

   排序后:

    10 14 73 25 23
    13 27 94 33 39
    25 59 94 65 82
    45

   单行来读取数据时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]

   这时10已经移至正确位置了,然后再以3为步长进行排序:

    10 14 73
    25 23 13
    27 94 33
    39 25 59
    94 65 82
    45

   排序之后变为:

    10 14 13
    25 23 33
    27 25 59
    39 65 73
    45 94 82
    94
    最后以1步长进行排序(此时就是简单的插入排序了)。

三、性能描述

    数据结构 :数组

  最差时间复杂度 :O(nlog2n)

  最优时间复杂度 :O(n)

  平均时间复杂度 :根据步长序列的不同而不同

  最差空间复杂度 :总共O(n)

四、总结

  关键在于步长序列的选择:

    已知的最好步长序列由Marcin Ciura设计(1,4,10,23,57,132,301,701,1750,…)
  这项研究也表明“比较在希尔排序中是最主要的操作,而不是交换。”用这样步长序列的希尔排序比插入排序和堆排序都要快,
  甚至在小数组中比快速排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。
    另一个在大数组中表现优异的步长序列是(斐波那契数列除去0和1将剩余的数以黄金分割比的两倍的幂进行运算得到的数列):
 (1, 9, 34, 182, 836, 4025, 19001, 90358, 428481, 2034035, 9651787, 45806244, 217378076, 1031612713, …)

五、C语言实现代码

View Code
 1 #include <stdio.h>
 2  
 3 int main()
 4 {
 5      const int n = 5;
 6      int i, j, temp; 
 7      int gap = 0;
 8      int a[] = {5, 4, 3, 2, 1}; 
 9      while (gap<=n)
10      {
11           gap = gap * 3 + 1;
12      } 
13      while (gap > 0) 
14      {
15          for ( i = gap; i < n; i++ )
16          {
17              j = i - gap;
18              temp = a[i];             
19              while (( j >= 0 ) && ( a[j] > temp ))
20              {
21                  a[j + gap] = a[j];
22                  j = j - gap;
23              }
24              a[j + gap] = temp;
25          }
26          gap = ( gap - 1 ) / 3;
27      }    
28  }

 

 

 参考文档:

  1. http://zh.wikipedia.org/wiki/希尔排序

posted on 2013-01-17 11:50  OnRoad_  阅读(271)  评论(0编辑  收藏  举报