【C++實現】基本排序演算法 插入排序——歸併排序——快速排序——堆排序
阿新 • • 發佈:2019-01-26
/*
排序總結:(基於100w隨機數,有序數、重複數測試)
1、插入排序適合近乎有序的序列
2、歸併排序優化:(優化前 120S)
1)資料小於15時採用插入排序 10S
2)避免頻繁動態申請記憶體 memcpy(dest,src,sizeof(int)*len) 用static 變數 0.2S
缺點:需要O(N)的空間複雜度
3、快速排序優化:(優化前 如果序列完全有序,則程式直接棧溢位,如果序列為隨機數 0.7S)
1)隨機選擇樞軸 可有效避免近乎有序序列排序慢的情況 儘量不用swap使用節約一次賦值的時間 0.4S
2) 資料小於15時採用插入排序 0.2S
優點:空間複雜度O(log(n))
缺點:近乎有序時效率不高
4、堆排序 :先heapify 在從小到大排
優點:空間複雜度O(1) 原地排序
*/
#include<ctime> inline void swap2(int &a, int &b){ int c = a; a = b; b = c; } //插入排序 void insertSort(int arr[], int lo, int hi){ for (int i = lo; i < hi; i++){ int e = arr[i]; int j; for (j = i; j >lo && e < arr[j - 1]; j--)//判斷條件放在for內部會導致錯誤 arr[j] = arr[j - 1]; arr[j] = e; } } void insertSort(int arr[], int n){ insertSort(arr, 0, n); } //歸併排序 void Merge(int arr[], int lo, int mi, int hi){ int lb = mi - lo; int lc = hi - mi; int* A = arr + lo; static int* B = new int[10000000 / 2];//此處優化後只需0.2S int* C = arr + mi; memcpy(B, A, lb*sizeof(int)); for (int i = 0, j = 0, k = 0; j < lb || k < lc;){ if (j < lb && (k >= lc || B[j] < C[k])) A[i++] = B[j++]; if (k < lc && (j >= lb || B[j] >= C[k])) A[i++] = C[k++]; } //delete[] B; } void __mergeSort(int arr[], int lo, int hi){ //if (hi - lo < 2) return;//100w資料需要121.2S 使用插入排序優化後只需10.1S if (hi - lo <= 15) { insertSort(arr, lo, hi); return; } int mi = lo + (hi - lo) / 2; __mergeSort(arr, lo, mi); __mergeSort(arr, mi, hi); Merge(arr, lo, mi, hi); } void mergeSort(int arr[], int n){ __mergeSort(arr, 0, n); } int partition(int arr[], int lo, int hi){ swap2(arr[lo], arr[rand() % (hi - lo) + lo]); int e = arr[lo]; int i = lo + 1, j = hi - 1; while (true) { while (i <= j && arr[i] < e) i++; // 從左向右找第一個小於x的數 while (i <= j && arr[j] > e) j--;// 從右向左找第一個大於等於x的數 if (i > j) break; swap2(arr[i++], arr[j--]); } swap2(arr[lo], arr[j]); return j; } int partition2(int arr[], int lo, int hi){ swap2(arr[lo], arr[rand() % (hi - lo) + lo]); int e = arr[lo]; hi--; while (lo<hi) { while (lo < hi && arr[hi] > e) hi--;// 從右向左找第一個大於等於x的數 if (lo < hi) arr[lo++] = arr[hi]; while (lo < hi && arr[lo] < e) lo++; // 從左向右找第一個小於x的數 if (lo<hi) arr[hi--] = arr[lo]; } arr[lo] = e; return lo; } void quickSort(int arr[], int lo, int hi){ //if (hi - lo < 2) return; if (hi - lo <= 15) { insertSort(arr, lo, hi); return; } int j = partition2(arr, lo, hi); quickSort(arr, lo, j); quickSort(arr, j + 1, hi); } void quickSort(int arr[], int n){ srand(time(NULL)); quickSort(arr, 0, n); } //堆排序 void shiftDown(int arr[], int k, int n){ int e = arr[k]; int j = k; while (k * 2 + 1 < n){ j = k * 2 + 1; if (j + 1 < n&&arr[j + 1] > arr[j]) j++; if (arr[j] > e) { arr[k] = arr[j]; k = j; } else break;//注意break } } void heapSort(int arr[], int n){ for (int i = (n - 2) / 2; i >= 0; i--){ shiftDown(arr, i, n); } for (int i = n - 1; i >= 0; i--){ swap2(arr[0], arr[i]); shiftDown(arr, 0, i); } }