希尔排序

来源:互联网 发布:mac safari历史记录 编辑:程序博客网 时间:2024/06/05 19:54
希尔排序:
  设待排序元素有n个,首先取一个整数gap<n作为间隔,将全部元素分为gap组,所有距离为gap的元素都在同一个组里,然后对每一个组都进行插入排序。然后缩小增量,直到gap==1的时候整个序列都会变成有序的。

例如:对{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }进行升序排列。


具体代码实现:
[cpp] view plain copy
  1. void ShellSort(int *a, int len)     //插入排序的变形,通过预排序使得元素大致有序,再通过插入排序使得数组整体有序  
  2. {  
  3.     int gap = len;           //增量  
  4.     while (gap > 1)  
  5.     {  
  6.         gap = gap / 3 + 1;              //增量要减小,直到增减为1  
  7.         for (int index = gap; index<len;++index)  
  8.         {  
  9.             int pos = index-gap;          //有序区的最后一个元素  
  10.             int tmp = a[index];  
  11.             while (pos > 0 && a[pos] > tmp)  
  12.             {  
  13.                 a[pos + gap] = a[pos];  
  14.                 pos -= gap;  
  15.             }  
  16.             a[pos + gap] = tmp;  
  17.         }  
  18.     }  
  19. }  


for(intindex = gap; index<len;++index)
  在这条语句中,index<len,++index。因为在进行插入排序的时候先是红色组中第二个元素排序,接下来是蓝色组中第二个元素排序,再下来是紫色组中第二个元素排序。这三个组轮流进行排序,并不是先把一组排完再去排另一组。

  进行希尔排序的时候gap的选取很重,决定了排序效率的高低,一般最开始设置gap为要排序的元素的个数,接下来gap按照gap=gap/3+1的趋势进行变化。希尔排序的平均时间复杂度是在n^1.25到1.6n^1.25的范围内。

希尔排序与插入排序的比较:

  插入排序在什么情况下效率最高呢???
  如果当要排序的序列大致上接近于有序的时候,插入排序的效率最高,基本上接近O(N)。因为当数据基本上接近于有序的时候,元素向有序区插入的时候比较的次数会很少,同样有序区元素向后移动的次数也是很少的。

  那么插入排序在什么情况下的效率最低呢???
  如果当要排序的序列大致上接近于逆序的时候,插入排序的效率最低,基本上接近与O(N*N)。因为这时候每向有序区插入一个元素的时候,假设最极端的情况下要比较和移动的次数就是有序区的长度。这时候插入排序的效率就会很低。

  针对于插入排序的最坏的情况,希尔排序对它进行了优化,希尔排序先对这组数据进行预排序(就是gap不为1的时候进行的分组排序),通过预排序就能将这组数据快速的接近于有序,这时候再使用插入排序效率就会提升上去。所以希尔排序的增量选择就很重要,增量大额话会起不到预排序的效果,增量小的话效率又会降低。

  如果当一组数据接近的有序的话,我们优先使用插入排序,效率高。如果当一组数据接近于逆序的话,我们使用希尔排序会更优。插入情况最好的情况就是希尔排序最坏的情况,因为这时候希尔排序的预排序起不到作用。插入排序最坏的情况则是希尔排序最高的情况,因为这时候预排序的效果是非常明显的。