您的位置:首页 > 其它

高效算法设计_再谈排序和检索(归并排序,逆序数对)

2017-08-11 09:17 447 查看

归并排序

上一个分治法的扩展

划分:把序列分成元素个数尽量相等的两半。

递归求解:把两半的元素分别排序

合并:把两个有序表合并成一个

输入:

8
1 2 12 11 9 7 13 20


输出:

1 2 7 9 11 12 13 20


#include <stdio.h>
#define MAXSIZE 1024
void merge_sort(int *A,int x,int y,int *T){
//T是辅助空间
int i;
if(y-x>1){
//递归入口,所剩元素大于1,只有一个元素没有必要排序
int m=x+(y-x)/2;//分治第一步,划分,技巧,向中间靠拢
int p=x,q=m,i=x;
merge_sort(A,x,m,T);//分治第二步,递归求解。
merge_sort(A,m,y,T);
while(p<m||q<y){//只要有一个序列非空,就要继续合并
if(q>=y||(p<m&&A[p]<=A[q]))
//第二个序列为空,或者两个序列都不为空,比较小的赋值,赋值A[p].
T[i++]=A[p++];
else T[i++]=A[q++];
//否则第二个不为空,且第一个为空,或者,两个都不为空,且A[p]<=A[q]时,才赋值A[q]
}
for(i=x;i<y;i++)   A[i]=T[i];
//右边的y是取不到的
}
}
void print(int* A,int n)//比赛中避免最后一个空格检查出错误。
{
for(int i = 0 ; i < n; i++)
{
if(i)
{
printf(" %d",A[i]);
}
else
{
printf("%d",A[i]);
}
}
printf("\n");
}

void process()//输入程序。
{
int n;
while(scanf("%d",&n)!=EOF)
{
int A[MAXSIZE];
int T[MAXSIZE];
for(int i = 0 ; i < n ; i++)
{
scanf("%d",&A[i]);
}
merge_sort(A,0,n,T);
print(A,n);
}
}
int main(int argc,char* argv[])
{
process();
return 0;
}


逆序对数

题目: 给一列数a1,a2,a3,…,an。求它的逆序对数,即有多少个有序对(i,j),使得i

输入:

8
1 9 6 3 4 7 9 0


输出:

0 1 2 3 3 4 6 6 10 12 13 13
0 1 3 4 6 7 9 9
13


第一行为计数过程表示cout逐渐自加的过程.

计算步骤:

刚开始归并排序两两分组 (1,9)(6,3)||(4,7)(9,0)

后面一位和前面一位进行对比,如果 i<j 且 ai>aj,逆序数对就加1

对于前半部分 count=0+1; 重排合并后(1,9,3,6) count=0+1+1+1.

对于后半部分count=3+0+1;重排合并后(4,7,0,9)count=3+0+1+2+0;

然后再重排合并(1,3,6,9,0,4,7,9)count=6+4+2+1+0=13,及最终结果

#include <stdio.h>
#define MAXSIZE 1024

int count,k=0;
int K[MAXSIZE];
void mergeSort(int* A,int x,int y,int* T)
{
if(y-x>1)
{
int m = x + (y - x) / 2 ;
int p=x,q=m,i=x;
mergeSort(A,x,m,T);
mergeSort(A,m,y,T);
while(p < m || q < y)
{
//if(m >= high || (l < mid && iArr[l] < iArr[m]))
if(q>= y||(p < m && A[p] <= A[q]))//=与号不能漏
{
T[i++] = A[p++];
}
else
{
T[i++]=A[q++];
count+=m-p;
printf("%d ",count);
}
}
for(int j = x ; j < y ; j++)
{
A[j]=T[j];
}
}
}

void print(int* A,int n)
{
for(int i = 0 ; i < n; i++)
{
if(i)
{
printf(" %d",A[i]);
}
else
{
printf("%d",A[i]);
}
}
printf("\n");
}

void process()
{
int n;
while(scanf("%d",&n)!=EOF)
{
count = 0;
int A[MAXSIZE];
int T[MAXSIZE];
for(int i=0;i<n;i++)
{
scanf("%d",&A[i]);
}
mergeSort(A,0,n,T);
print(A,n);
printf("%d\n",count);
}
}

int main()
{
process();
getchar();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息