2.分并排序

2.分并排序

方法

1.确定分界点:mid (0+n)/2

2.递归排序left,right(分成两个数组)

3.(重点)归并---合二为一

用两个指针从开头比较

 

 

 

 

(稳定)

遇到相同的先把第一个输出,保证数组里的相同数的位置是不变的

先分成好几段

先递归分成好几段

再和并

在这里插入图片描述

代码

优雅的分并

#include<iostream>using namespace std;
const int N=1e6+10;
int n;
int q[N],tmp[N];
void merge_sort(int q[],int l,int r)
{
    if(l>=r) return;//如果数组小于等于一个,直接出去
    int mid=(l+r)>>1;//相当于除于二(把l+r看作二进制向右退一位,向下取整)(l+r<<1,相当于乘以2)
    merge_sort(q,l,mid),merge_sort(q,mid+1,r);//递归分成好多段
    
/*为什么不用 mid - 1 作为分隔线呢
​
即 merge_sort(q, l, mid - 1 ), merge_sort(q, mid, r)
​
因为 mid = l + r >> 1 是向下取整,mid 有可能取到 l (数组只有两个数时),造成无限划分
​
解决办法: mid 向上取整就可以了, 即 mid = l + r + 1 >> 1
*/
   
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r)//不能越过边境
        if (q[i]<=q[j]) tmp[k++]=q[i++];//合并
        else tmp[k++]=q[j++];
    while(i<=mid) tmp[k++]=q[i++];//如果有一半有剩余的全给tmp数组
    while(j<=r) tmp[k++]=q[j++];
    
    for(i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];//把tmp再还给q
​
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    
    merge_sort(q,0,n-1);
    
    for(int i=0;i<n;i++)printf("%d ",q[i]);
    
    return 0;
}

 

 
posted @ 2022-05-18 21:39  scanfppp  阅读(30)  评论(0编辑  收藏  举报