十大排序算法(原理及代碼實現細節)

本文參考一些書籍啊哈算法,數據結構與算法(清華大學),以及一些網上的博客node

而後動圖也是從網上偷來的(^_^),代碼實現我儘可能用你們容易懂的方式實現ios

數組居多,而後,桶排序(是別人代碼,不過寫的不徹底正確後面會更新),都是學習嘛c++

有誤的地方,還望各位指正,但願對你有幫助(其實很靈活的,在運用上),也不要這樣就知足了算法

多多地運用,會使理解更深的。shell

按上面的順序來吧數組

原理在代碼裏直接上動圖吧數據結構

冒泡排序動圖演示ide

冒泡排序代碼實現學習

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string.h>
 4 using namespace std;  5 const int N = 1e5 + 10;  6 int a[N];  7 //1.比較相鄰的元素。若是第一個比第二個大,就交換它們兩個;  8 //固然若是你是降序那就,第一個比第二個小,就交換它們兩個;  9 //2.對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對, 10 //這樣在最後的元素應該會是最大的數; 11 //3.針對全部的元素重複以上的步驟,除了最後一個; 12 //重複步驟1~3,直到排序完成。
13 void Bubble_sort(int* arr, int len) 14 { 15     for(int i = 1;i < len;i++) 16         for(int j = 1;j <= len - i;j++) 17             if (arr[j] > arr[j + 1])//升序
18  { 19                 int tem = arr[j]; 20                 arr[j] = arr[j + 1]; 21                 arr[j + 1] = tem; 22  } 23 } 24 
25 int main() 26 { 27     int n; 28     while (cin >> n) 29  { 30         for (int i = 1; i <= n; i++) 31             cin >> a[i]; 32  Bubble_sort(a, n); 33         cout << "After Bubble_sort:\n"; 34         for (int i = 1; i <= n; i++) 35             cout << a[i] << " \n"[i == n]; 36  } 37     return 0; 38 }
View Code

 

快速排序動圖演示ui

快速排序代碼實現

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;  4 const int N = 1e5 + 10;  5 int a[N];  6 
 7 //它的基本思想是:經過一趟排序將要排序的數據分割成獨立的兩部分,  8 //其中一部分的全部數據都比另一部分的全部數據都要小,  9 //而後再按此方法對這兩部分數據分別進行快速排序 10 //整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列
11 
12 void quick_sort(int L, int R, int* arr) 13 { 14     if (L >= R) return; 15     int MostL = arr[L]; 16     int i = L, j = R; 17     while (i != j) 18  { 19         //先從最右邊找出小於第一個元素的位置
20         while (arr[j] >= MostL && i < j) 21             --j; 22 
23         //而後從最左側找出大於第一個元素的位置
24         while (arr[i] <= MostL && i < j) 25             ++i; 26 
27         //若是兩個哨兵沒有相遇交換兩者
28         if (i < j) 29  { 30             int tem = arr[i]; 31             arr[i] = arr[j]; 32             arr[j] = tem; 33  } 34  } 35 
36     //將第一個元素放在它應該在的位置
37     arr[L] = arr[i]; 38     arr[i] = MostL; 39 
40     //對於當前哨兵位置的兩側還未有序,遞歸調用便可
41     quick_sort(L, i - 1, arr); 42     quick_sort(i + 1, R, arr); 43 } 44 
45 int main() 46 { 47     int n; 48     while (cin >> n) 49  { 50         for (int i = 1; i <= n; i++) 51             cin >> a[i]; 52 
53         quick_sort(1, n, a); 54         puts("After quick_sort:"); 55         for (int i = 1; i <= n; i++) 56             cout << a[i] << " \n"[i == n]; 57  } 58     return 0; 59 }
View Code

插入排序動圖演示

