二路归并排序

二路归并排序主要运用了“分治算法”,分治算法就是将一个大的问题划分为n个规模较小而结构相似的子问题。

这些子问题解决的方法都是类似的,解决掉这些小的问题之后,归并子问题的结果,就得到了“大”问题的解。

  二路归并排序主旨是“分解”与“归并”

  分解:  

    1.将一个数组分成两个数组,分别对两个数组进行排序。

    2.循环第一步,直到划分出来的“小数组”只包含一个元素,只有一个元素的数组默认为已经排好序。

  归并:

    1.将两个有序的数组合并到一个大的数组中。

    2.从最小的只包含一个元素的数组开始两两合并。此时,合并好的数组也是有序的。

              

        图1. 归并排序过程                                  图2. 合并两个有序数组

                                                                                          

举例说明:

  1.图中原始数组为{2,4,7,5,8,1,3,6},数组中元素的个数为8个。首先将8个元素的数组二分,每次分解后,

数组中元素的数目为原数组的一半。直到分解为只含有一个元素的数组。

  2.将小的数组按序合并,每次合并后数组的大小为上层数组的一倍。此时数组中的元素都是按序排列的。

  3.在合并两个有序数组。如图2

下面的是自顶向下递归实现2路归并排序:

#include  <iostream>
using namespace std;

void  Merge(int * a, int low, int mid, int high)
{
	int i = low, j = mid + 1, p = 0;//对应a数组的下标
	int * r = new int[high - low + 1];//申请另一个对应大小的数组来存放排好序的数据
	while (i <= mid && j <= high)
	{
		r[p++] = (a[i] <= a[j]) ? a[i++] : a[j++];
	}
	while (i <= mid)
		r[p++] = a[i++];
	while (j <= high)
		r[p++] = a[j++];
	for (p = 0, i = low; i <= high; p++, i++)
		a[i] = r[p];//最后再把有序数据存进a数组中,使得a数组对应部分数据有序
	delete[] r;
}
//自顶向下(递归实现)
void MSort(int *a, int low, int high)
{
	if (low<high)
	{
		int mid = (low + high) / 2;
		MSort(a, low, mid);
		MSort(a, mid + 1, high);
		Merge(a, low, mid, high);
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	int a[] = { 2,4,7,5,8,1,3,6 };
	int n = sizeof(a) / sizeof(int);
	MSort(a, 0, n - 1);
	for (int i = 0; i<n; i++)
		cout << a[i] << " ";
	cout << endl;
	system("PAUSE");
	return 0;
}

  

  

参考资料:《算法导论》2.1章节

原文地址:https://www.cnblogs.com/wuyepeng/p/9819827.html