排序演算法的一點點小結
阿新 • • 發佈:2018-12-18
一轉眼2月過去了,秋招快結束了,趁現在這段時間對之前面試中問到的排序演算法做一個小結,怕背熟練的又忘記了。。。
#include<Windows.h> #include<iostream> #include<vector> #include<stdio.h> #include<stack> using namespace std; void maopao(vector<int> &a)//時間複雜度O(n^2),空間複雜度O(1),穩定排序 { if (a.empty()) return; int n = a.size(); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (a[i] > a[j]) { swap(a[i], a[j]); } } } } void maopao1(vector<int> &a)//變種1 設立標誌位,當標誌位在一輪迴圈中不變時說明陣列已經有序 { if (a.empty()) return; int n = a.size(); for (int i = 0; i < n; i++) { bool flag = false; for (int j = i + 1; j < n; j++) { if (a[i] > a[j]) { swap(a[i], a[j]); flag = true; } } if (!flag) break; } } void kuaipai(vector<int> &a,int left,int right)//遞迴版本,時間複雜度O(nlongn),最好情況O(n),最差情況O(n^2),輔助情況(O(n)) 非穩定排序 { if (left > right) return; int i = left; int j = right; int k = a[i]; while (i < j) { while (i < j&&a[j] >= k) { j--; } if (i < j) a[i++] = a[j]; while (i < j&&a[i] < k) { i++; } if (i < j) a[j--] = a[i]; } a[i] = k; kuaipai(a, left, i-1); kuaipai(a, i + 1, right); } int post(vector<int> &a, int left, int right)//非遞迴版本 { int i = left; int j = right; int k = a[i]; while (i < j) { while (i < j&&a[j] >= k) { j--; } if (i < j) a[i++] = a[j]; while (i < j&&a[i] < k) { i++; } if (i < j) a[j--] = a[i]; } a[i] = k; return i; } void kuaipai1(vector<int> &a,int i ,int j) { stack<int> t; t.push(i); t.push(j); int k; while (!t.empty()) { int r = t.top(); t.pop(); int l = t.top(); t.pop(); k = post(a, l, r); if (k-1 > l) { t.push(l); t.push(k - 1); } if (k + 1 < r) { t.push(k + 1); t.push(r); } } } void xuanpai(vector<int> &a)//時間複雜度O(n^2),額外空間O(1),不穩定排序 { for (int i = 0; i < a.size(); i++) { int min = i; for (int j = i+1; j < a.size(); j++) { if (a[j] < a[min]) { min = j; } } if(min!=i)swap(a[i], a[min]); } } void charu(vector<int> &a)//直接插入排序,時間複雜度O(N^2),空間複雜度O(1),穩定排序 { for (int i = 1; i < a.size(); i++) { int j = i; while (j > 0 && a[j] < a[j - 1]) { swap(a[j], a[j - 1]); j--; } } } void xier(vector<int> &a)//空間複雜度O(nlongn)~O(n^2),空間複雜度O(1),不穩定排序 { for (int gap = a.size() / 2; gap > 0; gap /= 2) { for (int i = gap; i < a.size(); i++) { int j = i; while (j - gap >= 0 && a[j] < a[j - gap]) { swap(a[j], a[j - gap]); j--; } } } } void merge(vector<int> &a, int l, int mid, int r) { int i = l; int j = mid + 1; int t = 0; vector<int> temp(r - l + 1, 0); while(i <= mid&&j <= r) { if (a[i] <= a[j]) { temp[t++] = a[i++]; } else { temp[t++] = a[j++]; } } while (i <= mid) { temp[t++] = a[i++]; } while (j <= r) { temp[t++] = a[j++]; } t = 0; while (t < (r - l + 1)) { a[l+t] = temp[t]; t++; }//a[l+t]=temp[t++] 陣列下標訪問越界? } void guibin(vector<int> &a,int l,int r)//時間複雜度O(nlogn),空間複雜度O(n),穩定排序 { if (l < r) { int mid = (r+l) / 2; guibin(a, l, mid); guibin(a, mid + 1, r); merge(a, l, mid, r); } } void adjustHeap(vector<int> &a, int i, int length) { int temp = a[i]; for (int k = 2 * i + 1; k < length; k = 2 * k + 1)//從i結點的左子結點開始,2*i+1開始 { if (k + 1 < length&&a[k] < a[k + 1])//如果左子節點小於右子節點,k指向右子節點 { k++; } if (a[k] > temp)//如果子節點的值大於父節點,將子節點的值賦給父節點 { a[i] = a[k]; i = k; } else break; } a[i] = temp; } void duipai(vector<int> &a)//時間複雜度O(nlogn),空間複雜度O(1),不穩定排序 { //建立大頂堆 for (int i = a.size() / 2 - 1; i >= 0; i--) { //從第一個非葉子結點從下至上,從右至左調整結構 adjustHeap(a, i, a.size()); } //調整堆結構+交換堆頂元素與末尾元素 for (int j = a.size() - 1; j > 0; j--) { swap(a[0],a[j]);//將堆頂元素與末尾元素交換 adjustHeap(a, 0, j);//重新對堆調整 } } int main(void) { vector<int> a = { 2,6,3,1,5,8,4,2,0 }; duipai(a); for (int i = 0; i < a.size(); i++) { cout << a[i] ; } cout << endl; system("pause"); return 0; }
以上程式碼均在vs2015下跑過,親證可用。