算法詳解參考:https://mp.weixin.qq.com/s/wO11PDZSM5pQ0DfbQjKRQAios
#include <iostream> #include <vector> using namespace std; void swap(vector<int> &arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } void BubbleSort(vector<int> &arr) { int flag = 1; // flag標記是否繼續比較元素大小,這裏賦值爲1是爲了進入循環 for(int i = 1; i < arr.size() && flag; i++) { flag = 0; // 初始化爲0 for(int j = arr.size() - 1; j >= i; j--) { if(arr[j] > arr[j+1]) // 升序 { swap(arr, j+1, j); flag = 1; // 不在比較元素時 flag = 1,進入下一次循環 } } } } int main() { vector<int> arr = {0, 5, 3, 4, 6, 2}; BubbleSort(arr); for(int i = 0; i < arr.size(); i++) cout << arr[i] << " "; cout << endl; return 0; } // 冒泡法排序總時間複雜度 O(n^2)
算法詳解參考:https://mp.weixin.qq.com/s/dGfh2t7xhg0wMM_DcYP1Cw算法
#include <iostream> #include <vector> using namespace std; void swap(vector<int> &arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } void SelectSort(vector<int> &arr) { int min; for(int i = 1; i < arr.size(); i++) { min = i; for(int j = i+1; j <= arr.size(); j++) { if(arr[min] > arr[j]) min = j; } if(i != min) swap(arr, i, min); } } int main() { vector<int> arr = {0, 5, 3, 4, 6, 2}; SelectSort(arr); for(int i = 0; i < arr.size(); i++) cout << arr[i] << " "; cout << endl; return 0; } // 簡單選擇排序總時間複雜度 O(n^2) // 性能略優於冒泡
算法詳解參考:https://mp.weixin.qq.com/s/McqFXkXucSZldjU46t5cdw數組
#include <iostream> #include <vector> using std::cout; using std::endl; using std::vector; void swap(vector<int> &arr, int i, int j) { int a = arr[i]; arr[i] = arr[j]; arr[j] = a; } void InsertSort(vector<int> &arr) { for(int i = 1; i < arr.size(); i++) { int j = i; while (j > 0 && arr[j] < arr[j-1]) { swap(arr, j, j-1); j--; } } } int main() { vector<int> arr = {0, 5, 3, 4, 6, 2}; InsertSort(arr); for(int i = 0; i < arr.size(); i++) cout << arr[i] << " "; cout << endl; return 0; } // 直接插入排序總時間複雜度 O(n^2) // 性能優於冒泡和簡單選擇排序
算法詳解參考:https://mp.weixin.qq.com/s/b9-dkpAhWJYshuSs5cwnOw性能
#include <iostream> #include <vector> using namespace std; void ShellSort(vector<int> &arr) { int increment = arr.size(); // 希爾排序的增量初始化 while (increment > 1) { increment /= 2; // 增量折半 for(int i = 0; i < increment; i++) { for(int j = i+increment; j < arr.size(); j = j+increment) { int temp = arr[j]; int k = 0; for(k = j-increment; k >= 0 && arr[k] > temp; k = k-increment) arr[k + increment] = arr[k]; // 因爲 k 的值發生了更新,可是在此循環結束以前索引 j 是沒有發生變化的,因此 k + increment != j(第一次循環時 k+increment = j) arr[k + increment] = temp; } } } } int main() { vector<int> arr = {5, 8, 6, 3, 9, 2, 1, 7}; ShellSort(arr); for(int i = 0; i < arr.size(); i++) cout << arr[i] << " "; cout << endl; return 0; } // 希爾排序是不穩定排序 // Hibbard增量序列:最壞時間複雜度 O(n^(3/2)) // Sedgewick增量序列:最壞時間複雜度 O(n^(4/3))
算法詳解參考:https://mp.weixin.qq.com/s/8Bid1naBLtEjPoP-R4HkBgui
#include <iostream> #include <vector> using namespace std; // 大頂堆調整 void adjustHeap(vector<int> &arr, int i, int length) { int temp = arr[i]; // 先取出當前元素 i for(int k = i*2 + 1; k < length; k = k*2 + 1) // 從 i 結點左子節點開始,也就是 2i+1 處開始 { if(k+1 < length && arr[k] < arr[k+1]) // 若是左子節點小於右子節點,k指向右子節點 k++; if(arr[k] > temp) // 若是子節點大於父節點,將子節點賦值給父節點(不用交換) { arr[i] = arr[k]; i = k; } else break; } arr[i] = temp; // 將 temp 值放到最終位置 } // 元素交換 void swap(vector<int> &arr, int i, int j) { int a = arr[i]; arr[i] = arr[j]; arr[j] = a; } void heapSort(vector<int> &arr) { // 構建大頂堆 for(int i = arr.size()/2 - 1; i >= 0; i--) // 從第一個非葉子結點從上至下,從右到左調整結構 adjustHeap(arr, i, arr.size()); // 調整堆結構加交換堆頂元素與末尾元素 for(int j = arr.size() - 1; j > 0; j--) { swap(arr, 0, j); // 將堆頂元素與末尾元素進行交換 adjustHeap(arr, 0, j); // 從新調整堆結構 } } int main() { vector<int> arr = {5, 8, 6, 3, 9, 2, 1, 7}; heapSort(arr); for(int i = 0; i < arr.size(); i++) cout << arr[i] << " "; cout << endl; return 0; } // 堆排序總體時間複雜度 O(nlogn)
算法詳解參考:https://mp.weixin.qq.com/s/885uGVhlffWAxjgIEW-TiAspa
#include <iostream> #include <vector> using namespace std; void merge(vector<int> &arr, int start, int mid, int end) { // 開闢額外大集合,設置指針 vector<int> tempArray((end - start + 1), 0); int p1 = start, p2 = mid+1, p = 0; // 比較兩個小集合的元素,依次放入大集合 while(p1 <= mid && p2 <= end) { if(arr[p1] <= arr[p2]) tempArray[p++] = arr[p1++]; else tempArray[p++] = arr[p2++]; } // 左(右)側小集合有剩餘,依次放入大集合尾部 while(p1 <= mid) tempArray[p++] = arr[p1++]; while(p2 <= end) tempArray[p++] = arr[p2++]; // 把大集合元素賦值回原數組 for(int i = 0; i < tempArray.size(); i++) arr[i+start] = tempArray[i]; } void mergeSort(vector<int> &arr, int start, int end) { if(start < end) { // 折半成兩個小集合,分別進行遞歸 int mid = (start + end) / 2; mergeSort(arr, start, mid); mergeSort(arr, mid+1, end); // 把兩個有序小集合歸併成一個大集合 merge(arr, start, mid, end); } } int main() { vector<int> arr = {5, 8, 6, 3, 9, 2, 1, 7}; mergeSort(arr, 0, arr.size() - 1); for(int i = 0; i < arr.size(); i++) cout << arr[i] << " "; cout << endl; return 0; } // 總時間複雜度 O(nlogn)
算法詳解參考:https://zhuanlan.zhihu.com/p/93129029指針
// 快排遞歸實現 #include <iostream> using namespace std; void quickSort(int *arr, int begin, int end) { if(begin < end) { int temp = arr[begin]; int i = begin; int j = end; while(i < j) { while(i < j && arr[j] > temp) j--; arr[i] = arr[j]; while(i < j && arr[i] <= temp) i++; arr[j] = arr[i]; } arr[i] = temp; // 遞歸排序基準數兩邊子集 quickSort(arr, begin, i-1); quickSort(arr, i+1, end); } else return; } int main() { int num[10] = {23, 14, 5, 7, 29, 50, 11, 33, 10, 8}; cout << "排序前: " << endl; for(int i = 0; i < 10; i++) cout << num[i] << " "; cout << endl; quickSort(num, 0, 9); cout << "排序後: " << endl; for(int i = 0; i < 10; i++) cout << num[i] << " "; cout << endl; return 0; } // 快速排序時間複雜度 O(nlog2N)