排序算法之归并排序

本文回顾了归并排序的基本概念,强调了其在分治法中的应用,以及如何通过递归方式实现,包括数组分割、合并操作和完整C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在我平时的练习与刷题当中我基本不用归并排序,快速排序这类排序,直接就是一个sort排序,简单了事。但是今天的训练赛当中遇到了一道题,它使用了归并排序的分治思想。正好有些遗忘,今天来复习一下。

定义:归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

所谓归并操作就是将两个有序的序列通过操作变成一个有序的数列。这种方法十分高效,时间复杂度为O(M+N)M+N为两个子数组的元素和。

下面是一张图,举例怎么将一个数组分开

下面是代码表示怎么用递归将数组分开

void merge_sort(int l,int r)
{
	if (l>=r) return ;
	int mid = (l+r)>>1;
	merge_sort(l,mid);
	merge_sort(mid+1,r);
} 

 这下面一部分是将两个有序的子数组合并成一个大的有序数组

void merge_sort(int l, int r)
{
	if (l >= r)
		return;
	int mid = l + r >> 1;//取中间值
	merge_sort(l, mid);//有序的数组从q[l]到q[mid]
	merge_sort(mid + 1, r);//有序的数组从q[mid+1]到q[r]
	int k = 0;//新数组tmp的下标
	int i = l;//初始值
	int j = mid + 1;//初始值
	while (i <= mid && j <= r)//当指针i,j均未到达该数组的有边界时
	{
		if (q[i] <= q[j]) //如果q[i]小于q[j],则将q[i]输入到tmp[k],然后i++,指针i向右移一位
			tmp[k++] = q[i++];
		else //如果q[i]大于q[j],则将q[j]输入到tmp[k],然后j++,指针j向右移一位
			tmp[k++] = q[j++];
	}
	//在指针i或者指针j走到尽头,则将另一指针后面的数直接加到tmp[k]的末尾即可
	while (i <= mid) //当指针j走到尽头,而指针i未走到尽头时
		tmp[k++] = q[i++];
	while (j <= r) //当指针i走到尽头,而指针j未走到尽头时
		tmp[k++] = q[j++];

	for (i = l, j = 0; i <= r; i++, j++) //将tmp[]赋值给q[]
		q[i] = tmp[j];
}

完整代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n;
int q[N], tmp[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);//有序的数组从q[l]到q[mid]
	merge_sort(q, mid + 1, r);//有序的数组从q[mid+1]到q[r]
	int k = 0;//新数组tmp的下标
	int i = l;//初始值
	int j = mid + 1;//初始值
	while (i <= mid && j <= r)//当指针i,j均未到达该数组的有边界时
	{
		if (q[i] <= q[j]) //如果q[i]小于q[j],则将q[i]输入到tmp[k],然后i++,指针i向右移一位
			tmp[k++] = q[i++];
		else //如果q[i]大于q[j],则将q[j]输入到tmp[k],然后j++,指针j向右移一位
			tmp[k++] = q[j++];
	}
	//在指针i或者指针j走到尽头,则将另一指针后面的数直接加到tmp[k]的末尾即可
	while (i <= mid) //当指针j走到尽头,而指针i未走到尽头时
		tmp[k++] = q[i++];
	while (j <= r) //当指针i走到尽头,而指针j未走到尽头时
		tmp[k++] = q[j++];

	for (i = l, j = 0; i <= r; i++, j++) //将tmp[]赋值给q[]
		q[i] = tmp[j];
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> q[i];
	merge_sort(q, 0, n - 1);
	for (int i = 0; i < n; i++)
		printf("%d ", q[i]);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值