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

来源:互联网 发布:阶乘递归算法 编辑:程序博客网 时间:2024/06/07 16:31

归并排序

上一个分治法的扩展

划分:把序列分成元素个数尽量相等的两半。
递归求解:把两半的元素分别排序
合并:把两个有序表合并成一个

输入:

81 2 12 11 9 7 13 20

输出:

1 2 7 9 11 12 13 20
#include <stdio.h>#define MAXSIZE 1024void 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 913

第一行为计数过程表示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 1024int 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;}
原创粉丝点击