版权声明:本文为博主原创文章,若需转载,请评论说明,并在文章显著位置标明原文出处。 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;
}
- 思维引擎
- 归并排序仍然是经典的分治案例,分成三个部分完成分解,解决,合并
- 问题定义:对序列 经进行排序
- 分解: 对子 划分成 , 两个部分,其中
- 解决:递归的解决两个子序列
- 合并:将两个有序的子序列合并成一个有序的序列
- 如何合并两个子序列
额外使用o(n)保存两个子序列,依次比较子序列的元素键值,然后按大小关系放入原序列的位置,这里需要注意的处理一个子序列已经遍历完成的情况。
- 时间复杂度
分治的时间复杂度计算不是很复杂,分别求出分解,解决,合并的时间复杂度,再相加就可以求出递归式了。
- 空间复杂度
在合并子问题时候需要 的额外空间 - 稳定性分析
可以看到在合并子问题的过程中,能确保相同键值元素的相对位置的,所以是稳定排序算法。