二路归并排序解决逆序对

1.问题简介:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 2.设计思路:二路归并排序的核心思想是分解和合并,将数组一分为二,起点为left,尾端为right,直到left>=right(分解完成,子数组中的元素个数为1)。完成上述的递归过程,当递归到结束条件满足时,递归往返回的过程,进行二分数组的合并,将二分之后的左右数组依次进行比较,将较小的插入到排序数组中。

因此,在递归往上走时,每一个二分的数组都是有序的。当递归完成时,数组的排序也完成了。同时在排序合并时,比较元素大小,如果左边数组元素大于右边数组的元素,则逆序对=左数长度-左边当前元素的下标+1。如果左边数组元素小于等于右边数组元素,则不形成逆序对。

3.代码:

/*二路归并排序*/
#include <iostream>
using namespace std;

#define N 5
int a[N] = { 1,3,2,3,1 };
int temp[N];        //临时存放排序好的元素的数组
int ans;        //存储逆序对变量

void merge(int left, int mid1, int mid2, int right);

void  merge_sort(int left,int right)
{
    int mid = (left + right) / 2;
    if (left >= right)    //left>=right时表明数组的元素个数为1,二分到底
    {
        return;
    }
    merge_sort(left, mid);    //    往左二分
    merge_sort(mid + 1, right);    //往右二分
    merge(left,mid,mid+1, right);
}

void merge(int left, int mid1, int mid2, int right)    //合并函数
{
    int left1 = left, left2 = mid2;
    int count = 0;
    while (left1 <= mid1 && left2 <= right)
    {
        if (a[left1] <= a[left2])
        {
            temp[count++] = a[left1++];
        }
        else {
            temp[count++] = a[left2++];
            ans += (mid1 - left1 + 1);
        }
    }

    /*左右数组,有一个为空之后,将剩下非空数组的元素都插入到有序数组中*/
    while (left1 <= mid1)
    {
        temp[count++] = a[left1++];
    }
    while (left2 <= right)
    {
        temp[count++] = a[left2++];
    }

    /*将有序数组中的元素插入到目标数组中*/
    for (int i = 0; i < count; i++)
    {
        a[left+i] = temp[i];
    }
}

int main()
{
    merge_sort(0, N-1);
    for (int i = 0; i < N; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    cout << "逆序对数量为:" <<ans<< endl;
    return 0;
}

4.运行结果:

5.总结:二路归并排序主要思想是分解(二分)和合并。整个过程可以利用递归解决,递归的出口为数组中的元素的个数为1。同时,当左边的元素大于右边元素时形成逆序对。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值