归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
数据结构与算法分析C++描述中图解如下:
可以看出合并有序数列的效率是比较高的,可以达到O(n)。
解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组左,右,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将前,后组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
好了,废话少说,代码奉上
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::begin;
using std::end;
template <class T>
void print(const vector<T> &v)
{
for(auto &i : v)
{
cout << i << " ";
}
cout << endl;
}
//归并排序
template <class T>
void mergeSort(vector<T> &v)//启动归并排序
{
vector<T> temp(v.size());//temp用于连接排好序的两个数组
mergeSort(v,temp,0,v.size()-1);
}
template <class T>
void mergeSort(vector<T> &v,vector<T> &temp,int left,int right)//left排序数组元素下标,right排序数组元素的上标
{
if(left == right)//只有1个元素了,无需排序,直接返回
{
return;
}
else
{
int middle = (left + right)/2;
mergeSort(v,temp,left,middle);//左半部分排序------分的体现
mergeSort(v,temp,middle+1,right);//右半部分排序-----分的体现
merge(v,temp,left,middle,right);//对整个上、下部分合并-----治的体现
}
}
template <class T>
void merge(vector<T> &v,vector<T> &temp,int left,int middle,int right)
{
int leftPos = left; //左半部分数组开始下标
int leftEnd = middle; //左半部分数组结束下标
int rightPos = middle+1; //右半部分数组开始下标
int rightEnd = right; //右半部分数组结束下标
int length = right - left + 1;//2个数组总的元素个数
int tempPos = left;//第3方存贮数组开始下标
while(leftPos <= leftEnd && rightPos <= rightEnd)//依次比较2个数组,将其中小的元素放入第3方数组
{
if(v[leftPos] <= v[rightPos])
{
temp[tempPos++] = v[leftPos++];
}
else
{
temp[tempPos++] = v[rightPos++];
}
}
while(leftPos <= leftEnd)//左半部分数组未走完,依次copy至第3方数组
{
temp[tempPos++] = v[leftPos++];
}
while(rightPos <= rightEnd)//右半部分数组未走完,依次copy至第3方数组
{
temp[tempPos++] = v[rightPos++];
}
for(int i = 0; i < length;i++)//copy第3方数组元素至原数组
{
v[left+i] = temp[left+i];
}
}
int main()
{
int a[] = {5,2,4,6,1,3};
vector<int> v = vector<int>(begin(a),end(a));
cout<<"排序前数组:";
print(v);
mergeSort(v);
cout<<"排序后数组:";
print(v);
system("pause");
return 0;
}