归并排序

归并排序:

       该算法采用分治法,将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序。(可用来求逆序数)

方法:首先考虑如何将两个有序序列合并,这个只要比较两个子序列的当前元素谁打谁小,然后取小的那一个,并将那个子序列 i++ ,之后再进行比较,若其中一个数列进行到结束之后,将另一个数列中的数搬过来即可。

1,申请空间,使其大小大于等于两个有序序列的和,用来存放合并后的序列

2,设置两个变量(例 i , j )分别指向两有序序列的起始位置

3,比较两变量所指向的元素 a[ i ]和b[ j ],选择所需要的(看题意是要从大到小还是从小到大)元素(这里加入a[ i] < b [j ] ,从小到大排)a[ i ] 放入合并空间,并更新变量值(i ++)

4,重复3知道其中一个序列比较完,将另一序列剩下的元素搬过来即可

主函数中申请空间,最后释放空间

        long long *p=(long long *)malloc(sizeof(long long )*n);
        mergesort(a,0,n-1,p);
        cout<<cnt<<endl;
        free(p);
(这个就是求了逆序数,累加在cnt 上)

void Merge(long long *a,long long left,long long mid,long long right,long long *p)
{
    long long n=mid,m=right;
    long long i=left,j=mid+1;
    long long k=0;
    while(i<=n&&j<=m)
    {
        if(a[i]<=a[j])
            p[k++]=a[i++];
        else
        {
            p[k++]=a[j++];
            cnt+=n-i+1;//因为a[i]到a[mid]位有序的,一旦a[i]>a[j]则从i到mid的所有数都大于a[j]因为题目从小到大排序所以这些数都需要交换到a[j]的后面
        }
    }
    while(i<=n)
    {
        p[k++]=a[i++];
    }
    while(j<=m)
        p[k++]=a[j++];
    for(int i=0;i<k;++i)
        a[left+i]=p[i];
}


上面是将两个有序序列合并,但如何让两个序列有序呢,这里的思路就是将数组分成两组A B ,如果这两组内的数据有序则可以进行合并了。之后再将A B 组分别各自再分成两组,依次类推,知道分出来的组里只有一个元素时可以认为已是有序的,然后再合并相邻的两个小组即可。如此要先通过递归分解数列再合并数列就完成了。


void mergesort(long long *a,long long left,long long right,long long *p)
{
    if(left<right)
    {
        int mid=(left+right)/2;
        mergesort(a,left,mid,p);
        mergesort(a,mid+1,right,p);
        Merge(a,left,mid,right,p);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值