插入排序代碼實現

 1 //插入排序的工做原理是經過構建有序序列,對於未排序數據,  2 //在已排序序列中從後向前掃描,找到相應位置並插入。  3 //具體算法描述以下:  4 
 5 //1.從第一個元素開始,該元素能夠認爲已經被排序;  6 //2.取出下一個元素,在已經排序的元素序列中從後向前掃描;  7 //3.若是該元素(已排序)大於新元素,將該元素移到下一位置;  8 //4.重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;  9 //5.將新元素插入到該位置後; 10 //6.重複步驟2~5 11 //其實有點像咱們玩撲克理牌的時候,不過咱們能夠觀察,就不會這麼死的步驟了
12 #include<bits/stdc++.h>
13 using namespace std; 14 const int N = 1e4 + 10; 15 
16 int a[N]; 17 
18 void Insertion_sort(int *arr,int len) 19 { 20   for(int i = 1;i < len;i++) 21  { 22      int Invalue = arr[i+1];//要插入的值
23       int curIndex = i;//當前位置 24       //找到插入的位置
25       while(curIndex >= 1 && arr[curIndex] > Invalue) 26  { 27           arr[curIndex + 1] = arr[curIndex]; 28           --curIndex; 29  } 30       //在後面插入值
31       arr[curIndex + 1] = Invalue; 32  } 33 } 34 
35 int main() 36 { 37     int n; 38     while(cin >> n) 39  { 40         for(int i = 1;i <= n;i++) 41             cin >> a[i]; 42  Insertion_sort(a,n); 43         puts("After Insertion_sort:"); 44         for(int i = 1;i <= n;i++) 45             cout << a[i] << " \n"[i == n]; 46  } 47     return 0; 48 }
View Code

希爾排序動圖演示

希爾排序代碼實現

 1 #include<bits/stdc++.h>
 2 using namespace std;  3 const int N = 1e4 + 10;  4 int a[N];  5 
 6 void shell_sort(int *arr,int len)  7 {  8     if(arr == NULL || len <= 0)  9     return; 10     int cnt = 1; 11     for(int gap = len >> 1;gap > 0;gap >>= 1) 12  { 13         if(gap == 2) gap++; 14         cout << "gap = " << gap << endl; 15         for(int i = gap + 1;i <= len;i++) 16  { 17             cout << "i = " << i << endl; 18             int tem = arr[i]; 19             int j = i - gap; 20             while(arr[j] > tem && j >= 1) 21  { 22                 cout << "j = " << j << endl; 23                 arr[j+gap] = arr[j]; 24                 j -= gap; 25  } 26             arr[j+gap] = tem; 27  } 28 // cout << cnt++ << ":\n"; 29 // for(int i = 1;i <= len;i++) 30 // cout << arr[i] << " \n"[i == len];
31  } 32 } 33 //10 34 //49 38 65 97 76 13 27 49 55 04
35 int main() 36 { 37     int n; 38     while(cin >> n) 39  { 40         for(int i = 1;i <= n;i++) 41         cin >> a[i]; 42  shell_sort(a,n); 43 
44         puts("After shell_sort:"); 45         for(int i = 1;i <= n;i++) 46         cout << a[i] << " \n"[i == n]; 47  } 48     return 0; 49 }
View Code

 

選擇排序動態圖演示

選擇排序代碼實現

 1 #include<bits/stdc++.h>
 2 using namespace std;  3 const int N = 1e5 + 10;  4 int a[N];  5 //選擇排序(Selection-sort)是一種簡單直觀的排序算法。它的工做原理  6 //首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,  7 //而後,再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。  8 //以此類推,直到全部元素均排序完畢。
 9 void Selection_sort(int *arr,int len) 10 { 11     for(int i = 1;i < len;i++) 12  { 13         int Minindex = i; 14         for(int j = i + 1;j <= len;j++) 15         if(arr[j] < arr[Minindex]) 16  { 17             Minindex = j; 18  } 19         int tem = arr[Minindex]; 20         arr[Minindex] = arr[i]; 21         arr[i] = tem; 22  } 23 } 24 
25 int main() 26 { 27     int n; 28     while(cin >> n) 29  { 30         for(int i = 1;i <= n;i++) 31             cin >> a[i]; 32  Selection_sort(a,n); 33         puts("After Selection_sort:"); 34         for(int i = 1;i <= n;i++) 35             cout << a[i] << " \n"[i == n]; 36  } 37     return 0; 38 }
View Code

