归并排序模版

86 阅读3分钟

归并我们可以同样套模版,首先找个边界1,这个边界我们就用MID。 然后我们把从MID开始分为两部分。

像这种情况,我们应该用MID=r+l+1/2,因为是偶数个:

image.png 所以我们的MID应该为(0+7+1/2=(8/2)=4 此刻我们就变形为如下这个样子了:

image.png 然后我们把R指针移动到MID+1的位置,然后和L指针进行比较,谁小谁就放到temp里面:

image.png 4比9小1,放TEMP里面,然后L++,挪到5头上,K++,跳到下一个位置:

image.png 接着比较L和R,5比9小,5放K那里,++:

image.png 7比9小,挪动。 9小于等于9,再挪:

image.png 这个时候我们就发现问题了,左边都排完了,但是3却比前面的数都小,这就有问题了,所以我们一开始不能直接把MID拿过来放中间,我们可以把3放到右半部分的开头,让R=MID:

image.png 这样的话就可以先比较3和4的值,把3先排过去了。这样排完之后是这个样子:

image.png 这个时候我们发现右半部分还剩好多。那我们就把它跟x,也就是MID 3作对比,如果小于MID就放过去

但是,我们发现,放过去之后也不行,这个4显得有点突兀:

image.png 实际上,因为我们的前半部分刚好是一个有序的,所以才可以正常排,假设我们前半部分也是一个乱序的:

image.png 那么排完之后应该是:

image.png

这个结果明显不是我们需要的,假设我们的前半部分和后半部分都是有序的:

image.png 那么这样排完之后应该是:

image.png 这个结果才是我们想要的,所以我们应该对前半部分和后半部分先排序,具体的排序方法用递归:

归并排序——一文吃透归并和递归的思想和完整过程!(没看懂请留言) - 少年π - 博客园 (cnblogs.com)

总结,归并模版

先分治,再递归,后合并。

归并

#include<iostream>  
using namespace std;  
const int N=1e6+10;  
int n=0;  
int q[N];  
int temp[N];


void G_qsort(int q[],int l,int r)
{
    
    //递归结束条件
    if(l>=r) return;
    
      
    //首先确定主元
    int mid=l+r>>1;
    
    
    G_qsort(q,l,mid);      //左区间排序
    _qsort(q,mid+1,r);  //右区间排序
    int i=l,j=mid+1, k=0;

    
    while(i<=mid && j<=r)//递归结束条件
    //谁小谁往temp里面放
    if(q[i]<=q[j])  temp[k++]=q[i++];
    else temp[k++]=q[j++];
    
    
    
    //如果有一个指针走完了,另一个指针还没走完,就把剩下的值也放到temp里
    while(i<=mid) temp[k++]=q[i++];
    while(j<=r) temp[k++]=q[j++];
    
    
    for(int i=l,j=0;i<=r;i++,j++)
    {
         q[i]=temp[j];
    }
    
    

    //放回到q
   // for(int i=0;i<r;i++)
  //  {
    //    q[i]=temp[i];
    //}
}
int main()  
{
   scanf("%d",&n);
   for(int i=0;i<n;i++)  
   {  
       scanf("%d",&q[i]);  
   }  
   
   G_qsort(q,0,n-1);  
   
   for(int i=0;i<n;i++)  
   {  
      printf("%d ",q[i]);
   }  
   return 0;  
}