zoukankan      html  css  js  c++  java
  • 【算法学习笔记】20.算法设计初步 归并排序 求逆序数

    先放上老版代码,这个并不好,由于用到了各种指针和动态数组申请和释放,容易出现问题,不如第二种方法直接用临时数组来解决这个问题

    老版:

    //归并 left是左边数组 left_len长度
    int* Merge(int* left,int left_len, int* right,int right_len){
        //申请一个数组res来存储结果
        int* res = (int *)malloc(sizeof(int)*(left_len+right_len));
        int l=0,r=0,k=0;//l r 分别是左右的指针 k是当前处理之后放在res的下标
        //只要有一边还有元素
        while (l<left_len and r<right_len) {
            if(left[l]>right[r]){//左边大于右边 说明是逆序数 此时左边还剩的元素个数就是f(r)
                cot += left_len - l;//cot累加
                res[k++]=right[r++];
            }else{
                res[k++]=left[l++];
            }
        }
        //还剩一些元素
        for (; l<left_len; l++) {
            res[k++]=left[l];
            
        }
        for (; r<right_len; r++) {
            res[k++]=right[r];
        }
        
        return res;
    }
    //归并排序 
    int* MergeSort(int* array,int array_len){
        if(array_len==1)//只有一个元素 直接返回
            return array;
        int middle = array_len/2;//取中间元素
        int* left = MergeSort(array, middle);//递归调用
        int* right = MergeSort(array+middle, array_len-middle);
        int* r = Merge(left, middle, right, array_len-middle);//获得归并结果
        return r;
    }

    新版(临时数组):

    //新版
    //A是待排序数组 T是临时数组 处理的是[x,y)
    void MergeSort(int* A,int x,int y, int* T){
        if(y-x<=1)  return;//只有一个元素 或者 空的时候 直接返回 不做任何更改
        int m = x+(y-x)/2;//中间下标
        //分治第一步划分已经完成,现在开始第二步 递归调用
        MergeSort(A, x, m, T);//处理[x,m)
        MergeSort(A, m, y, T);//处理[m,y)
        //开始第三步 归并 合并结果
        int l=x,r=m,i=x;//l是左半边的指针 r是右半边的 i是当前指T的指针
        
        while (l<m || r<y) {//当左半边和右半边只要有一个非空时都要进行处理
            //当右侧到了尽头 或者 左侧没有到尽头 而且 左侧指的元素小于右侧时
            //注意这里的|| 和 && 前后的运算是有意安排的 因为是从左到右短路运算
            //这样避免了A[l] A[r]指向非法元素的情况
            if(r>=y || (l<m && A[l]<=A[r])){
                T[i++] = A[l++];//复制左边元素到临时数组
            }
            else{
                T[i++] = A[r++];
                //如果要处理逆序对数则在此处进行累加即可  
                //f(j) = m-l 此时m-l正是左边比右边[r]大的元素的个数  
                cnt += m - l ; 
            }
        }
        for (int i=x; i<y; i++) A[i]=T[i];//把临时数组划回来
        return;
    }
    
    




  • 相关阅读:
    驼峰命名法
    Java中有关Null的9件事
    java开发中JDBC连接数据库代码和步骤
    TestNG 与 Junit的比较
    洛谷 P1880 [NOI1995]石子合并(区间dp,断环为链)
    洛谷 P1901 发射站(单调栈)
    洛谷 P2947 [USACO09MAR]向右看齐Look Up(单调栈)
    洛谷 P2629 好消息,坏消息(前缀和,单调队列,断环为链)
    洛谷 P3810 【模板】三维偏序(陌上花开)(CDQ分治)
    洛谷 CF429D Tricky Function(平面最近点对,分治)
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/4379251.html
Copyright © 2011-2022 走看看