这一章节所讲的归并排序,跟希尔排序一样,也是一种效率很高的排序方法,也同样采用了分而治之的方法.
归并排序的基本思想为:先把无序序列一分为二,然后分别对两边的序列进行排序,最后再整合两边已经排好的序列.下边已一张图来展示归并排序的思想(图是借用网友的,见做的非常简洁易懂,便引用之)
从途中我们看到,二分后的两边序列,又进行二分归并处理,直到两边的序列不能二分为止.这就是采用的递归思想,出口为左右了;两边各只有一个元素,然后再将两边的有序序列归并成最终序列.下边看代码理解:
#include <iostream>
#include <string.h>
#include <errno.h>
#include <stdio.h>
using namespace std;
//需要注意的是,这里的类模板需要放在头文件中去实现,这里为了直观,直接放这里了
template <typename T>
class Sort
{
private:
//合并两边的有序序列
static void Merger(T* nArray, int nBegin, int nMid, int nEnd, bool Min2Max=true)
{
int len = nEnd - nBegin + 1;
T tmp[len]; //申请一个临时空间,存放合并后的序列
int lIndex = nBegin; //左边有序序列的其实位置
int rIndex = nMid + 1;//右边有序序列的起始位置
int k = 0; //临时空间的起始位置
//分别从二分的左边第一个元素,右边的第一个元素开始比较,依次将二者的极值放到临时空间中
while( (lIndex <= nMid)&&(rIndex <= nEnd))
{
if( Min2Max ? (nArray[lIndex] < nArray[rIndex]):(nArray[lIndex] > nArray[rIndex]))
{
tmp[k++] = nArray[lIndex++];
}
else
{
tmp[k++] = nArray[rIndex++];
}
}
//把左边剩余的元素追加到临时空间中
while(lIndex <= nMid)
{
tmp[k++] = nArray[lIndex++];
}
//或者把右边剩余的元素追加到临时空间中
while(rIndex <= nEnd)
{
tmp[k++] = nArray[rIndex++];
}
//将临时空间排好序的元素放到原序列空间中
for(int i=nBegin, k=0; i<=nEnd; i++)
{
nArray[i] = tmp[k++];
}
}
//归并排序(注意采用的是递归方式)
static void Merger(T* nArray, int nBegin, int nEnd, bool Min2Max = true)
{
if(nBegin != nEnd)
{
int Mid = (nEnd + nBegin)/2; //将序列一分为二
Merger(nArray, nBegin, Mid, Min2Max);//对左边的序列进行归并排序
Merger(nArray, Mid+1, nEnd, Min2Max);//对右边的序列进行归并排序
Merger(nArray, nBegin, Mid, nEnd, Min2Max); //合并左右两边已经排好序的序列
}
}
public:
static void Merger(T* nArray, int nLen, bool Min2Max = true)
{
Merger(nArray, 0, nLen-1, Min2Max);
}
};
int main(int argc, char* argv[])
{
int array[] = {12,32,2,4,6,54,13,34,25,87,76,89,32,14,23};
int len = sizeof(array)/sizeof(int);
Sort<int>::Merger(array, len);
for(int i=0; i<len; i++)
{
cout << array[i] << " ";
}
cout << endl;
return 0;
}
编译测试