归并排序(merge_sort)(及自底向上的归并排序)

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

分析过程:

将一个目标排序数组,采用二分法,一直递归分解,直到数量为1,开始两两比较排序合并,最终完成目标数组合并排序。

示例代码:

#include <bits/stdc++.h>

using namespace std;

void merge(int *a,int l,int mid,int r){
    int temp[r-l+1];//临时存储数组,合并时使用 
    for(int i=l;i<=r;i++)
        temp[i-l]=a[i];

    int k0=l,k1=mid+1;
    for(int k=l;k<=r;k++){
        if(k0>mid){ //左边处理结束 
            a[k]=temp[k1-l];
            k1++;
        }
        else if(k1>r){//右边处理结束 
            a[k]=temp[k0-l]; 
            k0++;        
        }
        else if(temp[k0-l]<=temp[k1-l]){//左边<右边 
            a[k]=temp[k0-l];
            k0++;
        }
        else{//右边小于左边 
            a[k]=temp[k1-l];
            k1++;
        }
    }
//  for(int i=l;i<=r;i++)
//      cout<<a[i]<<" ";
//  cout<<endl;

}


void merge_sort(int *a,int l,int r){

    if(l>=r)    return; // 划分数组大小为1时返回 
    int mid=(l+r)/2;//取中间值 
    merge_sort(a,l,mid); //左边范围递归 
    merge_sort(a,mid+1,r);//右边范围递归 

    merge(a,l,mid,r);//合并排序 
}


int main(){
    int n;
    cin>>n;
    int arr[n];
    for(int i=0;i<n;i++){
        cin>>arr[i];
    }
    merge_sort(arr,0,n-1);
    for(int i=0;i<n;i++)
        cout<<arr[i]<<" ";
    return 0;
}

自底向上归并排序:
这里写图片描述
还有可以直接采用自底向上归并排序,不用递归。首先直接从相邻合并,步长依次成倍递增。

void merge_sort1(int *a,int n){
    for(int sz=1;size<n;sz*=2) //步长成倍递增 
        for(int k=0;k<n-sz;i+=sz*2)//两两合并 
            merge(a,i,i+sz-1;min(i+2*sz-1,n-1));//使用min,防止右边界越界 
}

猜你喜欢

转载自blog.csdn.net/qq_29377279/article/details/79532809