归并排序
算法思想
归并排序的思想就是利用分治算法。
分治算法: 将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解后进行合并,就可以得到原问题的解。
归并算法的实现步骤:
- 分解,将要解决的问题划分为若干个规模较小的同类问题
- 求解,当子问题划分得到足够小时,用较简单的方法解决
- 合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
归并排序是先将大区间划分为一个个小区间,进行排序。先局部有序,再整体有序。 (黑色为分解过程,红色为合并的过程)
代码实现
void merge(vector<int>& sub_vec1, vector<int>& sub_vec2,
vector<int>& vec)
{
int i = 0;
int j = 0;
while (i < sub_vec1.size() && j < sub_vec2.size())
{
if (sub_vec1[i] <= sub_vec2[j])
{
vec.push_back(sub_vec1[i]);
i++;
}
else
{
vec.push_back(sub_vec2[j]);
j++;
}
}
for (; i < sub_vec1.size(); i++)
{
vec.push_back(sub_vec1[i]);
}
for (; j < sub_vec2.size(); j++)
{
vec.push_back(sub_vec2[j]);
}
}
void merge_sort(vector<int>& vec)
{
if (vec.size() < 2)
{
return;
}
int mid = vec.size() / 2;
vector<int> sub_vec1;
vector<int> sub_vec2;
for (int i = 0; i < mid; i++)
{
sub_vec1.push_back(vec[i]);
}
for (int i = mid; i < vec.size(); i++)
{
sub_vec2.push_back(vec[i]);
}
merge_sort(sub_vec1);
merge_sort(sub_vec2);
vec.clear();
merge(sub_vec1, sub_vec2, vec);
}
int main()
{
vector<int> v = { 6, 7, 1, 4, 4, 8, 6 };
merge_sort(v);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
system("pause");
}
时间复杂度:O(N*lgN)
假设有n个元素,n个元素归并排序的时间为T(n)。
总时间 = 分解时间 + 解决子问题时间 + 合并时间
分解时间: 即对原问题拆解为两个子问题的时间复杂度O(N)
解决两个子问题的时间: 2T(n/2)
合并时间:对已排好序的数组进行合并O(N)
T(n) = 2T(n/2) + 2O(N)
= 2T(n/2) + O(N)
= O(N + 2n/2 + 4n/4 + 8n/8…)
= O(NlgN)
也就是 在每一层都是N个节点,每一层的时间消耗都是O(N),但是二叉树中一共有logN层,所以总的时间复杂度就是O(N*logN)
空间复杂度 O(N)
用到了额外的一个数组vec,所以总的空间复杂度是O(N)