归并排序的基本操作是合并两个已排序的表。因为两个表是已排序的,所以若将输出放到第三个表中则该算法可以通过对输入数据一趟排序来完成。基本的合并算法是取两个输入数组A和B、一个输出数组C以及三个计数器(Actr、Bctr、Cctr),他们的初始位置位于对应数组的初始端。A[Actr]和B[Bctr]中的较小者被复制到C[Cctr],相关的计数器向下移动一步。当两个输入表一个用完时,则将另一个表中的剩余部分拷贝到C中。具体递归算法用C++描述如下:
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
/**
* Internal method that merge two sorted halvas of a subarray.
* data is an array of Comparable items.
* tmpArray is an array to place the merged result.
* leftPos is the left-most index of the subarray.
* rightPos is the index of the start of the second half.
* rightEnd is the right-most index of the subarray.
*/
template <class Comparable>
void merge(vector<Comparable> &data, vector<Comparable> &tmpArray, int leftPos, int rightPos, int rightEnd)
{
int leftEnd = rightPos - 1;//the index of the start of the first half.
int tmpPos = leftPos; //the index of the start of the tmpArray.
int numElements = rightEnd - leftPos + 1; //the number of the items
//merge
while(leftPos <= leftEnd && rightPos <= rightEnd)
{
if(data[leftPos] < data[rightEnd])
{
tmpArray[tmpPos++] = data[leftPos++];
}
else
{
tmpArray[tmpPos++] = data[rightPos++];
}
}
if(leftPos > leftEnd)
{
while(rightPos <= rightEnd)
{
tmpArray[tmpPos++] = data[rightPos++];
}
}
else
{
while(leftPos <= leftEnd)
{
tmpArray[tmpPos++] = data[leftPos++];
}
}
//copy tmpArray back
for(int i=0; i<tmpPos; ++i)
{
data[i] = tmpArray[i];
}
}
/**
* Internal method that makes recursive calls.
* data is an array of Comparable items.
* tmpArray if an array to place the merged result.
* left is the start index of the subArray.
* right is the end index of the subArray.
*/
template <class Comparable>
void mergeSort(vector<Comparable> &data, vector<Comparable> &tmpArray, int left, int right)
{
if(left < right)
{
int center = (left+right) / 2;
mergeSort(data, tmpArray, left, center);
mergeSort(data, tmpArray, center+1, right);
merge(data, tmpArray, left, center+1, right);
}
}
/**
* mergeSort algorithm.
*/
template <class Comparable>
void mergeSort(vector<Comparable> &data)
{
vector<Comparable> tmpArray(data.size());
mergeSort(data, tmpArray, 0, data.size()-1);
}
int main(void)
{
int ary[] = {0, 1, 9, 2, 8, 4, 5, 3, 6, 7};
vector<int> data(ary, ary+sizeof(ary)/sizeof(int));
mergeSort(data);
copy(data.begin(), data.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
归并排序的分析:
归并排序是用于分析递归例程技巧的经典实例:必须给运行时间写出一个地推关系。假设N是2的幂,从而总可以将它分成相等的两部分。对于N=1,归并排序所用的时间是常数,我们将其记为1。否则,对于N个数归并排序的用时相等于完成两个大小为N/2的递归排序所用的时间再加上合并的时间,他是线性的。下述方程给出准确的表示:T(1) = 1
T(N) = 2T(N/2)+N
T(N) = NlogN+N = O(NlogN)这是一个标准的地推关系,求解后得到这样的公式: