1. 程式人生 > >排序算法——Shell排序

排序算法——Shell排序

技術 證明 增量 sub 數組大小 blog cto 希爾 一次

二、Shell排序

  Shell排序也叫“縮減增量排序”(disminishing increment sort),基於插入排序進行。

  Shell建議的序列是一種常用但不理想的增量序列:1,...,N/8,N/4,N/2 (ht=N/2,hk=hk+1/2)

void shellSort(vector<int> &a)
{
  for(int gap=a.size()/2;gap>0;gap/=2)
  {
//對於hk(即gap),hk+1,...,N-1中的每個位置i,把位置i上的元素放到i,i-hk,i-2hk......中的正確位置上
for(int i=gap;i<a.size();++i) {
int tmp=a[i]; int j=i; for(;j>=gap&&tmp<a[j-gap];j-=gap) { a[j]=a[j-gap]; } a[j]=tmp; } }

思路:

  通過比較相隔一定間隔(hk)的元素來工作,各趟比較所用的距離隨算法的進行而減小,直到只比較相鄰元素的最後一趟排序為止。

步驟:

  使用一個增量序列h1,h2,...ht,只要h1=1,任何增量序列都是可行的。

  1)先將待排元素序列分成若幹個子序列(每個子序列由相隔某個“增量”的元素組成),分別進行插入排序;

    在使用增量hk的一趟排序後,對每個i,都有a[i]≤a[i+hk],即所有相隔hk的元素都被排序,此時稱文件是hk排序的;

一趟hk排序的作用,即對hk個獨立子數組執行一次插入排序。

希爾排序的一個重要性質——一個hk排序的文件保持它的hk排序性,不會被後面的各趟排序打破。

  2)依次縮減增量,再重復步驟 1)進行排序;

  3)直到hk為1時,再對全體元素進行一次直接插入排序(insertion sort);

  技術分享圖片

  待排數組為{34,8,64,51,32,21,5},數組大小N=7,則增量序列為1,3。

  hk

=3時,對{34,51,5},{8,32},{64,21}這3個子數組進行插入排序(其中,每個數組元素相隔3),hk=3 排序後的數組為{5,8,21,34,32,64,51}。

  增量縮減為hk=1,即對全體元素進行一次插入排序,排序完成,得到最終的有序數組為 {5,8,21,32,34,51,64}。

時間復雜度:

  Shell排序的運行時間依賴於增量序列的選擇,證明較為復雜。

  使用Shell建議的增量序列:1,...,N/8,N/4,N/2 (ht=N/2,hk=hk+1/2),最壞情形是Θ(N2

  使用Hibbard增量序列:1,3,7,......,2k-1,最壞情形為Θ(N3/2).

適用情形:

  普通的插入排序適用於非常少量的輸入。

  希爾排序在適量輸入時是上佳選擇,對適當的增量序列,性能極好,且代碼少,易寫。

排序算法——Shell排序