標籤:ext col 使用 font http 序列 分享 個數 排序
二、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排序