堆排序動圖演示

堆排序代碼實現

 1 //堆排序,是指利用堆這種數據結構所設計的一種排序算法。  2 //堆是一個近似徹底二叉樹的結構,並同時知足堆積的性質:  3 //即子結點的鍵值或索引老是小於(或者大於)它的父節點。  4 //
 5 //步驟:  6 //在最小堆的數據結構中,堆中的最小值老是位於根節點  7 //在優先隊列中使用堆的話堆中的最小值位於根節點 堆中定義如下幾種操做:  8 //最小堆調整:將堆的末端子節點做調整,使得子節點永遠大於父節點  9 //建立最小堆:將堆中的全部數據從新排序  10 //
 11 //堆排序:移除位在第一個數據的根節點,並作最大堆調整的遞歸運算  12 //其實說白了就是一種有某種性質的數據結構  13 //而後你作什麼改動,都必須經過調整來維護該性質
 14 
 15 #include<bits/stdc++.h>
 16 using namespace std;  17 const int N = 1e4 + 10;  18 int h[N];  19 int n;  20 
 21 void Swap(int x,int y)  22 {  23     int tem = h[x];  24     h[x] = h[y];  25     h[y] = tem;  26 }  27 
 28 //傳入一個向下調整的結點編號i
 29 void shiftdown(int i)  30 {  31     int t,flag = 0;//t用於記錄較大值結點編號,flag用於標記是否須要下調整  32     //當i有兒子,且須要調整是進行下面的操做
 33     while(i*2 <= n && !flag )  34  {  35         if(h[i] < h[i*2])//和左兒子比較
 36         t = 2*i;  37         else t = i;  38         //若是有右兒子再比較
 39         if(i*2 + 1 <= n)  40  {  41             if(h[t] < h[i*2 + 1])  42                 t = 2*i + 1;  43  }  44 
 45         if(i != t)  46  {  47  Swap(t,i);  48             i = t;  49  }  50         else flag = 1;  51  }  52 }  53 
 54 //傳入須要向上調整的結點i  55 //void shiftup(int i)  56 //{  57 // int flag = 0;  58 // if(i == 1) return;  59 // while(i != 1 && flag == 0)  60 // {  61 // if(h[i] < h[i/2])  62 // Swap(i,i/2);  63 // else flag = 1;  64 // i = i/2;//更新結點  65 // }  66 //}  67 
 68 //創建最大堆,以後最大元素是h[1]
 69 void creatHeap()  70 {  71     //徹底二叉樹有n/2個非葉結點
 72     for(int i = n/2;i >= 1;i--)  73  shiftdown(i);  74 }  75 
 76 //int deleteMin()  77 //{  78 // int t = h[1];  79 // h[1] = h[n];  80 // n--;  81 // shiftdown(1);  82 // return t;  83 //}
 84 /*
 85 從小到大排序的時候不創建最小堆而創建最大堆。最大堆創建好後,  86 最大的元素在h[ 1]。由於咱們的需求是從小到大排序,  87 但願最大的放在最後。所以咱們將h[1]和h[n]交換,  88 此時h[ n]就是數組中的最大的元素。請注意,交換後還需將h[1]向下調整以保持堆的特性。  89 OK如今最大的元素已經歸位,須要將堆的大小減1即n--,而後再將h[ 1]和h[ n]交換  90 並將h[ 1]向下調整。如此反覆,直到堆的大小變成1爲止。此時數組h中的數就已是排序好的了  91 */
 92 void heap_sort()  93 {  94     while(n > 1)  95  {  96         Swap(1,n);  97         n--;  98         shiftdown(1);  99  } 100 } 101 int main() 102 { 103     int i,num; 104 
105     while(cin >> num) 106  { 107          for(int i = 1;i <= num;i++) 108         cin >> h[i]; 109     n = num; 110  creatHeap(); 111  heap_sort(); 112 
113     for(int i = 1;i <= num;i++) 114         cout << h[i] << " \n"[i == num]; 115  } 116     return 0; 117 }
View Code

