归并排序

时间复杂度:O(nlogn)二分一次需要logn表示层数,每一层元素个数n个

空间复杂度:O(n)需要数组同样大小的临时空间

 

将数组按照二分法,分成两块,分别各自排顺序

给出如下数组

 

将两部分分别排好序

 

然后用分别排好序的数组

 

首先,将原数组复制一遍,蓝色箭头表示原数组,红色箭头表示新数组

 

将复制的数组分成两部分,每一个部分的第一个元素进行比较

 

 

 

选出小的元素放入原数组,蓝色箭头后移到下一位,选中的红色箭头也后移到下一位

 

每一轮,红色数组前半部分和后半部分的元素进行比较,将小的元素填入蓝色数组。之后选择下一个元素进入下一轮比较,以此类推

 

定义三个标记位置

 

ij表示需要比较的元素,k表示比较后需要放入的位置

 

知道了归并的思想,再用递归的方法写归并函数

//将arr[l,mid]和arr[mid+1,r]两部分进行归并
template<typename T>
void __merge(T arr[], int l, int mid, int r) {//确定元素放置在原数组中的位置
    T aux[r - l + 1];
    for(int i=l;i<=r;i++){
        aux[i-l] == arr[i];
    }
    int i = l, j = mid + 1;
    for (int k = l; k <= r; k++) {
        if(i>mid){//判断是否越界
            arr[k] = aux[j-l];
            j++;
        }
        else if (j > r) {//判断是否越界
            arr[k] = aux[i - l];
            i++;
        }
        else if (aux[i - l] < aux[j - l]) {//如果i-1小,i-1就放入k中
            arr[k] = aux[i - l];
            i++;
        }
        else {//如果j-1小,j-1就放入k中
            arr[k] = aux[j - l];
            j++;
        }
    }
}

//递归使用归并排序,对arr[l,r]范围进行排序
template <typename T>
void __mergeSort(T arr[], int l, int r) {
    if (l >= r) {//一个元素都没有,数据集为空
        return;
    }
    int mid = (l + r) / 2;
    __mergeSort(arr, l, mid);//左半部分归并排序
    __mergeSort(arr, mid + 1, r);//右半部分归并排序
    __merge(arr, l, mid, r);//归并
}

template<typename T>
void mergeSort(T arr[], int n) {
    __mergeSort(arr, 0, n - 1);//第n个是空的,n-1有值
}

 优化:

当左半部分最大值小于右半部分最小值的时候,整个数组已经完成排序,无需继续进行排序

if(arr[mid]>arr[mid+1]){
    __merge(arr,l,mid,r);    
}

 常见的递归型并归排序

#include<iostream>
using namespace std;
const int maxn=100001;
//将数组A的左区间与右区间合并为有序区间 
void merge(long A[],int L1,int R1,int L2,int R2){
    int i=L1,j=L2;
    int temp[maxn],index=0;
    while(i<=R1&&j<=R2){
        if(A[i]<=A[j]){
            temp[index++]=A[i++];
        }
        else{
            temp[index++]=A[j++];
        }
    }
    while(i<=R1){
        temp[index++]=A[i++];
    }
    while(j<=R2){
        temp[index++]=A[j++];
    }
    for(int i=0;i<index;i++){
        A[L1+i]=temp[i];
    }
}

//将array数组当前区间left,right进行并归 
void mergeSort(long A[],int left, int right){
    if(left<right){
        int mid=(left+right)/2;
        mergeSort(A,left,mid);
        mergeSort(A,mid+1,right);
        merge(A,left,mid,mid+1,right);
    }
}

int main(){
    int n;
    cin>>n;
    long* num=new long[n];
    for(int i=0;i<n;i++){
        cin>>num[i];
    }
    mergeSort(num,0,n-1);
    for(int i=0;i<n;i++){
        cout<<num[i]<<" ";
    }
    return 0;
} 

 

posted @ 2020-08-01 10:40  Heinrich♣  阅读(158)  评论(0编辑  收藏  举报