设计用时间复杂度为O(nlgn)的算法对长度为n的数组中的逆序对计数。
核心思想就是修改合并排序算法,因为当合并时会比较两个连续小数组中元素的大小。
#include <stdio.h>
#include <string.h>
#include <time.h>
#define BUFFER_SIZE 10
void Merge(int *a,int p,int q,int r,int *cnt)
{
int i=0;
int j=0;
int k=0;
int n1=q-p+1;
int n2=r-q;
int n=n1+n2;
int b[n1+1];
int c[n2+1];
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
b[n1]=BUFFER_SIZE;//哨兵元素,注意别溢出
c[n2]=BUFFER_SIZE;//哨兵元素,注意别溢出
for(i=p,j=0;i<=q;i++)
{
b[j]=a[i];
j++;
}
for(i=q+1,k=0;i<=r;i++)
{
c[k]=a[i];
k++;
}
for(i=p,j=0,k=0;i<=r;i++)
{
if(b[j]<=c[k])
{
a[i]=b[j];
j++;
}
else
{
a[i]=c[k];
k++;
(*cnt)++; //出现逆序对,计数
}
}
}
void MergeSort(int *a,int p,int r,int *cnt)
{
int q=0;
if(p>=r)
{
return;
}
q=(p+r)/2;
MergeSort(a,p,q,cnt);
MergeSort(a,q+1,r,cnt);
Merge(a,p,q,r,cnt);
}
void Output(int *a,int len)
{
int i=0;
for(i=0;i<len;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main()
{
int i=0;
int k=1;
int cnt=0;//计算逆序对数目
int a[BUFFER_SIZE];
memset(a,0,sizeof(a));
srand((unsigned)time(NULL));
for(i=0;i<BUFFER_SIZE;i++)
{
a[i]=rand()%BUFFER_SIZE;
}
printf("随机生成的数组:");
Output(a,BUFFER_SIZE);
printf("冒泡排序后:");
MergeSort(a,0,BUFFER_SIZE-1,&cnt);
Output(a,BUFFER_SIZE);
printf("逆序对的数目为:%d\n",cnt);
system("pause");
return 0;
}