数据结构实验之排序五:归并求逆序数
Time Limit: 50 ms Memory Limit: 65536 KiB
Problem Description
对于数列a1,a2,a3…中的任意两个数ai,aj (i < j),如果ai > aj,那么我们就说这两个数构成了一个逆序对;在一个数列中逆序对的总数称之为逆序数,如数列 1 6 3 7 2 4 9中,(6,4)是一个逆序对,同样还有(3,2),(7,4),(6,2),(6,3)等等,你的任务是对给定的数列求出数列的逆序数。
Input
输入数据N(N <= 100000)表示数列中元素的个数,随后输入N个正整数,数字间以空格间隔。
Output
输出逆序数。
Sample Input
10 10 9 8 7 6 5 4 3 2 1
Sample Output
45
Hint
Source
xam
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long int count;
/* data[left...mid] and data[mid+1...right] */
void mergeit(int data[],int left,int mid,int right,int reserve[])
{
int i=left,j=mid+1; // the start location
int m=mid,n=right; // the end location
int k=0;// count
while(i<=m&&j<=n)
{
if(data[i]<=data[j])
reserve[k++]=data[i++];
else
{
reserve[k++]=data[j++];
count+=mid-i+1;
}
}
while(i<=m)
reserve[k++]=data[i++];
while(j<=n)
reserve[k++]=data[j++];
for(i=0; i<k; i++) // return the data that has ordered
data[left+i]=reserve[i];
}
void mergesort(int data[],int left,int right,int reserve[])
{
if(left<right)
{
int mid=(left+right)/2; // SET THE MID
mergesort(data,left,mid,reserve); // merge the left
mergesort(data,mid+1,right,reserve); // merge the right
mergeit(data,left,mid,right,reserve); // MERGE THE DATA
}
}
int main()
{
int data[123456];
int reserve[123456];
memset(data,0,sizeof(data));
memset(reserve,0,sizeof(reserve));
int n;
scanf("%d",&n);
int i;
for(i=0; i<n; i++)
scanf("%d",&data[i]);
mergesort(data,0,n-1,reserve);
printf("the result of the merge order:\n");
for(i=0; i<n; i++)
printf("%d ",data[i]);
printf("\nthe number of the inverse is %ld\n",count);
return 0;
}
1.归并排序:将两个或者两个以上的有序子序列“归并”为一个有序数列。
【 52 23 80 36 68 14 】
【 52 23 80 】 【 36 68 14 】
【 52 23 】 【 80 】 【 36 68 】 【 14 】
【 52 】 【 23 】 【 80 】 【 36 】 【 68 】 【 14 】
【 23 52 】 【 80 】 【 36 68 】 【 14 】
【 23 52 80 】 【 14 26 68 】
【 14 23 36 38 52 80 】
2.性质相同,规模更小,采用递归。
3.逆序数在合并数组时计数求得。
(希望可以帮到你一点!)