归并序(mergeSort):
归并排序以最坏情形运行时间运行,所使用的比较次数几乎是最优的,而且是递归算法很好的例子。归并排序的基本操作是合并两个已排序的表。因为这两个表是已经排序的,所以若放到第三个表中,则该算法可以通过对输入数据的一趟排序来完成。
行为描述:
算法描述:
取两个输入数组A数组B、一个输出数组C及3个计数器(),它们的初试位置对应于数组的开始,和中较小者被被复制到C中的下一个位置,相关计数器向前推进一个单位,当其中一个输入表用完时,另一个输入表的后续元素拷贝到C中。
归并排序的性质:【分析递归例程的经典实例,分而治之方法的经典体现】
对于N= 1, 常数时间完成归并排序,对于N()个数的归并排序用时等于完成大小为N/2的递归排序所用时间+合并所用时间,即
依次递推,对项求和得:,即:。
虽然归并运算的运行时间为,但它很难用于主存排序,主要问题在于,合并两个排序的表需要线性附加内存,在整个算法中还需要花费大量时间拷贝数组到临时变量中并再次回填到原数组中,其结果是严重减慢了排序时间。此外,归并排序的运行时间很大程度上取决于数组中用于比较和移动所花费的时间。这些消耗和编程语言相关。
对于其他语言(如Java),排序一般对象时,元素的比较耗时较多,但元素的移动耗时较小,而在所有的排序算法中,归并排序使用最少次数的比较,因此,在Java中,归并排序是一般目的排序的最佳选择。事实上,Java标准库的一般排序就是采用的归并排序算法。
对于C++语言,当对象很大时,复制一般的对象代价是很大的,而对象的比较相对消耗较小,这是因为编译器在处理函数模板的扩展时具有强大的执行在线优化能力。在C++的排序算法中,普通排序通常使用的是快速排序算法。
归并排序实例:
//mergeSort.cpp
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//mergeSort vector
template<class Comparable>
void mergeSort(vector<Comparable> &v);
//mergeSort inner part to be ordered small array
template<class Comparable>
void mergeSort(vector<Comparable> &v, vector<Comparable> &temArray, int left, int right);
//merge v_left and v_riht part
template<class Comparable>
void merge(vector<Comparable> &v, vector<Comparable> &temArray, int leftPos, int rightPos, int rightEnd);
int main(){
int arr[] = {81, 94, 11, 96, 12, 35, 17, 95, 28, 58, 41, 75, 15};
int len = sizeof(arr) / sizeof(arr[0]);
vector<int> v;
for(int i = 0 ; i < len; i++){
v.push_back(arr[i]);
}
cout << "******* the original data ***********" << endl;
for(typename vector<int>::iterator itr = v.begin(); itr != v.end(); ++itr){
cout << *itr << " ";
}
cout << endl;
cout << "******* the sorted data ***********" << endl;
mergeSort(v);
for(typename vector<int>::iterator itr = v.begin(); itr != v.end(); ++itr){
cout << *itr << " ";
}
cout << endl;
cout << " done ." << endl;
return 0;
}
template<class Comparable>
void mergeSort(vector<Comparable> &v){
vector<Comparable> temArray(v.size());
mergeSort(v, temArray, 0, v.size() - 1);
}
template<class Comparable>
void mergeSort(vector<Comparable> &v, vector<Comparable> &temArray, int left, int right){
if(left < right){
int center = (left + right) / 2;
//iterative merge left part
mergeSort(v, temArray, left, center);
//iterative merge right part
mergeSort(v, temArray, center + 1, right);
//merge the left part and right part
merge(v, temArray, left, center + 1, right);
}
}
template<class Comparable>
void merge(vector<Comparable> &v, vector<Comparable> &temArray, int leftPos, int rightPos, int rightEnd){
int leftEnd = rightPos - 1;
int temPos = leftPos;
int numElements = rightEnd - leftPos + 1;
//left part and right part has same size
while(leftPos <= leftEnd && rightPos <= rightEnd){
//compare the two parts and assingn the smaller value to temArray
if(v[leftPos] < v[rightPos]){
temArray[temPos++] = v[leftPos++];
}else{
temArray[temPos++] = v[rightPos++];
}
}
//if left part has more elements, insert into the temArray last
while(leftPos <= leftEnd){
temArray[temPos++] = v[leftPos++];
}
//if right part has more elements, insert into the temArray last
while(rightPos <= rightEnd){
temArray[temPos++] = v[rightPos++];
}
//copy the sorted temArray to vector v
for(int i = 0; i < numElements; i++, rightEnd--){
v[rightEnd] = temArray[rightEnd];
}
}
practice makes perfect !