快排
- 選定一個基準元素
x
- 分區過程,
>= x
的數全放到它的右邊,<= x
的數全放到它的左邊 - 交換,若是此時兩個指針
i、j
沒有相遇過,則i
必定是遇到了一個>= x
的數,j
遇到了一個<= x
的數,此時須要將a[i]、a[j]
交換 - 再對左右區間分別重複第二步,直到區間中只有一個數時返回
void quick_sort(int l, int r) { if (l>=r) return; int m=l+r>>1, x=a[m], i=l-1, j=r+1; while (i<j) { while (a[++i]<x); while (a[--j]>x); if (i<j) swap(a[i], a[j]); } quick_sort(l, j); quick_sort(j+1, r); }
快速選擇:快應用於尋找數組數組中的第 k 小/第 n-k 大的數算法
每次快速選擇都會將位於基準值x右邊且≤x的一個數放到x左邊,故k次以後,前k個最小數組
int quick_select(vector<int>& a, int l, int r, int k) { if (l==r) return a[l]; int p = (l+r)>>1, x = a[p], i = l-1, j = r+1; while (i < j) { do i++; while (a[i] < x); do j--; while (a[j] > x); if (i < j) swap(a[i], a[j]); } int sz=j-l+1; if (sz>=k) return quick_select(a, l, j, k); else return quick_select(a, j+1, r, k-sz); }
歸併
- 取中心點
mid = l + r >>> 1
- 遞歸處理左半邊
[l, m]
和右半邊[mid+1, r]
,當某一次歸併處理完畢後,兩個區間內的數分別有序 - 最後用雙指針算法將兩個區間合併
void merge_sort(int l, int r) { if (l>=r) return; int m=l+r>>1; merge_sort(l, m); merge_sort(m+1,r); int i=l, j=m+1, k=0, b[r-l+1]; while (i<=m && j<=r) { if (a[i]<=a[j]) b[k++]=a[i++]; else b[k++]=a[j++]; } while (i<=m) b[k++]=a[i++]; while (j<=r) b[k++]=a[j++]; for (int i=l, j=0; i<=r; i++, j++) a[i]=b[j]; }