《算法之美》---归并排序

将一个大序列的排序问题分解为对两个或多个子序列的排序问题,然后对子序列递归使用同样的方式进行排序;在子序列排好序后,将结果合并起来即可。利用这种思想的排序方法就是著名的归并排序。之所以称为归并排序,是因为整个算法的成本由归并部分决定。

 

归并算法描述如下:

1)如果n=1,排序完成;

2)将序列分解为两个子序列A[1 ceiling(n/2)]A[ceiling(n/2)+1 n]

3)递归对子序列A[1 ceiling(n/2)]A[ceiling(n/2)+1 n]进行排序;

4)将排好序的两个子序列进行归并。

 

归并排序使用的是分治策略,而分治策略的关键是分解和合并。归并排序的分解很简单:直接将序列从中间斩断;但合并的时候需要将两个排好序的子序列按次序进行合适的穿插,从而获得原序列的一个排序。

合并时我们使用两个指针:一个指向A序列里下一个要归并的元素,一个指向B序列里下一个要归并的元素。每步我们对这两个指针所指的元素进行比较,小者被归并到C序列里,并将指向较小者的指针往后推进一个元素,另一个指针保持不动。这样循环往复直到一个子序列为空。这时,另一个子序列中剩下的所有元素直接复制到C序列末尾即可。

 

注意:归并排序在最坏、平均和最好情况下时间复杂度都是Θ(nlogn)。这是归并排序一个显著的特点:一视同仁。

/*

函数名:      MergeSort

功能:        归并排序

模板参数说明:T必须支持小于操作

参数说明:    data待排序数组, size待排序数组大小

前置条件:    data!=NULL, size>0

后置条件:    data按非降序排列

用法:  

#include <algorithm>

int arr[]={10,9,8,4,5,7,6,3,1,4};

MergeSort(arr, 10);

*/

template <typename T>

void MergeSort (T data[], int size)

{

         if ( size>1 )

         {

                   //预处理

                   int mid=size/2;

                   int numOfleft=mid;

                   int numOfright=size-mid;

                   T* left=new T[numOfleft];

                   T* right=new T[numOfright];

                   //分解

                   std::copy(data, data+numOfleft, left);

                   std::copy(data+numOfleft, data+size, right);

                   MergeSort(left, numOfleft);

                   MergeSort(right, numOfright);

                   //合并

                   std::merge(left, left+numOfleft, right, right+numOfright, data);

                   //清理

                   delete[] left;

                   delete[] right;

         }

}

 

/*

函数名:      MergeSort

功能:        归并排序

模板参数说明:T元素类型, Func函数对象或指针

参数说明:    data待排序数组, size待排序数组大小,f函数对象或指针

前置条件:    data!=NULL, size>0

后置条件:    dataf排列

用法:  

#include <algorithm>

bool cmp(int a, int b)

{ return a<b; }

int arr[]={10,9,8,4,5,7,6,3,1,4};

MergeSort(arr, 10cmp);

*/

template <typename T, typename Func>

void MergeSort (T data[], int size, Func f)

{

         if ( size>1 )

         {

                   int mid=size/2;

                   int numOfleft=mid;

                   int numOfright=size-mid;

                   T* left=new T[numOfleft];

                   T* right=new T[numOfright];

                   std::copy(data, data+numOfleft, left);

                   std::copy(data+numOfleft, data+size, right);

                   MergeSort(left, numOfleft, f);

                   MergeSort(right, numOfright, f);

                   std::merge(left, left+numOfleft, right, right+numOfright, data, f);

                   delete[] left;

                   delete[] right;

         }

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值