归并排序求逆序对(C语言)

目录

1.归并排序过程

(1)逆序对概念

(2)基本思想

(3)算法实现


1.归并排序过程

使用归并排序实现求逆序对,那么首先得了解什么是归并排序(关于归并排序可以求逆序对,也是在做题中学会的)。

首先得了解归并排序本身的思想,再来了解使用归并排序求逆序的过程:

1.算法思想:
合并排序是采用分治策略实现对N个元素进行排序的算法,是分治法的一个典型应用和完美体现,它是一种平衡,简单的二分分治策略,计算过程分为三步:

  • (1)分解:将待排序元素分成大小大致相同的两个子序列。
  • (2)求解子问题:用合并排序法分别对两个子序列递归地进行排序。
  • (3)合并:将排好序的有序子序列进行合并,得到符合要求的有序序列。

例如:设待排序序列A=<8,3,2,9,7,1,5,4>,采用合并排序算法对序列A进行排序。

在这里插入图片描述 

 

使用C语言实现各种排序(总结)

(1)逆序对概念

假设两个元素Ai,Aj,并且i<j,但是Ai>Aj,那么(Ai,Aj)构成一对逆序对。

(2)基本思想

基本思想:归并排序是两个有序的序列(a[maxn],b[maxn])进行合并,借助一个辅助的数组aux[maxn],用来记录合并之后的序列;而合并的过程是a[i]和b[j]的值进行比较,如果a[i]的值小于等于b[j]的值,那么首先将a[i]的值放入到aux[k]中(隐含的意义就是a[i]和b[j]两个数是有序的);如果a[i]的值大于b[j]的值,那么首先将b[j]的值放入到aux[k]中(隐含的意义就是a[i]和b[j]两个数是逆序的)。

注意:现在根据这个思想画图来理解。

例如:现在对<3,6,7,4,2,1,5>进行归并排序,只画出合并的过程,分解的过程没有画出。

 上图所示:根据刚才表述的思想(可能表述的不是太清楚),比如上面的第二趟归并过程中,middle=1,而left=0,right=3,可以看到元素3和4进行比较,3小于4,是顺序的,所以将3先放入aux[k]中,left下标向右移动;当6和4进行比较时,6大于了4,所以是逆序的,但是仔细看可以发现,要计算4前面到底有多少个是大于它的,直接可以使用(middle-left+1)即可算出,因为合并的每个数组都是有序的数组,所以既然6大于了4,那么如果6的后面还有数据的话,那么一定大于4,所以和4可以构成的逆序对数就是(middle-left+1).依次下面过程的合并也是同样的道理。

计算上面的逆序:count=0;

  • ①第一趟4和7的比较出现逆序,1和2的比较出现逆序,所以逆序数为count=count+2;
  • ②第二趟6和4比较出现逆序,而其他都是顺序,所以逆序数为count=count+1;

  • ③第三趟比较,逆序数为:count=count+10;

  • 最终的逆序数为13.

(3)算法实现

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define MAXSIZE 11

typedef int ElemType;
int merge[MAXSIZE];

//合并两个有序子序列
int count=0;
void Merge(int merge[],int a[],int left,int right,int middle){
	int i=left,j=middle+1;
	int k=left;
	while(i<=middle&&j<=right){
		if(a[i]<=a[j]){
			merge[k++]=a[i++];
		}else{
			merge[k++]=a[j++];
			count+=middle-i+1;
		}
	}
	while(i<=middle)merge[k++]=a[i++];
	while(j<=right)merge[k++]=a[j++];
	i=0;
	for(i=left;i<=right;i++)a[i]=merge[i];
}
//合并排序算法

void Mergesort(int a[],int left,int right){
	if(left<right){
		int middle=(left+right)>>1;
		Mergesort(a,left,middle);
		Mergesort(a,middle+1,right);
		Merge(merge,a,left,right,middle);
    }
}
void display(int a[],int n){
	for(int i=0;i<n;i++){
		printf("%d\t",a[i]);
	}
}

int main(){
	int array[MAXSIZE];
	int n;
	for(int i=0;i<MAXSIZE;i++){
		array[i]=0;
	}
	printf("请输入待排关键字个数: ");
	scanf("%d",&n);
	printf("请输入关键字: ");
	for(int i=0;i<n;i++){
		scanf("%d",&array[i]);
	}
	Mergesort(array,0,n-1);
	display(array,n);
	printf("\n");
	printf("逆序对: %d\n",count);
	return 0;
} 

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
归并排序是一种常用的排序算法,同时也可以用来解逆序数。在C语言中,可以通过实现归并排序算法解逆序数。 首先,我们需要定义一个全局变量来统计逆序数的数量。然后,我们可以使用归并排序的思想来进行排序并计算逆序数。 归并排序的核心思想是将一个数组分成两个子数组,分别对子数组进行排序,然后再将两个排好序的子数组合并成一个有序的数组。在合并的过程中,我们可以统计逆序数的数量。 具体实现归并排序逆序数的步骤如下: 1. 定义一个全局变量count,用于统计逆序数的数量。 2. 创建一个辅助数组temp,用于存储排序的结果。 3. 实现一个递归函数mergeSort,用于对数组进行归并排序。 4. 在mergeSort函数中,首先判断数组的长度是否大于1,如果小于等于1,则直接返回。 5. 将数组分成两个子数组,分别递归调用mergeSort函数进行排序。 6. 在合并两个子数组时,比较两个子数组的元素大小,并将较小的元素放入temp数组中。如果存在逆序,则将逆序数的数量count加上左子数组中剩余的元素个数。 7. 将剩余的元素依次放入temp数组中。 8. 将temp数组中的元素复制回原数组。 9. 最后,返回逆序数的数量count。 以下是用C语言实现归并排序逆序数的示例代码: ```c #include <stdio.h> int count = 0; void merge(int arr[], int left, int mid, int right) { int i = left, j = mid + 1, k = 0; int temp[right-left+1]; while (i <= mid && j <= right) { if (arr[i <= arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; count += mid - i + 1; // 统计逆序数的数量 } } while (i <= mid) { temp[k++] = arr[i++]; } while (j <= right) { temp[k++] = arr[j++]; } for (i = left, k = 0; i <= right; i++, k++) { arr[i = temp[k]; } } void mergeSort(int arr[], int left, int right) { if (left >= right) { return; } int mid = (left + right) / 2; mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); merge(arr, left, mid, right); } int main() { int arr[] = {9, 6, 5, 3, 2}; int n = sizeof(arr) / sizeof(arr<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [逆序数(C语言)--归并](https://blog.csdn.net/qq_46182442/article/details/104055951)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [C语言归并排序与逆序数](https://blog.csdn.net/wwxy1995/article/details/82953957)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值