• 归并排序以及逆序对统计


    归并排序以及逆序对统计

    1. 归并排序

    归并排序利用分治的方法,将两个有序数组进行合并,达到排目的。有序数组可以通过不停地将数组进行二分,最终得到一个数,认为此数组有序。然后将两个一个数的数组进行合并,得到一个有序的有两个数据的数组,然后返回上一层继续合并,最终得到有序数列。

    第一步:解决两个有序数组合并

    void mergeArray(int a[],int m, int b[], int n, int re[])    //a,b,合并到re;m,n分别为a,b数组的长度
    {
    	int i,j,k;		//给两个数组分别设定一个指针,把两个之中较小的放在re中,本次较小的指针后移
    	i=j=k=0;
    	while(i<m && j<n)									//合并相同长度的数据
    	{
    		if(a[i]>b[j])
    			re[k++]=b[j++];
    		else
    			re[k++]=a[i++];
    	}
    	while(i<m)											//多出的部分直接复制在re中
    		re[k++]=a[i++];
    	while(j<n)											//多出的部分直接复制在re中
    		re[k++]=b[j++];
    }
    

    第二步:归并排序

    void mergeArray(int a[],int left,int mid,int right, int tmp[])   
    //合并a[left...mid],a[mid+1...right]
    {
        int i=left,j=mid+1,k=0;
        int m=mid,n=right;
     	while(i<=m && j<=n)
    	{
    		if(a[i]>a[j])
    			tmp[k++]=a[j++];
    		else
    			tmp[k++]=a[i++];
    	}
    	while(i<=m)
    		tmp[k++]=a[i++];
    	while(j<=n)
    		tmp[k++]=a[j++];
        for(i=0;i<k;i++)    
     //本层合并完两个有序数组,返回到上一层位置,作为上一层的有序数组的基础,进而进行上一组的合并操作
            a[left+i]=tmp[i];
    }
    void mergeMain(int a[],int left, int right, int temp[])
    {
        int mid;
        if(left<right)
        {
            mid=left+(right-left)/2;
            mergeMain(a,left,mid,temp);             //左边递归二分数组
            mergeMain(a,mid+1,right,temp);          //右边递归二分数组
            mergeArray(a,left,mid,right,temp);      //合并操作
        }
    }
    bool mergeSort(int a[],int n)
    {
        int *re;
        re=new int[n];							   //一次性分配好空间,不能每次分配,释放
        if(!re)                                    //检查空间是否分配成功
            return false;
        mergeMain(a,0,n-1,re);
        delete[] re;
        re=NULL;                                    //空指针
        return true;
    }
    

    2. 逆序对

    逆序对数量查找可以通过归并排序的交换次数算出,在数组a[left...mid]和a[mid+1..right],left<= i <=mid, mid+1<= j< =right ,当满足a[i] > a[j] 时存在逆序对,假设a[j]放在a[i]之前,则a[i]到a[mid](因为a数组为有序数组)的值都大于a[j],共有mid-i+1个逆序对,因此只需要在归并排序中合并数组的时候稍加改动即可

    int ans=0;														 //全局变量统计数目
    void mergeArray(int a[],int left,int mid,int right, int tmp[])  
    {
        int i=left,j=mid+1,k=0;
        int m=mid,n=right;
     	while(i<=m && j<=n)
    	{
    		if(a[i]>a[j])
            {
    			tmp[k++]=a[j++];
    //当a[i]>a[j]的时候,如果此时把a[j]放在a[i]前面,那么a[i]到a[mid]的值都大于a[j],因此在交换之前属于逆序对
    //左边数组 9 8 7  右边数组 1 2 3
    //当把 1 放在 9 前面,那么9 8 7 都是 1 的逆序对,数量 mid-1+1
    			ans+=mid-i+1;
            }
    		else
    			tmp[k++]=a[i++];
    	}
    	while(i<=m)
    		tmp[k++]=a[i++];
    	while(j<=n)
    		tmp[k++]=a[j++];
        for(i=0;i<k;i++)  
            a[left+i]=tmp[i];
    }
    
  • 相关阅读:
    nc 服务器nc l 9995实现双向通信
    Python2/Python3使用virtualenv创建虚拟环境venv
    Linux Openwrt CPU使用率
    JS中slice和splice的区别
    Vue3中路由跳转的语法
    Antd中的table组件报错问题的解决
    Word替换文本的方法记录
    Vite2 Error:Unknown variable dynamic import
    使用SSH方式拉取代码
    css单行超出加省略号
  • 原文地址:https://www.cnblogs.com/TianyuSu/p/6350333.html
Copyright © 2020-2023  润新知