归并排序(merge sort)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
如图所示,对长度为4的序列进行归并排序:
1.首先,把长度为4的序列分解成长度为2的两个子序列;
2.然后,把长度为2的数组分解成两个长度为1的子数组;
3.然后,把长度为1的数组合并、排序成长度为2的有序序列;
4.最后,把长度为2的序列合并排序成长度为4的序列,结束。
递归实现思路是自顶向下,先拆分再合并
代码如下:
template <typename ElementType>
void merge(ElementType* data, ElementType* copy, int begin, int end)
{
int mid = (end + begin) / 2; //左区间的终点
int left = begin; //左区间的起点
int right = mid + 1; //右区间起点
int copyIndex = begin; //拷贝数组起点
while(left <= mid && right <= end)
{
if(data[left] <= data[right])
copy[copyIndex++] = data[left++];
else
copy[copyIndex++] = data[right++];
}
//拷贝剩下的元素
while(left <= mid)
copy[copyIndex++] = data[left++];
while(right <= end)
copy[copyIndex++] = data[right++];
//把排序后的区间数据复制到原始数据中去
for(int i = begin; i <= end; ++i)
data[i] = copy[i];
}
template <typename ElementType>
void mergeSortCore(ElementType* data, ElementType* copy, int begin, int end)
{
if(begin < end)
{
int mid = (end + begin) / 2;
//拆分
mergeSortCore(data, copy, begin, mid);
mergeSortCore(data, copy, mid + 1, end);
//合并
merge(data, copy, begin, end);
}
}
template <typename ElementType>
void mergeSort(ElementType* data, unsigned int length)
{
ElementType* copy = new(nothrow) ElementType[length];
if(copy == NULL)
{
cerr << "Allcation Error!!!" << endl;
exit(1);
}
mergeSortCore(data, copy, 0, length - 1);
delete []copy;
}
非递归的思路是自底向上,从长度为1开始一步步合并
代码如下:
template <typename ElementType>
void mergeSort(ElementType* data, int length)
{
ElementType* copy = new(nothrow) ElementType[length];
if(copy == NULL)
{
cerr << "Allocation Error!!!" << endl;
exit(1);
}
int begin = 0;//区间开始处
int step = 1;//步长
while( step < length)
{
begin = 0;
while(begin + step < length)
{
merge(data, copy, begin, min(begin + 2 * step - 1, length - 1));
begin += 2 * step;//同一步长的下一区间
}
step *= 2;//步长每次加倍
}
}