首页 > 代码库 > 分治算法——归并排序与快速排序

分治算法——归并排序与快速排序

1、归并排序

分治思想:每次从中间分开为两个子问题,对每个子问题排序完成之后,将两个已排序的部分进行归并操作即得到最终排序的结果。

(1)如果数组S中元素个数为0或者1返回

(2)选取中间位置的元素下标,对左半部分SL递归排序,对右半部分SR递归排序

(3)将排好序的SL、SR进行归并后返回最终结果

平均时间复杂度O(NlogN),最坏情况也为O(NlogN),最好情况为O(N)。

C++模版实现:

template <typename T>
void TMergeSort(vector<T> & arr, vector<T> &tmp, int left, int right)
{
	if (left < right)
	{
		int mid = (left + right) / 2;
		TMergeSort(arr, tmp, left, mid);
		TMergeSort(arr, tmp, mid + 1, right);
		
		int leftPos = left, rightPos = mid + 1, tmpPos = left;
		while (leftPos <= mid && rightPos <= right)
			if (arr[leftPos] <= arr[rightPos])
				tmp[tmpPos++] = arr[leftPos++];
			else
				tmp[tmpPos++] = arr[rightPos++];
		while (leftPos <= mid) tmp[tmpPos++] = arr[leftPos++];
		while (rightPos <= right) tmp[tmpPos++] = arr[rightPos++];
		
		for (int i = left; i <= right; i++)
			arr[i] = tmp[i];
	}
}


2、快速排序

分治思想:分为子问题的时候是随机分,找一个枢轴元素,将此元素的位置找到。随机分的方法也可以使用三数取中值方法,对第一个、最后一个、中间位置元素进行判断,选取大小为中间的元素为枢轴元素,这样可以节约14%左右的比较次数。也可以使用最不安全的分法,就是每次选取第一个元素为枢轴。

(1)如果数组S中元素个数为0或者1,返回

(2)用选定的方法选取一个枢轴元素v

(3)将S-{v}划分为两个不相交的集合,其中S+ = {x | x >= v},S- = {x | x <= v}

(4)对S+和S- 分别进行递归排序,S- 、v、S+即为排序的最终结果

平均时间复杂度为O(NlogN),最坏情况为O(N^2),最好情况为O(NlogN)。

C++模版实现如下:

template <typename T>
void TQuickSort(vector<T> & p, int low, int high)
{
	if (low < high)
	{
		int l = low, h = high, m = (low + high) / 2, p_index;
		//三数取中值方法选择枢轴 
		T pivot;
		if ((p[l] <= p[m] && p[m] <= p[h]) || (p[h] <= p[m] && p[m] <= p[l]))
		{
			pivot = p[m];
			p_index = m;
		}
		if ((p[l] <= p[h] && p[h] <= p[m]) || (p[m] <= p[h] && p[h] <= p[l]))
		{
			pivot = p[h];
			p_index = h;
		}
		if ((p[m] <= p[l] && p[l] <= p[h]) || (p[h] <= p[l] && p[l] <= p[m]))
		{
			pivot = p[l];
			p_index = l;
		}
		
		while(l < h)
		{
			while (l < h && p[h] >= pivot) h--;
			p[p_index] = p[h]; p_index = h;
			while (l < h && p[l] < pivot) l++;
			p[p_index] = p[l]; p_index = l;
		}
	 	p[p_index] = pivot;
		TQuickSort(p, low, p_index);
		TQuickSort(p, p_index + 1, high);
	}
}


分治算法——归并排序与快速排序