归并排序详解(C++)/逆序数求解

一、归并排序原理

        归并排序(Merge Sort)是一种基于分治法的高效、稳定排序算法。其原理是将数组不断地分割成两个子数组,直到每个子数组只包含一个元素为止;然后逐步合并这些子数组,在合并的过程中进行排序,最终得到完全有序的数组。

二、归并排序标准代码

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;
	while (i <= mid && j <= r)
		if (q[i] <= q[j]) tmp[k++] = q[i++];
		else tmp[k++] = q[j++];
	while (i <= mid) tmp[k++] = q[i++];
	while (j <= r) tmp[k++] = q[j++];
	for (int i = 0, j = l; j <= r; i++, j++) q[j] = tmp[i];
}

三、代码解析

1.

void merge_sort(int q[], int l, int r)

传入数组,以及所需排序的区间

2.

if (l >= r) return;

递归结束的条件

3.

int mid = l + r >> 1;
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);

l + r >> 1相当于(l + r)/2向下取整;程序先归并再执行其于程序,将整个数组两份两份的往下分,直到只剩一个元素,然后接下来就是个数数1,1比较,1,1比较,...,比较后的两个数有序,然后个数数2,2比较,2,2比较,...,比较后的4个数依然有序,以此类推直到全部结果有序

4.

int k = 0, i = l, j = mid + 1;

设定变量,k 初始化,i , j 为两个指针,i 为开头,j 为中间位置,将数组分为两部分

5.

while (i <= mid && j <= r)
		if (q[i] <= q[j]) tmp[k++] = q[i++];
		else tmp[k++] = q[j++];

循环条件:i 和 j 都没超过各自的结尾,

循环程序;比较 q[i] 和 q[j],将 i 和 j 所对应的数组元素较小的放入新数组 tmp,将放入新数组的指针+1指向下一个元素再次比较以此类推,最终会有一个指针结束而另一个指针有剩余

6.

while (i <= mid) tmp[k++] = q[i++];
while (j <= r) tmp[k++] = q[j++];

将两个指针中有剩余的数组元素全部放进新数组,注意排序是从两个开始,举个例子,a 和 b 比较然后排序 ,c 和 d 比较后排序,然后排好的 ab 和排好的 cd 比较后排序,因此排序之前的两部分数组都是有序的,所以直接放入新数组

7.

for (int i = 0, j = l; j <= r; i++, j++) q[j] = tmp[i];

将数组 q 更新,注意我们是在 l 到 r 范围内排序的,所以将此部分更新,设定两个变量,j 从 l 开始到 r 结束

四、总结

        归并排序就是利用递归将整个问题精确到最小个数,再从小到大比较合并的过程

五、逆序数计算

1.代码

long long merge_sort(int q[], int l, int r)
{
	if (l >= r) return 0;
	int  mid = l + r >> 1;
	res=merge_sort(q, l, mid) + merge_sort(q, mid + 1, r);//归并求和
	int k = 0, i = l, j = mid + 1;//起始指针
	while (i <= mid && j <= r)//同时满足条件执行
		if (q[i] <= q[j]) tmp[k++] = q[i++];//小的放新数组
		else tmp[k++] = q[j++],res += mid - i + 1;//j较小的话放入后逆序数为剩余i的数量
	while (i <= mid) tmp[k++] = q[i++];//剩余无法比较的放入新数组
	while (j <= r) tmp[k++] = q[j++];
	for (int i = 0, j = l; j <= r; i++, j++) q[j] = tmp[i];//更新数组q
	return res;//返回值
}

2.解析

        在归并排序的基础上进行改造,首先函数变为有返回值的函数,因为 j 在 i 右边,所以当 j 放进新数组后,逆序数即为 i 数组中剩余的元素个数 mid - i + 1,再将递归函数加起来即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值