本文參考一些書籍啊哈算法,數據結構與算法(清華大學),以及一些網上的博客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 }
快速排序動圖演示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 }
插入排序動圖演示
插入排序代碼實現
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 }
希爾排序動圖演示
希爾排序代碼實現
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 }
選擇排序動態圖演示
選擇排序代碼實現
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 }
堆排序動圖演示
堆排序代碼實現
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 }
歸併排序動圖演示(二路歸併)
歸併排序代碼實現
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 }
計數排序動圖演示
計數排序代碼實現
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 }
桶排序
桶排序代碼實現
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 }
基數排序動態圖演示
基數排序代碼實現
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 }
最後各排序算法對比