《C++数据结构原理与经典问题求解》―10种排序算法的实现2

C++数据结构原理与经典问题求解
 

 
编著者:左飞
出版社:电子工业出版社
ISBN号: 978-7-121-07321-2
丛书名:C/C++开发专家
出版日期: 2008-10
字数:870.4千字
页码:548
开本:16
http://www.phei.com.cn/bookshop/bookinfo.asp?bookcode=TP073210&booktype=main
http://product.dangdang.com/product.aspx?product_id=20385620
 
第11章 排序
 
11.2.3 希尔排序 
      
     希尔排序又称为缩小增量排序,因D.L.Shell于1959年提出而得名。该算法先取一个小于数据表中元素个数n的整数gap,并以此作为第一个间隔,将数据表分为gap个子序列,所有距离为gap的对象放在同一个子序列中。也就把数据表中的全部元素分成了gap个组。而所有距离为gap的倍数的记录会被放在同一个组中。分组确定后,就在每一个小组中分别进行直接插入排序。局部排序完成后就缩小间隔gap,并重复上述步骤,直至取到gap = 1时,完成最后一次直接插入排序。来简单地分析一下这个算法为什么会起作用。显然开始时间隔gap较大,因而各组中的数据量相对较小,因而至少在最开始的时候算法是非常快的。随着算法的进行,间隔gap的取值变得越来越小,因此子序列中元素个数也就越来越多,所以排序工作可能会变慢。但是由于前面已经完成了部分排序工作,因而在很大程度上减轻了后期的工作量,致使最终总体的排序速度还是比较快的。这就是这种所谓“缩小增量排序”方法的设计原理所在。
 
还需要说明的是间隔gap的取法可能有很多种。后面的例子中所使用的取法是(gap = gap/2,此处公式无法显示)。最初Shell在设计算法时提出来的取法是(gap = gap/2,此处公式无法显示)。后来大名鼎鼎的Knuth提出取。也有学者认为取互质的gap为好。但到目前为止无论哪种取法都尚未得到严密的数学证明。
 
下面来举例说明希尔排序是如何工作的。假设有一个数据表如图11-3所示。
 
 
   图11-3 数据表

显然,数据表中共有6个元素。那么第一轮操作可以取 ,于是将数据表中的元素分为三组,每组两个元素。分别对这三组进行直接插入排序,这个过程如图11-4所示。
 
 
 图11-4 希尔排序示例第一轮操作

在第二轮操作时,首先进行间隔缩小,取得 ,则将第一轮处理得到的数据表划分为间隔为2的两组,同理对其进行直接插入排序。这个过程如图11-5所示。
 
 
 图11-5 希尔排序示例第二轮操作

接下来进行第三轮gap=1时的操作。易见第二轮操作结束,数据表已经有序,因此事实上第三轮所作的工作就非常之少了,这里就不再赘述第三轮的操作过程了。

下面给出希尔排序算法的示例代码:

 
//希尔排序
#ifndef SHELLSORT_H
#define SHELLSORT_H
#include <vector>
using namespace std;
class ShellSort
{
private:
 int len;
 vector<int> list;
public:
 ShellSort(vector<int> _list, int _len);
 void shell_sort();
 void out();
};
#endif
#include "ShellSort.h"
#include <iostream>
using namespace std;
ShellSort::ShellSort(vector<int> _list, int _len)
{
 for (int i=0; i<_len; i++) list.push_back(_list[i]);
 this->len = _len;
}
//3 希尔排序------------------------------------------------------------
void ShellSort::shell_sort()
{
 int insertNum;
 int gap = len/2;          //初始增量
 while (gap)           //当gap>=1
 { 
  for (int i=gap; i<len; i++)      //对gap间隔子序列进行插入排序
  {
   insertNum = list[i];            //待插入元素
   int j = i;           
   while (j>=gap && insertNum<list[j-gap]) 
   {        //寻找插入位置
    list[j] = list[j-gap];
    j -= gap;
   }
   list[j] = insertNum;      //插入
  }
  
  gap = gap/2;         //缩小增量
 }
 
}
 
 
void ShellSort::out()
{
 for (int i=0; i<len; i++)
 {
  cout<< list[i] << " ";
  if ((i+1)%18 == 0) cout<<endl;
 }
 cout <<endl;
}
 
 

分析希尔排序的时间复杂度是一件十分困难的工作,特别在间隔选取方式发生变化的情况下,尚不能给出一个定量结果。到目前为止,关于间隔值选取方式与关键码比较次数和元素移动过程之间的关系不存在理论上的证明结果。最后需要说明的希尔排序是一个不稳定的排序方法。
----------------------------------------------------

你可能感兴趣的:(数据结构,算法,职场,希尔排序,休闲)