0. 简述
归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。
作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:
- 自上而下的递归(所有递归的方法都可以用迭代重写);
- 自下而上的迭代;
1. 算法步骤
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
- 重复步骤 3 直到某一指针达到序列尾;
- 将另一序列剩下的所有元素直接复制到合并序列尾。
2. 动图演示
3. C++代码实现
迭代法
include <iostream>
#include <vector>
using namespace std;
int min(int x, int y)
{
return x < y ? x : y;
}
//迭代版
void Merge_Sort(vector<int> &v)
{
int len = v.size();
vector<int> temp(len);
int step; //步长
int i;
for (step = 1; step < len; step = step*2) //步长倍数增长
{
for (i = 0; i < len; i = i + step*2) //当前步长下,相邻两个分段数的比较(so每段要跳两个step(段))
{
int j = i; //temp[]起始位置应该与v[]一样
int low = i;
int mid = min(i + step, len);
int high = min(i + step * 2, len);
int start1 = low, end1 = mid;
int start2 = mid, end2 = high;
while (start1 < end1 && start2 < end2)
{
temp[j++] = v[start1] < v[start2] ? v[start1++] : v[start2++];
}
//首先,四个元素分为两两一组,各自肯定是排好序了的
//其次,在比较的过程中就肯定会出现有一组到头了,另一组还有没赋值的
//最后,就必须将剩下的全部放到新数列中
while (start1 < end1)
{
temp[j++] = v[start1++];
}
while (start2 < end2)
{
temp[j++] = v[start2++];
}
}
v = temp;
}
}
int main()
{
vector<int> v1 = {44,99,33,11,77,88,55,44,66,22};
Merge_Sort(v1);
for (auto i : v1) //可遍历容器<vector>遍历
{
cout << i << endl;
}
return 0;
}
递归法
#include <iostream>
#include <vector>
using namespace std;
/*
递归版归并排序算法运行过程:
--------
---- ----
-- -- ----
- -(左递归不成立,11插入排序) -- ----
-- - -(11插入排序) ----
-- --(22插入排序) ----
---- -- --
---- - -(11插入排序) --
---- -- - -(11插入排序)
---- -- --(22插入排序)
---- ----(44插入排序)
*/
void Merge(vector<int> &Array, int start, int mid, int end)
{
vector<int> temp(end - start + 1);
int i = 0;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
while (start1 <= end1&&start2 <= end2)//与迭代法的区别:end是参加比较的
temp[i++] = Array[start1] < Array[start2] ? Array[start1++] : Array[start2++];
while (start1 <= end1)
temp[i++] = Array[start1++];
while (start2 <= end2)
temp[i++] = Array[start2];
for (i = 0; i < temp.size(); i++)//下标细节
Array[i + start] = temp[i];
}
void Merge_Sort(vector<int> &Array, int start, int end)
{
if (start >= end)
return;
int mid = (start + end) / 2;
//左归并
Merge_Sort(Array, start, mid);
//右归并
Merge_Sort(Array, mid + 1, end);
//插入排序
Merge(Array, start, mid, end);
}
int main()
{
vector<int> v = { 99,66,55,77,22,88,33,44,11,0 };
int len = v.size() - 1;
Merge_Sort(v, 0, len);
for (auto i : v)
{
cout << i << endl;
}
return 0;
}