归并排序模板
归并排序模板(merge_sort)
归并排序要点:
基于分治的思想
- 确定分界点
mid = (l + r)/2; - 递归排序左右两边
归并——合二为一(归并排序的核心)
过程分析:
当我们要排序一个数组时,归并排序首先把这个数组分成两半,然后想办法把左、右两边数组排序,再把他们归并起来。当我们对左、右两边的数组进行排序时,再分别把左、右两边的数组分成两半,再对每一个部分排序,再归并。
分到一定程度后,每一部分只有一个元素,那么就不用分了,因为此时一定有序。再两两归并就好。




额外需要注意的点:
- 对于两个已经排序好的数组,如何归并成一个数组呢?
我们可以考虑开辟一个临时数组来存归并后的数组
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define bug(x) cout<<#x<<"=="<<x<<endl;
#define endl "\n"
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int inf = 0xc0c0c0c0;
const int N = 1e5 + 10;
int a[N], tmp[N];
void merge_sort(int q[], int l, int r) {
if (l >= r) return; //递归终止条件,区间元素个数只有一个或者没有
int mid = l + r >> 1;//确定分界点
//递归处理左右两端
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
//归并
int k = 0, i = l, j = mid + 1;//k指合并了几个数,i:指向左半边的起点,j:指向右半边的起点
while (i <= mid && j <= r) { //i小于左半边边界,j小于右半边边界
if (q[i] <= q[j]) tmp[k++] = q[i++];
else tmp[k++] = q[j++];
}
while (i <= mid) tmp[k++] = q[i++];//左边没循环完,直接加到tmp数组里
while (j <= r) tmp[k++] = q[j++];//右边没循环完,直接加到tmp数组里
//把结果赋值回q[]数组里
for (i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j];
}
int main() {
ios;
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
merge_sort(a, 0, n - 1);
for (int i = 0; i < n; i++) cout << a[i] << " ";
return 0;
}

浙公网安备 33010602011771号