排序 sort === ###### tags: `Algorithm` ## Insetion sort 遍歷一個序列, 不斷把元素插入到左邊已經排序過的序列 ```cpp #include<bits/stdc++.h> using namespace std; #define maxN 1000 int arr[maxN]; void insertion_sort( int len){ for( int i=1; i<len; i++){ int key = arr[i]; int j; for( j=i-1; j>=0&&(arr[j]>key); j--){ arr[j+1] = arr[j]; } arr[j+1] = key; } } ``` ## Merge sort * 把區段切成 2 半, 分別排序後 merge 起來 * C++ 有提供 [merge](http://www.cplusplus.com/reference/algorithm/merge/) 函數 Template ```cpp #define maxN 100000 int arr[maxN]; int tmp[maxN]; inline void m_merge( int f, int r){ int m = (f+r)>>1; int fi = f, ri = m, tmpi = f; while( fi<m || ri<r){ if( ri==r || arr[fi]<arr[ri] && fi<m){ tmp[tmpi++] = arr[fi++]; } else{ tmp[tmpi++] = arr[ri++]; } } for( int i=f; i<r; i++){ arr[i] = tmp[i]; } } void msort( int f, int r){ if( r-f<=1) return; int m = (f+r)>>1; msort( f, m); msort( m, r); m_merge( f, r); } ``` ## Quick sort ### 提示 遍歷找小 swap 到前面 -> 基準移到中間 -> 遞迴兩半 ___ 把比基準點小的移到左邊, 比基準點大的移到右邊 若排序 f 到 r 基準點: 需要再 f 上 * 取 f 第個, 或是取第 rand()%(r-f)+f 後 swap 到第 f 個 從 f 後開始找到如果比基準點小就 swap 到右邊 ```cpp swap( arr[rand()%(r-f)], arr[f]); cout << arr[f] << "\n\n"; int j=f; for( int i=f; i<r; i++){ if( arr[i] < arr[f]){ swap( arr[++j], arr[i]); } } swap( arr[f], arr[j]); // 要把基準點 swap 到大小交接處 ``` 遞迴左邊和右邊, 記得不包含基準點 ```cpp void qsort( int f, int r){ if( r-f <=1) return; swap( arr[rand()%(1)+f], arr[f]); int j=f; for( int i=f; i<r; i++){ if( arr[i] < arr[f]){ swap( arr[++j], arr[i]); } } swap( arr[f], arr[j]); qsort( f, j); qsort( j+1, r); } ``` ## Stable Sort 穩定排序, Sort by Index 如果排序後能保持相等元素的先後順序, 我們稱為穩定排序 如果需要用不穩定排序法穩定排序, 我們可以 ***sort by index*** ```cpp #include<bits/stdc++.h> using namespace std; #define maxN (1000) int arr[maxN], id[maxN]; bool cmp( const int &a, const int &b){ return (arr[a]==arr[b])? (a<b) : arr[a]<arr[b]; } int main(){ for( int i=0; i<maxN; i++){ arr[i] = rand(); id[i] = i; } sort( id, id+maxN, cmp); for( int i=0; i<maxN; i++){ cout << arr[ id[i]] << '\n'; } } ``` ## Unique ### 提示 排序 -> 找到下一個不一樣的並 push_back ___ ```cpp #define maxN 1000 int arr[maxN]; int u[maxN]; int uniq(){ sort(arr,arr+maxN); int ai=0, ui=0; while(ai+1<maxN){ for( ; arr[ai]==arr[ai+1]&&ai+1<maxN; ai++); u[ui++]=arr[ai++]; } return ui; // size of u } ``` ## 字典序 ### 提示 遍歷兩個直到比出大小, 如果完全一樣(其中一個是前綴)就比較長度 ```cpp bool cmp( string a, string b){ int len=min(a.size(),b.size()); for( int i=0; i<len; i++){ if( a[i]<b[i]) return true; if( a[i]>b[i]) return false; } return a.size()<b.size(); } ``` ### ref ![](https://i.imgur.com/kiuZeF9.jpg)