数据结构与算法分析-C++描述 第7章 归并排序(mergeSort)

 归并序(mergeSort):

        归并排序以O(N\log N)最坏情形运行时间运行,所使用的比较次数几乎是最优的,而且是递归算法很好的例子。归并排序的基本操作是合并两个已排序的表。因为这两个表是已经排序的,所以若放到第三个表中,则该算法可以通过对输入数据的一趟排序来完成。

行为描述:

 算法描述:

        取两个输入数组A数组B、一个输出数组C及3个计数器(Actr, Bctr, Cctr),它们的初试位置对应于数组的开始,A[Actr]B[Bctr]中较小者被被复制到C中的下一个位置,相关计数器向前推进一个单位,当其中一个输入表用完时,另一个输入表的后续元素拷贝到C中。

归并排序的性质:【分析递归例程的经典实例,分而治之方法的经典体现】

       对于N= 1, 常数时间完成归并排序,对于N(N = 2^k)个数的归并排序用时等于完成大小为N/2的递归排序所用时间+合并所用时间,即   T(1) = 1, T(N) = T(N/2) + N

$$ \begin{align} \dfrac{T(N)}{N} =& \dfrac{T(N/2)}{N/2} +1 \\ \dfrac{T(N/2)}{N/2} =& \dfrac{T(N/4)}{N/4} +1 \end{align} $$

依次递推,对\log N项求和得:\dfrac{T(N)}{N} = T(1) + \log N,即:T(N) = N + N\log N = O(N\log N)

        虽然归并运算的运行时间为O(N\log N),但它很难用于主存排序,主要问题在于,合并两个排序的表需要线性附加内存,在整个算法中还需要花费大量时间拷贝数组到临时变量中并再次回填到原数组中,其结果是严重减慢了排序时间。此外,归并排序的运行时间很大程度上取决于数组中用于比较和移动所花费的时间。这些消耗和编程语言相关。

        对于其他语言(如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 !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值