歸併排序動圖演示(二路歸併)

歸併排序代碼實現

 1 #include<bits/stdc++.h>
 2 using namespace std;  3 const int N = 1e4 + 10;  4 //該算法的主要思想是對於兩個已經有序的數組進行合併是簡單的  5 //只須要對兩個數組元素大小比較便可  6 //那麼剛開始只需二分數組,分出來的兩個小數組又遞歸地  7 //進行排序,而後有序的兩個小數組就能夠合併爲一個大數組  8 //分治+二分
 9 
10 int a[N],t[N]; 11 
12 void Merge_sort(int *arr,int *T,int l,int r) 13 { 14     //若是隻有一個元素就不須要進行二分了
15     if(r - l >= 1) 16  { 17         int m = l + (r - l)/2; 18 
19         //二分遞歸
20  Merge_sort(arr,T,l,m); 21         Merge_sort(arr,T,m+1,r); 22 
23         int i = l,j = m + 1; 24         int nst = l; 25 
26         //合併兩個有序的小數組
27         while(i <= m || j <= r) 28             if(j > r || (i <= m && arr[i] < arr[j])) 29                 T[nst++] = arr[i++]; 30             else T[nst++] = arr[j++]; 31 
32         for(nst = l;nst <= r;nst++) 33             arr[nst] = T[nst]; 34  } 35 } 36 
37 int main(){ 38 
39     int n; 40     while(cin >> n) 41  { 42         for(int i = 1;i <= n;i++) 43             cin >> a[i]; 44         Merge_sort(a,t,1,n); 45         puts("After Merge_sort:"); 46         for(int i = 1;i <= n;i++) 47             cout << a[i] << " \n"[i == n]; 48  } 49     return 0; 50 }
View Code

計數排序動圖演示

計數排序代碼實現

 1 #include<iostream>
 2 #include<string.h>
 3 #include<cstdio>
 4 using namespace std;  5 
 6 const int N = 1e5 + 10;  7 int a[N],b[N];  8 
 9 //這個算法的侷限性,最大最小值之差太大就不行了,由於數組不可能開的很大
10 void Count_sort(int n, int* A,int *B,int l,int r) 11 { 12     int d = (r - l); 13     for (int i = 0; i <= d; i++) 14         b[i] = 0; 15 
16     for (int i = 1; i <= n; i++) 17         b[a[i] - l]++; 18 } 19 
20 int main() 21 { 22     int n; 23     while (cin >> n) 24  { 25         int r = -1e6,l = 1e6; 26         for (int i = 1; i <= n; i++) 27  { 28             cin >> a[i]; 29             if (a[i] > r) 30                 r = a[i]; 31             if(a[i] < l) 32                 l = a[i]; 33  } 34         int d = r - l; 35  Count_sort(n, a, b, l, r); 36 
37         puts("After Count_sort:"); 38         for (int i = 0; i <= d; i++) 39             for (int j = 1; j <= b[i]; j++) 40                 cout << i + l << " "; 41         puts(""); 42  } 43     return 0; 44 }
View Code

桶排序

桶排序代碼實現

 1 //算法描述:  2 //首先它是創建在計數排序的基礎上  3 //你須要知道數列裏的最大最小值  4 //而後本身定義桶的個數(有些人直接分爲10個桶),而後每一個桶對應一個區間  5 //把每一個數放到對應的區間  6 //每一個桶內部能夠用其餘排序算法來排,  7 //每一個桶排序好以後,因爲桶之間保存的數字大小區間不同  8 //最後合併全部桶就獲得有序序列了  9 //這份代碼是別人寫的,我原本想用一個二位數組寫的, 10 //不過用鏈表寫也不錯,我是理解了他的了,還加了一些註釋 11 //並且這個寫法沒有離散化,致使輸入的數據不能夠是負數 12 //並且桶內的排序至關於插入排序是n^2的複雜度,是不對的,總的複雜度 13 //竟然是n^2,我表示這個不是真的桶排序
