求序列A中逆序对的个数(C语言实现)

本文介绍了一种使用分治法及归并排序原理求解数组中逆序对数量的方法。通过对数组进行递归划分,计算左右子数组逆序对数量,并在合并过程中统计跨子数组的逆序对。

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

目录

1.题目概述:

2.题目解析:

3.题目代码:

4.样例展示:

5.题目总结:


1.题目概述:

        给定一个数组, 若 (ai>aj)且(i<j) 就为一个逆序对。 例如数(3,1,4,5,2)的逆序对为4个,分别是<3,1>,<3,2>,<4,2>、<5,2>。 编写一个实验程序,采用分治法求序列A中逆序对的个数,即逆序数。


2.题目解析:

        问题思路:利用分治法进行求解

1.将数组分成两半,分别求出左半边的逆序数和右半边的逆序数

2.再算有多少逆序是由左半边取一个数和右半边取一个数构成

实际上就是归并排序的改造,即对此排列进行归并排序,边排序边计算它的逆序数

        问题关键:设左半边和右半边都是从小到大有序的(此时进行归并),从左到右依次扫描,比较两个各取一个数的大小,如果左边第一个数比右边第一个数大,那么左边排列的其他数字也可以和右边第一个数构成逆序数,以此类推。


3.题目代码:

#include <stdio.h>
int sum = 0;
int MergeSort(int SR[], int s, int m, int n)
{
	int j, i = s;
	int b[n - i + 1];
	int k, l = s, temp = 0, count = 0;
	for (j = m, k = 0; i < m && j <= n;)
	{
		if (SR[i] > SR[j])
		{
			b[k++] = SR[j++];
			temp++;
		}
		if (SR[i] <= SR[j] || j == n + 1)
		{
			count += temp * (m - i);
			b[k++] = SR[i++];
			temp = 0;
		}
	}
	for (; i < m; k++)
		b[k] = SR[i++];
	for (; j <= n; k++)
		b[k] = SR[j++];
	for (k = 0; l <= n; l++, k++)
		SR[l] = b[k];
	return count;
}
void Sort(int SR[], int s, int t)
{
	int m;
	if (s < t)
	{
		m = (s + t) / 2;
		Sort(SR, s, m);
		Sort(SR, m + 1, t);
		sum += MergeSort(SR, s, m + 1, t);
	}
}
int main()
{
	int n, i;
	printf("A数组中数的个数是:");
	scanf("%d", &n);
	int a[n], b[n];
	printf("A数组序列为:\n");
	for (i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
		b[i] = a[i];
	}
	Sort(a, 0, n - 1);
	printf("序列A中逆序对为:%d\n", sum);
	return 0;
}

4.样例展示:


5.题目总结:

        对于该问题,我将序列分成子序列,并分别求解各个子序列中存在的逆序对数量,然后将结果合并,即可求出整个序列的逆序对,这也就是分治法,在这个过程中,排序并且找到逆序对同时进行计数,根据这一特点我想到了归并排序,因此,我在归并排序中增加计数器,解决了这个问题,是这个问题的难点。这是对于该问题的简要分析。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小航同学吖

制作不易,动动你的小手

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值