【模板】排序模板總結

快排
  • 選定一個基準元素 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];
}
相關文章
相關標籤/搜索