好幾天沒看《算法導論》,今天看了一天的排序算法,印象第一的是基數算法,由於竟然違反個人一個常識,它採用的是最低有效位進行排序的。
插入排序、歸併排序、堆排序、快速排序,這些都是比較排序算法:它們都是經過對元素進行比較操做來肯定輸入數組的有序次序,這些算法能夠用決策樹模型分析,能夠證實任意比較排序算法排序n個元素的最壞狀況運行時間的下界爲Omega(nlgn),其中堆排序和歸併排序是漸進最優的比較排序算法。ios
算法c++ |
最壞狀況運行時間算法 |
平均狀況/指望運行時間api |
插入排序(原址)數組 |
Theta(n^2)數據結構 |
Theta(n^2)性能 |
歸併排序ui |
Theta(nlgn)spa |
Theta(nlgn)code |
堆排序(原址) |
Theta(nlgn) |
-------- |
快速排序(原址) |
Theta(n^2) |
Theta(nlgn)指望) |
HEAPSORT(A) BULID-HEAP(A) For i = A.length downto 2 exchange A[1] with A[i] length-size=A.length-size-1 HEAPIFY(A,1)
#include <cstdio> #include <cstdlib> #include <cmath> using namespace std; int parent(int); int left(int); int right(int); void Max_Heapify(int [], int, int); void Build_Max_Heap(int [], int); void print(int [], int); void HeapSort(int [], int); /*父結點*/ int parent(int i) { return (int)floor((i - 1) / 2); } /*左子結點*/ int left(int i) { return (2 * i + 1); } /*右子結點*/ int right(int i) { return (2 * i + 2); } /*單一子結點最大堆積樹調整*/ void Max_Heapify(int A[], int i, int heap_size) { int l = left(i); int r = right(i); int largest; int temp; if(l < heap_size && A[l] > A[i]) { largest = l; } else { largest = i; } if(r < heap_size && A[r] > A[largest]) { largest = r; } if(largest != i) { temp = A[i]; A[i] = A[largest]; A[largest] = temp; Max_Heapify(A, largest, heap_size); } } /*創建最大堆積樹*/ void Build_Max_Heap(int A[],int heap_size) { for(int i = (heap_size-2)/2; i >= 0; i--) { Max_Heapify(A, i, heap_size); } } /*印出樹狀結構*/ void print(int A[], int heap_size) { for(int i = 0; i < heap_size;i++) { printf("%d ", A[i]); } printf("\n"); } /*堆積排序程序碼*/ void HeapSort(int A[], int heap_size) { Build_Max_Heap(A, heap_size); int temp; for(int i = heap_size - 1; i >= 0; i--) { temp = A[0]; A[0] = A[i]; A[i] = temp; Max_Heapify(A, 0, i); } print(A, heap_size); } /*輸入資料並作堆積排序*/ int main(int argc, char* argv[]) { const int heap_size = 13; int A[] = {19, 1, 10, 14, 16, 4, 7, 9, 3, 2, 8, 5, 11}; HeapSort(A, heap_size); system("pause"); return 0; }
#include <iostream> using namespace std; /* #堆排序#% #數組實現#% */ //#篩選算法#% void sift(int d[], int ind, int len) { //#置i爲要篩選的節點#% int i = ind; //#c中保存i節點的左孩子#% int c = i * 2 + 1; //#+1的目的就是爲了解決節點從0開始而他的左孩子一直爲0的問題#% while(c < len)//#未篩選到葉子節點#% { //#若是要篩選的節點既有左孩子又有右孩子而且左孩子值小於右孩子#% //#從兩者中選出較大的並記錄#% if(c + 1 < len && d[c] < d[c + 1]) c++; //#若是要篩選的節點中的值大於左右孩子的較大者則退出#% if(d[i] > d[c]) break; else { //#交換#% int t = d[c]; d[c] = d[i]; d[i] = t; // //#重置要篩選的節點和要篩選的左孩子#% i = c; c = 2 * i + 1; } } return; } void heap_sort(int d[], int n) { //#初始化建堆, i從最後一個非葉子節點開始#% for(int i = (n - 2) / 2; i >= 0; i--) sift(d, i, n); for(int j = 0; j < n; j++) { //#交換#% int t = d[0]; d[0] = d[n - j - 1]; d[n - j - 1] = t; //#篩選編號爲0 #% sift(d, 0, n - j - 1); } } int main() { int a[] = {3, 5, 3, 6, 4, 7, 5, 7, 4}; //#QQ#% heap_sort(a, sizeof(a) / sizeof(*a)); for(int i = 0; i < sizeof(a) / sizeof(*a); i++) { cout << a[i] << ' '; } cout << endl; return 0; }
QUICKSORT(A,p,r) if p < r q=PARTITION(A,p,r) QUICKSORT(A,p,q-1) QUICKSORT(q+1,r)上面算法的關鍵部分是PARTITION過程,它實現了對子數組的原址重排。
PARTITION(A,p,r) x=A[r] i=p-1 for j=p to r-1 if A[j]<=x I=i+1 Exchange A[i] with A[j] Exchange A[i+1] with A[r] Return i+1
#include <utility> using std::swap; int partition(int* array, int left, int right) { int index = left; int pivot = array[index]; swap(array[index], array[right]); for (int i=left; i<right; i++) { if (array[i] > pivot) // 降序 swap(array[index++], array[i]); } swap(array[right], array[index]); return index; } void qsort(int* array, int left, int right) { if (left >= right) return; int index = partition(array, left, right); qsort(array, left, index - 1); qsort(array, index + 1, right); }