1.快速排序演算法
最壞時間複雜度為O(n*n), 這與基數的選擇有關, 期望的已耗用時間為O(nlgn),且O(nlgn)記號中隱含的常數因子很小。另外,它還能夠進行就地排序.
快速排序邏輯:
1、先從數組中取出一個數作為基數,基數的選擇對排序效率的影響很大, 一般隨機來選擇.
2、分區,將比這個基數小的數全部放到它的左邊,比基數大的數全部放到其右邊
3、對左右兩個區間重複第二步,直到每個區間只有一個數
#include <iostream>#include <cstdlib>void swap (int& a, int& b){ int tmp = a; a = b; b = tmp;}int partion(int a[], int f, int e){ int i = f; for (int j = f; j < e; j++) { if (a[j] < a[f]) { swap (a[++i], a[j]); } } swap (a[i], a[f]); return i;}void quickSort(int a[], int f, int e){ if (f < e) { int i = f + rand() % (e - f); swap(a[f], a[i]); int mid = partion(a, f, e); quickSort(a, f, mid); quickSort(a, mid + 1, e); }}int main(){ int a[] = {6, 7, 0, 3, 2, 4, 5, 8, 9, 1}; quickSort(a, 0, 10); for (int i = 0; i < 10; i++) { std::cout<<a[i]<<" "; } std::cout<<std::endl; return 0;}
2.歸併排序
時間複雜度為O(n*lgn)
歸併排序的思想是分而治之, 每個遞迴過程涉及三個步驟:
第一, 分解: 把待排序的 n 個元素的序列分解成兩個子序列, 每個子序列包括 n/2 個元素.
第二, 治理: 對每個子序列分別調用歸併排序merge, 進行遞迴操作
第三, 合并: 合并兩個排好序的子序列,產生排序結果.
#include <iostream>void mergeArray(int a[], int f, int m, int e, int tmp[]){ int i = f, j = m + 1; int k = 0; while (i <= m && j <= e) { if (a[i] < a[j]) tmp[k++] = a[i++]; else tmp[k++] = a[j++]; } while (i <= m) tmp[k++] = a[i++]; while (j <= e) tmp[k++] = a[j++]; for (i = 0; i < k; i++) { a[f + i] = tmp[i]; }}void merge(int a[], int f, int e, int temp[]){ if (f < e) { int mid = f + (e - f) / 2; merge(a, f, mid, temp); //左邊有序 merge(a, mid + 1, e, temp); //右邊有序 mergeArray(a, f, mid, e, temp); //合并左右兩個有序數組 }}void mergeSort(int a[], int len){ int *p = new int[len]; merge(a, 0, len, p); delete[] p;}int main(){ int a[] = {6, 7, 0, 3, 2, 4, 5, 8, 9, 1}; mergeSort(a, 9); for (int i = 0; i < 10; i++) { std::cout<<a[i]<<" "; } std::cout<<std::endl; return 0;
3.選擇排序
時間複雜度為O(n * n)
選擇排序邏輯:
每一趟從待排序的資料元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最後,直到全部待排序的資料元素排完。選擇排序不是穩定排序演算法, 會破壞原來元素的順序.
#include <iostream>void selectSort(int a[], int n){ for (int i = 0; i < n; i++) { int pos = i; for (int j = i + 1; j < n; j++) { if (a[j] < a[pos]) { pos = j; } } if (pos != i) { int tmp = a[i]; a[i] = a[pos]; a[pos] = tmp; } }}int main(){ int a[] = {6, 7, 0, 3, 2, 4, 5, 8, 9, 1}; selectSort(a, 10); for (int i = 0; i < 10; i++) { std::cout<<a[i]<<" "; } std::cout<<std::endl; return 0;}
4.插入排序
時間複雜度為O(n * n)
插入排序就是每一步都將一個待排資料按其大小插入到已經排序的資料中的適當位置,直到全部插入完畢。
#include <iostream>void insertSort(int a[], int n){ for (int i = 1; i < n; i++) { for (int j = i - 1; j >= 0 && a[j + 1] < a[j]; j--) { int tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; } }}int main(){ int a[] = {6, 7, 0, 3, 2, 4, 5, 8, 9, 1}; insertSort(a, 10); for (int i = 0; i < 10; i++) { std::cout<<a[i]<<" "; } std::cout<<std::endl; return 0;}
5.希爾排序
希爾排序是插入排序的一種.希爾排序的實質就是分組插入排序,該方法又稱縮小增量排序.
該方法的基本思想是:
先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的.
#include <iostream>void shallSort(int a[], int len){ for(int grap = len / 2; grap > 0; grap /= 2) { for(int i = grap; i < len; ++i) { for(int j = i - grap; j >=0 && a[j] > a[j + grap]; j -= grap) std::swap(a[j], a[j + grap]); } }}int main(){ int a[] = {6, 7, 0, 3, 2, 4, 5, 8, 9, 1}; shallSort(a, 10); for (int i = 0; i < 10; i++) { std::cout<<a[i]<<" "; } std::cout<<std::endl; return 0;}
6.堆排序
時間複雜度為O(n*logn)
利用大頂堆(小頂堆)堆頂記錄的是最大關鍵字(最小關鍵字)這一特性,使得每次從無序中選擇最大記錄(最小記錄)變得簡單。
堆排序為不穩定排序,不適合記錄較少的排序
#include <iostream>void heapation(int a[], int pos, int len){ int left = pos * 2; int right = left + 1; int root = pos; if (left < len && a[left] > a[root]) root = left; if (right < len && a[right] > a[root]) root = right; if (root != pos) { std::swap(a[root], a[pos]); heapation(a, root, len); }}//建立最大堆void createHeap(int a[], int len){ for (int i = len / 2; i >= 0; i--) { heapation(a, i, len); }}void heapSort(int a[], int len){ createHeap(a, len); for (int i = 0; i < len; i++) { std::swap(a[0], a[len - i - 1]); heapation(a, 0, len - i - 1); }}int main(){ int a[] = {6, 7, 0, 3, 2, 4, 5, 8, 9, 1}; heapSort(a, 10); for (int i = 0; i < 10; i++) { std::cout<<a[i]<<" "; } std::cout<<std::endl; return 0;}
7.計數排序
使用此排序需要注意的是排序的資料符合常態分佈,有很大的局限性,雖然時間複雜度為O(n),但是犧牲了空間。假設要排序的數為:4,5,9,2,3,1000那麼我們需要分配1000個空間。
#include <iostream>void countSort(int a[], int len){ if (len <= 0 || a == NULL) return; int b[1024] = {0}; int c[1024] = {0}; int maxlen = a[0]; for(int i = 0; i < len; ++i) { b[a[i]]++; if (maxlen < a[i]) maxlen = a[i]; } for(int i = 0; i < maxlen; ++i) { b[i + 1] += b[i]; } for(int i = 0; i < len; ++i) { c[--b[a[i]] ] = a[i]; } for(int i = 0; i < len; ++i) { a[i] = c[i]; }}int main(){ int a[] = {6, 7, 0, 3, 2, 4, 5, 8, 9, 1}; countSort(a, 10); for (int i = 0; i < 10; i++) { std::cout<<a[i]<<" "; } std::cout<<std::endl; return 0;}