(二)C++分治算法下的归并排序

分治算法下的归并排序

1、分治思想

将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解。

分治模式在每层递归时都有三个步骤:

(1)      分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。

(2)      解决这些子问题,递归地求解各子问题。然而,若子问题的规模足够小,则直接求解。

(3)      合并这些子问题的解成原问题的解。

2、归并算法

    归并排序算法完全遵循分治模式。其操作如下:

(1)      分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。

(2)      解决:使用归并排序递归地排序两个子序列。

(3)      合并:合并两个已排序的子序列以产生排序的答案。

    当待排序的序列长度为1时,递归“开始回升”,在这种情况下不要做任何工作,因为长度为1的每个序列都已排好序。

    归并排序算法的关键操作是“合并”步骤中两个已排序序列的合并。通过调用一个辅助过程MERGE(A,p,q,r)来完成合并,其中A是一个数组,p、q和r是数组下标,满足p≤q<r。该过程假设子数组A[p…q]和A[q+1…r]都已排好序。它合并这两个子数组形成单一的已排好序的子数组并代替当前的子数组A[p…r]。

3、归并算法伪代码

(1)过程MERGE需要O(n)的时间,其中n=r-p+1是待合并元素的总数。

伪代码如下:

MERGE(A,p,q,r)
 1 n1=q-p+1
 2 n2=r-p
 3 let L[1..n1+1] and R[1..n2+1] be new arrays
 4 for i=1 to n1
 5		L[i]=A[p+i-1]
 6 for j=1 to n2
 7		R[j]=A[q+j]
 8 L[n1+1]=∞
 9 R[n2+1]=∞
10 i=1
11 j=1
12 for k=p to r
13 	if L[i]≤R[j]
14		A[k]=L[i]
15		i=i+1
16	else A[k]=R[j]
17		j=j+1

(2)把过程MERGE作为归并排序算法中的一个子程序来用。MERGE-SORT(A,p,r)排序子数组A[p..r]中的元素。若p≥r,则该子数组最多有一个元素,所以已经排好序。否则,分解步骤简单地计算一个下标q,将A[p..r]分成两个子数组A[p..q]和A[q+1..r],前者包含 n/2个元素,后者包含 n/2个元素。

伪代码如下:

MERGE-SORT(A,p,r)
1 if p<r
2 	q=⌊(p+r)/2⌋
3		MERGE-SORT(A,p,q)
4		MERGE-SORT(A,q+1,r)
5		MERGE(A,p,q,r)

4、具体实现代码

#include <iostream>
using namespace std;

//打印数组
void PrintMergeSort(int arr[], int num)
{
	for (int i = 0; i < num; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return;
}

//归并排序
void Merge(int arr[], int des[], int low, int mid, int top)
{
	int i = low;
	int j = mid + 1;
	int k = low;
	
	while ((i <= mid) && (j <= top))//将小的放入des中
	{
		if (arr[i] < arr[j])
		{
			des[k++] = arr[i++];
		}
		else
		{
			des[k++] = arr[j++];
		}
	}

	while (i <= mid)//若还剩几个尾部元素,直接复制到des中
	{
		des[k++] = arr[i++];
	}

	while (j <= top)//若还剩几个尾部元素,直接复制到des中
	{
		des[k++] = arr[j++];
	}
	return;
}

//分治思想 把问题分解
void MSort(int arr[], int des[], int low, int top, int max)//des代表要拷到的目的地
{
	int *space = NULL;
	int mid = 0;
	if (low == top)//只有一个元素时,不需要归并,直接拷贝给des
	{
		des[low] = arr[low];
	}
	else//如果有多个元素,把问题分解
	{
		mid = (low + top) / 2;
		space = (int*)malloc(sizeof(int)*max);
	}
	
	//当剩下一个元素的时候,递归划分结束,然后开始merge归并操作
	if (space != NULL)
	{
		MSort(arr, space, low, mid, max);
		MSort(arr, space, mid + 1, top, max);
		Merge(space, des, low, mid, top);
	}
	free(space);
	return;
}

//归并排序
void MergeSort(int arr[], int len)
{
	MSort(arr, arr, 0, len - 1, len);
}

int maindm002()
{
	int len = 0;
	int array[] = { 2, 4, 5, 7, 1, 2, 3, 6 };

	//数组长度
	len = sizeof(array) / sizeof(*array);

	//原始数组
	cout << "The origin array:" << endl;
	PrintMergeSort(array, len);
	
	//归并排序
	MergeSort(array, len);

	//归并排序后的数组
	cout << "The MergeSort array:" << endl;
	PrintMergeSort(array, len);

	system("pause");
	return 0;
}


阅读更多
上一篇(九)队列的链式存储结构设计与实现
下一篇(三)最大子段和问题
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