一.基本思想
归并排序是建立在归并操作上的一个有效排序算法,该算法是分治法的典型应用。将已有的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序;如果将两个子序列合并成一个序列,称为二路归并。
二.图解算法步骤
排序步骤:
- 递归找到序列的中间位置,将序列分为两部分,直到不能再继续分为止
- 递归排序分成的两部分;具体可以开一个辅助空间,空间大小为要排序的节点个数,对辅助空间进行初始化;
- 用两个索引记录左序列起始位置和右序列起始位置,如果左索引大于中间位置mid,则原数组对应位置值为右边索引对应的值,++右索引;如果右索引值大于最右位置,则原数组对应位置值为左边索引对应的值,++左索引。
- 如果左边索引位置的值小于/等于右边索引位置的值,则对给定序列的对应位置值为左边索引值,左索引+1;如果左边索引位置的值大于右边索引位置的值,则对给定序列的对应位置值为右边索引值,右索引+1;
三.代码实现
#include<iostream>
#include<vector>
using namespace std;
void mergesort(vector<int>& v, int l, int r, int mid)
{
vector<int> tmp(r - l + 1); //开具体节点个数的辅助空间
for (int i = l; i <= r; ++i)
{
tmp[i - l] = v[i]; //初始化辅助空间
}
int st = l;
int right = mid + 1;
for (int i = l; i <= r; ++i)
{
if (st > mid)
{
v[i] = tmp[right - l];
++right;
}
else if (right > r)
{
v[i] = tmp[st - l];
++st;
}
else if (tmp[st - l] >= tmp[right - l])
{
v[i] = tmp[right - l];
++right;
}
else
{
v[i] = tmp[st - l];
++st;
}
}
}
void merge_sort(vector<int>& v, int l, int r)
{
if (l >= r)
return;
int mid = (l + r) / 2;
merge_sort(v, l, mid);
merge_sort(v, mid + 1, r);
mergesort(v, l, r, mid);
}
int main()
{
vector<int> v{ 1, 3, 2, 5, 7, 0, 4 };
int len = v.size();
merge_sort(v, 0, len - 1);
for (int i = 0; i < len; ++i)
{
cout << v[i]<<' ';
}
cout << endl;
return 0;
}
结果: