算法实践4 二分归并排序

问题:

二分归并排序:对\(n\)个不同的数构成的数组\(A[1 \dots n]\)进行排序,其中\(n=2^k\)

解析

归并排序需要两个有序的数组,我们每次二分当前区间,将左右两个区间都变成有序的,就可以进行归并排序了。想要保证子区间有序,我们同样可以用相同的方式去对其进行排序,这就变成了一个递归的过程。当子区间长度为\(1\)时,就一定有序,这时直接返回就可以了。

设计

void binaryMerge(int l, int r) {
    if (l == r) return;
    binaryMerge(左子区间);
    binaryMerge(右子区间);
    归并排序
}

分析

二分区间,将区间分成了\(log(n)\)层,每层都需要\(O(n)\)遍历进行归并排序,总时间复杂度\(O(nlogn)\)

源码

https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验4 二分归并排序

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 7;

int a[N], tmp[N];
int n;

void binaryMerge(int l, int r) {
    if (l == r) return;
    int mid = l + r >> 1;
    binaryMerge(l, mid);
    binaryMerge(mid + 1, r);
    int p1 = l, p2 = mid + 1, tot = l;
    while (p1 <= mid || p2 <= r) {
        if (p1 > mid || (p2 <= r && a[p1] > a[p2])) tmp[tot++] = a[p2++];
        else tmp[tot++] = a[p1++];
    }
    for (int i = l; i <= r; ++i) a[i] = tmp[i];
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    binaryMerge(1, n);
    for (int i = 1; i <= n; ++i) {
        printf("%d%c", a[i], " \n"[i == n]);
    }
    return 0;
}
posted @ 2021-03-29 16:08  stff577  阅读(126)  评论(0)    收藏  举报