算法实践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;
}

浙公网安备 33010602011771号