希爾排序數組
這裏內部用了直接插入的方法;優化
1 void HashSort(int a[],int n){ 2 int i,j,temp; 3 int gap=n; 4 do{ 5 gap=gap/3+1; 6 for(i=gap;i<n;i++){ 7 if(a[i]<a[i-gap]){ 8 temp=a[i]; 9 //注:這裏要手動檢測越界問題 10 for(j=i-gap;a[j]>temp && j>=0;j-=gap) 11 a[j+gap]=a[j]; 12 a[j+gap]=temp; 13 } 14 } 15 }while(gap>1); 16 }
堆排序ui
對選擇排序的改進,每次找最小值的時候沒有利用上次的結果,因此將記錄所有存入徹底二叉樹中,構造大頂堆或小頂堆,每次取一個極值,這樣就能夠利用前一次的比較結果了spa
徹底二叉樹的特色:code
其實也不須要構造二叉樹,須要將數組放棄0下標位置用其餘下標對應相應徹底二叉樹結點便可blog
1 //i:規範位置;n:堆的結點樹 2 void HeapAdjust(int a[],int i,int n){ 3 int k=a[i],j=i; 4 for(j*=2;j<n;j*=2){ 5 //找到子結點中較大的那個 6 if(j+1<n && a[j+1]>a[j]) 7 j++; 8 //較大的子結點小於根節點就退出 9 if(k>=a[j]) 10 break; 11 //較大的子結點覆蓋雙親結點 12 //覆蓋後,較大子結點這個位置就是新的規範位置 13 a[i]=a[j]; 14 i=j; 15 } 16 //退出循環後就說明,位置是已經規範,直接將規範值賦到該處便可 17 a[i]=k; 18 } 19 20 void HeapSort(int a[],int n){ 21 int i,k; 22 //構建大頂堆 23 for(i=n/2;i>0;i--){ 24 HeapAdjust(a,i,n); 25 } 26 //循環將頂部最大值與尾部交換 27 for(;n>1;n--){ 28 k=a[1]; 29 a[1]=a[n-1]; 30 a[n-1]=k; 31 //交換後恢復大頂堆 32 HeapAdjust(a,1,n-1); 33 } 34 }
快速排序排序
冒泡排序有類似的原理遞歸
1 int partition(int a[],int low,int high){ 2 //令0下標位置記錄爲標準數 3 int sign=a[low]; 4 while(low<high){ 5 //注:下面兩循環中若與標誌爲相等也交換的話,那麼將死循環,這個與標誌數相等的數將和標準數互相一直換下去 6 //比標準數大的放左邊 7 //由於上面的標誌數直接取了low位置,因此下面直接覆蓋便可,不須要交換,退出循環後直接將標誌數賦在應有位置 8 while(low<high && a[high]>=sign) 9 high--; 10 a[low]=a[high]; 11 //比標準數小的放右邊 12 while(low<high && a[low]<=sign) 13 low++; 14 a[high]=a[low]; 15 } 16 //退出循環以後low=high,且這個位置存放的就是標準數 17 a[low]=sign; 18 return low; 19 } 20 21 void QSort(int a[],int low,int high){ 22 int sign; 23 if(low<high){ 24 sign=partition(a,low,high); 25 QSort(a,low,sign-1); 26 QSort(a,sign+1,high); 27 } 28 } 29 30 void QuickSort(int a[],int n){ 31 QSort(a,0,n-1); 32 }
其實快速排序法適用於規模較大的排序,而直接插入法則對規模較小的排序效率較高(長度分界爲7),因此在快速排序中對長度小於7的排序段用直接插入法就能夠進一步優化快速排序it
1 void QSort(int a[],int low,int high){ 2 int sign; 3 if((high-low)>7){ 4 sign=partition(a,low,high); 5 QSort(a,low,sign-1); 6 QSort(a,sign+1,high); 7 }else{ 8 InsertSort(k+low,high-low+1); 9 } 10 }
固然,快速排序法中有兩次遞歸調用,也是能夠利用僞遞歸的方法對其進行更深一步的優化io