// nixushu.cpp : 定义控制台应用程序的入口点。
//
//求数列的逆序数,在归并排序过程中,寻找逆序数,时间复杂度为归并排序的复杂度,O(NlogN),空间复杂度也是归并的复杂度 此方法的空间复杂度是 2 * O(N),另外两种方法一是在递归函数内部用临时变量,另一个是和这种方法相似,不过是从a到b,再从b到a
//#include <iostream>//放在这居然编译通不过,怪了!
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#define N 6
using namespace std;
int mergeNixu(int *a,int *b,int low, int mid, int high)//把a中的数组归并到b,a中low到mid是有序的,mid+1到high也是有序的
{
int nixu=0;
if (low<high)
{
int l1=low,l2=mid+1;
int i=low;//a的low到high对应b的low到high
while(l1<=mid&&l2<=high)
{
if (a[l1]<=a[l2])
{
b[i++]=a[l1++];
}
else//此时a[l1]>a[l2],判断前面的部分有多少个大于当前的a[l2],即逆序的数量,是前面部分的总个数
{
b[i++]=a[l2++];
nixu += mid-l1+1;//从第l1的位置到第mid 的位置都是,所以加1
}
}
while(l1<=mid)b[i++]=a[l1++];
while(l2<=high)b[i++]=a[l2++];
}
return nixu;
}
static int nixushu=0;
void mergeSortNixushu(int *a,int *b,int low,int high)//low,high 表示要归并的起始位置和终止位置,从a数组归并到b数组
{
if (low==high)//仅有一个元素时
{
b[low]=a[low];
}
else
{
int mid = (low + high)>>1;
mergeSortNixushu(a,b,low,mid);
mergeSortNixushu(a,b,mid+1,high);//这步之后,b不一定是分段有序的(刚开始时,只有一个元素时肯定是有序的),所以下一步不能对b归并
nixushu += mergeNixu(b,a,low,mid,high);//这一步归并后,保证a在low到high之间是有序的,但是b不一定是有序的
for (int i=low;i<=high;i++)
{
b[i]=a[i];//每次归并后,令b=a,这样可保证b一直是分段有序的。当前这次调用后b是完全有序的,但对于上一层的递归来说,b只是其中一个部分,所以要保证b是有序的
}
//总结起来思路就是:不断地对a进行递归2路归并,每一段的结果暂存到b中,然后从b中归并排序到a中,这就要求b要分段有序,但此时b可能无序(因为我们从没为b排序过),但是a是分段有序的,
//下一步的递归其实是从已经获得分段有序的序列中归并,所以要保证b也是有序的,即令b=a。
/*for (int i=0;i<6;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
for (int i=0;i<6;i++)
{
cout<<b[i]<<" ";
}
cout<<" once merge "<<endl;*/
}
}
int mergeSortNixushu2(int *a,int *b,int low,int high)//非递归的方式,先对a归并中间结果放到b,然后对b归并中间结果放到a,初始值在a中,最终结果放到b中
{
int step;
int i,j,flag=1;
int nixushu=0;
if (low<high)
{
for (step=1;step<high;step*=2)
{
if (flag==1)
{
flag=0;
i=low,j=i+step;
while(i<=high&&j-1<=high)//一个步长也够的时候进不来循环之内,此时这小段数据有序,不用归并
{
if (j+step-1<=high)//有完整的两个步长
{
nixushu+=mergeNixu(a,b,i,j-1,j+step-1);
i+=2*step;
j=i+step;
}
else//只有一个完整的步长,即是最后的归并处理,所以要跳出循环
{
nixushu+=mergeNixu(a,b,i,j-1,high);
break;
}
}
}
else
{
flag=1;
i=low,j=i+step;
while(i<=high&&j-1<=high)
{
if (j+step-1<=high)
{
nixushu+=mergeNixu(b,a,i,j-1,j+step-1);
i+=2*step;
j=i+step;
}
else
{
nixushu+= mergeNixu(b,a,i,j-1,high);
break;
}
}
}
}
if (flag==1)
{
for (int k=low;k<high;k++)
{
b[k]=a[k];
}
}
}
return nixushu;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[]={3,5,4,6,1,2};
int b[N];
for (int i=0;i<N;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
cout<<" unreversive nixushu is "<<mergeSortNixushu2(a,b,0,N-1)<<endl;
//mergeSortNixushu(a,b,0,N-1);
cout<<" nixushu is "<<nixushu<<endl;
for (int i=0;i<N;i++)
{
cout<<b[i]<<" ";
}
cout<<" once merge "<<endl;
system("pause");
return 0;
}
归并排序求逆序数
最新推荐文章于 2022-07-01 17:30:45 发布