合并排序中子排序结果放回原数组时应注意的问题

  在对数组进行合并排序时,往往会用到递归。而一遇上递归,就很容易被迷住。毕竟,递归的过程细节是很烧脑的。这时,如果再来几个子函数,就更嗨了。下面就说一说我自己遇见的这个递归:

  template<class T>

  void MergeSort(T a[],int left,int right){
    int t=right-left;
    t++;
    T b[t];//每次递归,定义一个与处理数据数量相等大小的数组,暂存处理后的数组
    if(left<right){
    int i=(left+right)/2;
    MergeSort(a,left,i);//这两次不同形式的递归结果为
    MergeSort(a,i+1,right);//将数组一分为二后两侧顺序排好
    Merge(a,b,left,i,right);//将排完顺序的半成品数组完全排好:即合并到数组b
    Copy(a,b,left,right);//将排好序的数组重新放回数组a
    }
  }

  下面我们就具体说一说Merege和Copy这两个子函数的具体细节:

  template<class T>

  void Merge(T a[],T b[],int left,int mid,int right){//将当前范围(left-right)中的数据按一定次序存入b数组
      int i=left,j=mid+1;
      int t=0;
      while(i<=mid&&j<=right){
      if(a[i]>a[j]){
        b[t++]=a[j++];
      }else{
       b[t++]=a[i++];
      }
    }
    while(i<=mid){
    b[t++]=a[i++];
    }
    while(j<=right){
    b[t++]=a[j++];
    }

  }

  template<class T>

  void Copy(T a[],T b[],int left,int right){//将最后排好顺序的元素重新放回a

    int t=0;//此处应注意的是我们处理的数据是a数组中的,而合并排序时将每次排好顺序的数据放回a中,此时要特别注意放回的方式,要将数据放回原来的索引范围,

    for(int i=left;i<=right;i++){//而不是单纯的放回去,下面给出一张图帮助理解
    a[i]=b[t++];
    }
  }

  template<class T>

  void Copy(T a[],T b[],int left,int right){//这是将复制简单理解为复制回a后的错误函数
    int t=right-left+1;
    for(int i=0;i<t;i++){
    a[i]=b[i];//这样的后果就是改变a数组原有内容,造成意想不到的计算结果
    }
  }

原文地址:https://www.cnblogs.com/SoundCoder/p/7637694.html