归并排序模板

归并排序模板(merge_sort)

归并排序要点:
基于分治的思想

  1. 确定分界点 mid = (l + r)/2;
  2. 递归排序左右两边
  3. 归并——合二为一(归并排序的核心)

过程分析:
当我们要排序一个数组时,归并排序首先把这个数组分成两半,然后想办法把左、右两边数组排序,再把他们归并起来。当我们对左、右两边的数组进行排序时,再分别把左、右两边的数组分成两半,再对每一个部分排序,再归并。
分到一定程度后,每一部分只有一个元素,那么就不用分了,因为此时一定有序。再两两归并就好。
image
image
image
image

额外需要注意的点:

  • 对于两个已经排序好的数组,如何归并成一个数组呢?
    我们可以考虑开辟一个临时数组来存归并后的数组
#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;
}
posted @ 2022-11-29 19:10  csai_H  阅读(143)  评论(0)    收藏  举报