【模板】排序模板总结

快排
  • 选定一个基准元素 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];
}
相关文章
相关标签/搜索