快排
- 选定一个基准元素
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]; }