14 #include<bits/stdc++.h>
15 using namespace std; 16 const int N = 1e4 + 10; 17 int a[N]; 18 
19 typedef struct node { 20     int key; 21     struct node* next; 22 }KeyNode; 23 
24 void bucket_sort(int keys[], int size, int bucket_size) 25 { 26     KeyNode** bucket_table = (KeyNode**)malloc(bucket_size * sizeof(KeyNode*)); 27 
28     for (int i = 0; i < bucket_size; i++) {    //初始化每一個桶
29         bucket_table[i] = (KeyNode*)malloc(sizeof(KeyNode)); 30         bucket_table[i]->key = 0; 31         bucket_table[i]->next = NULL; 32  } 33 
34     for (int i = 0; i < size; i++) { 35         KeyNode* node = (KeyNode*)malloc(sizeof(KeyNode)); 36         node->key = keys[i]; 37         node->next = NULL; 38 
39         int index = keys[i] / 10;//給數據分類的方法(關係到排序速度,很重要)
40         KeyNode* p = bucket_table[index]; 41         if (p->key == 0) { 42             p->next = node; 43             p->key++; 44  } 45         else { 46             while (p->next != NULL && p->next->key <= node->key) { 47             //新來的就找到本身的位置 48             //這裏選擇類插入排序的方式,實際上是不對的,由於這樣的方式至關與每一個桶內又是 49             //n^2複雜度
50                 p = p->next; 51  } 52             node->next = p->next; 53             p->next = node; 54             (bucket_table[index]->key)++;//這個桶當前數據量加一
55  } 56  } 57 
58     KeyNode* k = NULL; 59     //遍歷每一個桶
60     for (int i = 0; i < bucket_size; i++) { 61         for (k = bucket_table[i]->next; k != NULL; k = k->next) { 62             printf("%d ", k->key); 63  } 64  } 65 } 66 
67 int main() 68 { 69     int n; 70     while(cin >> n) 71  { 72         for(int i = 0;i < n;i++) 73         cin >> a[i]; 74         puts("After bucket_sort:"); 75         bucket_sort(a, n, 10); 76  } 77     return 0; 78 }
View Code

基數排序動態圖演示

基數排序代碼實現

 1 #include<bits/stdc++.h>
 2 using namespace std;  3 int a[100];  4 int n, ma;  5 void work(int cur) {  6     int b[10] = { 0 };  7     int c[100];  8     for (int i = 0; i < n; i++)  9         b[(a[i] / cur) % 10]++; 10 
11     for (int i = 1; i < 10; i++) 12         b[i] += b[i - 1];//前綴和,b[i]表示當前位小於等於i的數字有多少個 13 
14 // 下面這個地方尤其關鍵爲啥從n - 1開始,而不是從0開始 15 // 由於是從最低位開始調整位置的,前面已經在低位排好了,若是從0開始 16 // 若是當前位兩個數字爲0,那麼他們的相對位置應該不變 17 // 從0開始就反了,順序錯了
18 
19     for (int i = n - 1; i >= 0; i--) 20  { 21         //精髓所在
22         c[b[(a[i] / cur) % 10] - 1] = a[i]; 23         b[(a[i] / cur) % 10]--; 24  } 25 
26     //複製一份給原始數據
27     for (int i = 0; i < n; i++) 28         a[i] = c[i]; 29 } 30 
31 void radix_sort() { 32     //1表明各位的比較,10表明十位的比較,依此類推
33     for (int i = 1; ma / i > 0; i *= 10) 34  work(i); 35 } 36 
37 int main() { 38 
39     while (cin >> n) { 40         ma = 0; 41         for (int i = 0; i < n; i++) { 42             cin >> a[i]; 43             if(a[i] > ma) ma = a[i]; 44  } 45         puts("before sort"); 46         for (int i = 0; i < n; i++) 47             cout << a[i] << ' '; 48         puts(""); 49  radix_sort(); 50         puts("after radix_sort"); 51         for (int i = 0; i < n; i++) 52             cout << a[i] << ' '; 53         puts(""); 54  } 55     return 0; 56 }
View Code

 

最後各排序算法對比

相關文章
相關標籤/搜索