前言:算法
本人自接觸算法近2年以來,在不斷學習中越多地發覺各類算法中的美妙。之因此在這方面過多的投入,主要仍是基於自身對高級程序設計的熱愛,對數學的沉迷。回想一下,前後也曾參加過ACM大大小小的校級賽、區域賽。沒什麼驚天動地的獎項,最好的名次也就省三等獎。如今做爲第一篇算法總結就拿常見的排序算法以我我的的理解,以及代碼實現跟你們簡單分享一下(排序算法若是一一羅列的話,不下十種。曾在圖書館的舊書架上看過一本近900頁的書,內容就是專門介紹排序算法)。shell
選擇排序(select)數組
選擇排序比較容易理解,每一次日後遍歷都是爲了尋找「最小值」的下標。N次遍歷,時間複雜度爲:O(n^2)數據結構
冒泡排序(bubble)學習
冒泡排序也比較形象,理解爲大氣泡不斷下沉,小氣泡往上冒。一樣日後進行n次遍歷,時間複雜度爲:O(n^2)。跟選擇排序的區別:選擇排序屬於穩定排序,從初始狀態到排序完成過程當中的每一次遍歷各元素先後位置「相對穩定」。並且,冒泡排序每一輪遍歷可能產生屢次交換swap(),而選擇排序固定每一輪的遍歷都只進行一次交換swap()操做。測試
插入排序(insert)ui
插入排序能夠理解爲對撲克牌排序,原先拿到一手雜亂的牌,經過「插入」將全部牌排好序。spa
通常的插入排序時間複雜度一樣是:O(n^2),進行具體樣例測試時跟樣例數據的初始順序有關。設計
希爾排序(shell)code
希爾排序爲進化版的插入排序,只由於其基於插入排序的思想上,加入步長」step」。通常讀者可能不知道希爾排序應用到大量數據的排序的高效,據研究的學者代表通常狀況下希爾排序的排序時間複雜度下降爲O(n^(3/2))
歸併排序(merge)
歸併排序是基於遞歸的思想進行的一種時間複雜度爲:O(N*lgN)排序算法,不過其附加O(n)的空間輔助代價。理解好歸併排序後能夠將其遞歸思想擴展應用到數列逆序數的求解問題上,這裏再也不展開。
快速排序(quick)
快速排序有多種實現方式,一樣是利用遞歸的思想,不斷將問題劃分爲具備相同性質的子問題進行求解。實現快速排序算法的平均時間複雜度爲:O(N*lgN);快排的O(N*lgN)算法一樣經過拓展能夠用於求無序數列的「第K大」元素。
堆排序(heap)
二叉堆,簡稱堆(heap)。一種很是奇妙的數據結構,是本人接觸過的算法當中最驚歎的算法之一,僅僅利用數組就能夠實現。在堆排序中,咱們通常採用大根堆,時間複雜度O(N*lgN),排序效果較快排穩定,並且也不須要額外的空間存儲代價。
代碼實現部分(C/C++),本程序建議在codeblocks這款界面比較友好的IDE測試。
1 /* 2 *排序算法彙總(C/C++實現) 3 */ 4 #include <cstdio> 5 #include <cstring> 6 //#define swap(x,y){x^=y;y^=x;x^=y;} 7 #define swap(x,y){int temp=x;x=y;y=temp;} 8 9 const int N = 10; 10 11 void selectSort(int *a,int n){ 12 for(int i=0;i<n;i++){ 13 int min=i; 14 for(int j=i+1;j<n;j++){ 15 if(a[j]<a[min]) min=j; 16 } 17 swap(a[i],a[min]); 18 } 19 } 20 //something error! 21 void bubbleSort(int *a,int n){ 22 for(int i=0;i<n;i++){ 23 for(int j=i;j<n;j++) 24 if(a[j]<a[i]) swap(a[i],a[j]); 25 } 26 } 27 void insertSort(int *a,int n){ 28 for(int i=1;i<n;i++){ 29 for(int j=i;j-1>=0&&a[j]<a[j-1];j--){ 30 swap(a[j],a[j-1]); 31 } 32 } 33 } 34 void shellSort(int *a,int n){ 35 //設定劃分步長step 36 int step=3; 37 int h=1; 38 while(h*step<n) h=h*step + 1; 39 while(h>=1){ 40 for(int i=1;i<n;i++){ 41 for(int j=i;j-h>=0&&a[j]<a[j-h];j-=h) 42 swap(a[j],a[j-h]); 43 } 44 h /= step; 45 } 46 } 47 void mergeSort(int *a,int p,int q,int *T){ 48 //[p,q)左閉右開 49 if(p+1>=q) return; 50 int m = p+(q-p)/2; 51 //printf("m=%d\n",m); 52 mergeSort(a,p,m,T); 53 mergeSort(a,m,q,T); 54 for(int i=p,x=p,y=m;i<q;){ 55 if( x<m && y<q && a[x]<a[y] || y>=q) T[i++]=a[x++]; 56 else T[i++]=a[y++]; 57 } 58 for(int i=p;i<q;i++) 59 a[i] = T[i]; 60 } 61 void qSort(int *a,int p,int q){ 62 if(p>=q) return ; 63 int i=p-1; 64 for(int j=p;j<q;j++) if(a[j]<a[q]){ 65 i=i+1; 66 swap(a[i],a[j]); 67 } 68 i=i+1; 69 swap(a[i],a[q]); 70 71 qSort(a,p,i-1); 72 qSort(a,i+1,q); 73 } 74 75 void sink(int *a,int n,int k){ 76 while(2*k<=n){ 77 int j=2*k; 78 if(j<n && a[j]<a[j+1]) j++; 79 //if(a[j]<a[j+1]) j=j+1; 80 if(a[k] > a[j]) break; 81 swap(a[j],a[k]); 82 k = j; 83 } 84 } 85 void heapSort(int *a,int n){ 86 for(int k=n/2;k>=1;k--) 87 sink(a,n,k); 88 for(;n>1;){ 89 swap(a[1],a[n]); 90 n--; 91 sink(a,n,1); 92 } 93 } 94 void pt(int *a,int s,int n){ 95 for(int i=s;i<n;i++) 96 printf("%d ",a[i]); 97 printf("\n"); 98 } 99 int main(){ 100 //printf("Hello world!\n"); 101 int a[N]={2,1,-1,123,0,1,21,7,-10,1}; 102 int b[N+1]={-999,2,1,-1,123,0,1,21,7,-10,1}; 103 int T[N]; 104 int c; 105 printf("請選擇一種排序算法:\n 1.選擇排序\n 2.冒泡排序\n 3.插入排序\n 4.希爾排序\n 5.歸併排序\n 6.快速排序\n 7.堆排序\n ----> "); 106 scanf("%d",&c); 107 switch(c){ 108 case 1: 109 selectSort(a,N); 110 break; 111 case 2: 112 bubbleSort(a,N); 113 break; 114 case 3: 115 insertSort(a,N); 116 break; 117 case 4: 118 shellSort(a,N); 119 break; 120 case 5: 121 mergeSort(a,0,N,T); 122 break; 123 case 6: 124 qSort(a,0,N-1); 125 break; 126 case 7: 127 heapSort(b,N); 128 break; 129 default: 130 printf("選擇無效!"); 131 return 1; 132 } 133 printf("輸出結果:\n"); 134 if(c==7) 135 pt(b,1,N+1); 136 else 137 pt(a,0,N); 138 139 return 0; 140 }
測試演示:
結語:
以上排序算法尚不能涵蓋全部排序算法,好比基數排序,字符串排序等。本次排序算法分享內容就此打住,日後將持續更新。。。(因水平有限錯漏在所不免,望各朋友不吝批評指正^_^)