排序算法大杂烩之归并排序

版权声明:本文为博主原创文章,若需转载,请评论说明,并在文章显著位置标明原文出处。 https://blog.csdn.net/lishang6257/article/details/83046861

排序算法大杂烩主干文章传送门

归并排序

#include <iostream>
#include <vector>

using namespace std;

//典型的分治策略,拆分,解决,合并
void Merge(vector<int> &a,int low,int high){
    vector<int> p1,p2;
    int mid = (low + high)/2;
    for(int i = low;i <= mid;i ++) p1.push_back(a[i]);
    for(int i = mid + 1;i <= high;i ++) p2.push_back(a[i]);
    vector<int>::size_type i = 0,j = 0,cur = low;
    while(cur <= high){
        if(i >= p1.size()) a[cur ++] = p2[j ++];
        else if(j >= p2.size()) a[cur ++] = p1[i ++];
        else if(p1[i] <= p2[j]) a[cur ++] = p1[i ++];
        else a[cur ++] = p2[j ++];
    }
}
void merge_sort(vector<int> &a,int low,int high){
    if(high == low) return;
    //high < low 异常不做处理
    int mid = (low + high)/2;
    merge_sort(a,low,mid);
    merge_sort(a,mid + 1,high);
    Merge(a,low,high);
    return;
}

int main()
{
    vector<int> a{2,3,4,5,1,9};
    merge_sort(a,0,a.size() - 1);
    for(auto c : a) cout << c << " ";
    cout << endl;
    return 0;
}

  • 思维引擎
  1. 归并排序仍然是经典的分治案例,分成三个部分完成分解,解决,合并
    • 问题定义:对序列 A [ 1.. n ] A[1..n] 经进行排序
    • 分解: 对子 A [ l . . h ] A[l..h] 划分成 A [ l . . m ] A[l..m] , A [ m + 1.. h ] A[m+1..h] 两个部分,其中 m = m + h 2 m = \lfloor \frac{m+h}{2} \rfloor
    • 解决:递归的解决两个子序列
    • 合并:将两个有序的子序列合并成一个有序的序列
  2. 如何合并两个子序列
    额外使用o(n)保存两个子序列,依次比较子序列的元素键值,然后按大小关系放入原序列的位置,这里需要注意的处理一个子序列已经遍历完成的情况。
  • 时间复杂度
    分治的时间复杂度计算不是很复杂,分别求出分解,解决,合并的时间复杂度,再相加就可以求出递归式了。
    T ( n ) = 2 T ( n / 2 ) + o ( n ) T ( n ) = o ( n l o g n ) T(n) = 2T(n/2) + o(n) \\ \Rightarrow T(n) = o(nlogn)
  • 空间复杂度
    在合并子问题时候需要 o ( n ) o(n) 的额外空间
  • 稳定性分析
    可以看到在合并子问题的过程中,能确保相同键值元素的相对位置的,所以是稳定排序算法

排序算法大杂烩主干文章传送门

猜你喜欢

转载自blog.csdn.net/lishang6257/article/details/83046861
今日推荐