MOOC 学习归并排序求逆序数

本文介绍了一种基于归并排序算法实现的逆序数计算方法。通过递归分解数组并进行排序,同时计算出数组中的逆序数。文章提供了完整的C++代码示例,包括分治思想的应用及逆序数的具体计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   基础的归并排序

#include <iostream>
#include<cstring>
using namespace std;

const int n = 10000;

void merge(int a[], int s, int e, int m, int temp[])   //排序部分
{

    int p1 = s, p2 = m + 1;  //两个标记分别指向数组的前后两部分
    int pd = 0;              //指向临时数组的开头
    while(p1 <= m&& p2 <= e)
    {
        if(a[p1] > a[p2])    //按次序比较前后两部分数字的大小,大的放到临时数组里面。
            temp[pd++] = a[p1++];
        else
            temp[pd++] = a[p2++];
    }                   //出循环意味着至少有一个数组已经全部排入临时数组
    while(p2 <= e)              //把没有排入的数组全部放进临时数组的尾部
        temp[pd++] = a[p2++];
    while(p1 <= m)
        temp[pd++] = a[p1++];
    for(int i = 0; i <= e - s; ++i)
    {
        a[i + s] = temp[i]; //把临时数组复制回原数组,用于之后的运算
    }
}

int nx(int a[], int s, int e, int m, int &ans)   //求逆序数
{
    int i = s;
    int j = m + 1;
    while(i <= m&&j <= e)               //比较大小来找出前半数组中比后半数组大的数
    {
        if(a[i] > a[j])
        {
            for(int f = j; f <= e; ++ f) //如果前面数组的一个数比后面数组的某一个数大,则前面的那个数比之后的所有数都大。
                ++ans;          //逆序数加一
            ++i;             //开始比较前面数组的后一个数字
        }
        else
        {
            ++j;             //不构成逆序数,继续比较后面的数字
        }
    }
    return ans;
}

void mergesort(int a[], int s, int e,int temp[],int &ans)  //分治部分
{
    if(e > s)
    {
        int m = s + (e - s)/2;           //找出中点
        mergesort(a, s, m, temp, ans);    //对前半部分分治
        mergesort(a, m+1, e, temp, ans);  //对后半部分分治
        nx(a, s, e, m,ans);                //分治完以后先求逆序数
        merge(a, s, e, m, temp);        //然后再排序
    }

}
int main()
{
    int ans = 0;
    int a[20] = {1,2,3,4,5,6,7,8,91,10,18,12,13,14,15,16,17,18,19,20};
    int temp[20];
    mergesort(a, 0, 19, temp, ans);
    for(auto c: temp)
        cout << c << endl;
    cout << "nx" << ans <<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值