希爾排序算法思想
希爾排序的實質就是分組插入排序,該方法又稱縮小增量排序.
基本思想是:先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然后依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。
代碼
要求
對于一個int數組,請編寫一個希爾排序算法,對數組元素排序。
給定一個int數組A及數組的大小n,請返回排序后的數組。保證元素小于等于2000。
測試樣例:
[1,2,3,5,2,3],6
[1,2,2,3,3,5]
程序一(好理解,但是比較麻煩)
class ShellSort {
public:int* shellSort(int* A, int n) {// write code hereif(n<2){return A;}int count = 2, argument; //count:一個子序列中的元素數,argument:增量,也是子序列的數量while(count<=n){argument = n/count;for(int i=0;i<argument;i++){sortArgu(A,n,i,argument); //這里把一次插入排序過程抽出來}count *=2;}return A;}private:void sortArgu(int* A, int n, int begin, int argu){int temp, last, current; //begin:子序列的起始元素current = begin+argu;// current: 一次插入排序中,當前要排序的元素,也就是無序部分的第一個元素while(current<n){last = current;while(last-argu>=begin){if(A[last]<A[last-argu]){temp = A[last];A[last] = A[last-argu];A[last-argu] = temp;}last -= argu;}current +=argu;}}
};
程序二
class ShellSort {
public:int* shellSort(int* A, int n) {// write code hereif(n<2){return A;}int temp,j;for(int step=n/2; step>0; step/=2){ //這里控制增量,最小值時為1,也就是一次普通的插入排序for(int i=step; i<n; i++){ //重點是在這里!!!這里是對第一個增量后的元素進行插入排序(插入排序時起始有序序列為1),沒有把一個子序列單獨抽出來進行排序(區別程序一),而是依次對第一個增量后的元素在其所屬的子序列中進行插入排序for(j=i; j>=step; j-=step){if(A[j]<A[j-step]){temp = A[j]; //這里還可以進一步優化,詳見程序三A[j] = A[j-step];A[j-step] = temp;}else{break;}}} }return A;}};
程序三
class ShellSort {
public:int* shellSort(int* A, int n) {// write code hereif(n<2){return A;}int temp,j;for(int step=n/2; step>0; step/=2){for(int i=step; i<n; i++){ //思想:找到待排序元素在有序部分的位置,然后插入,而不是每一次都把待排序元素與前一個元素交換位置。temp = A[i]; //記錄下待排序元素for(j=i; j>=step; j-=step){if(temp<A[j-step]){ //有序部分的每一個元素都與待排序元素比較A[j]=A[j-step]; //滿足上述條件,則元素后移}else{break;}}A[j]=temp; //將待排序元素插入合適位置} }return A;}};
參考
1 白話經典算法系列之三 希爾排序的實現