算法设计与分析第二章复习

递归与分治

本文主要讲解合并排序算法
算法思想 :
分而治之,将一个无序数列分成n个子列,然后再求解子列,最后合并成最终的答案。
核心特征 :局部有序到整体有序
算法设计:
本文采用递归法:
记函数名字为 MergeSort

以数组为例,由于是递归法,所以参数中必须有能让递归进行下去的参数,而将大数组分成小数组最重要的是要能知道数组的索引,(本文直接采用每次切开一半的做法,这样有利于合并),因此参数中必须包含该数组最左边和最右边的索引,记为left,right,由于长度可以直接由左右索引推导出来,不需要放在参数中,放在函数体中即可。

由于是递归,还要确定函数的base case。本题中很明显,将数组分的不能在分了也就是只剩下一个数就不需要在递归了,因此可以 将base case的条件记为left == right。

接下来就是主体部分了,根据分治的思想 可以很容易的得到,首先:分
分的时候需要注意,需要求解中间值,以便界定左右两个数组,这里需要注意中间值mid 应该
不应该等于 (right-left+1)/2 这是总共有多少数的求法,我们需要的数这一堆数中,中间位置的索引
应等于(left + right )/2。

然后 :治的话先考虑最简单的情形,左边一个数组有一个数,右边一个数组有一个数,那么左右两边交换下位置即可,当左右两边大于1个数的时候,这个时候直接交换就行不通了。首先应该考虑到,合并 实在小问题到大问题这个过程,因此可以知道,左右两边应该都是有序的。这时候问题就变成了 如何将两个有序数组合并一个数组,我们知道可以采用一个临时数组进行存储,然后在将结果拷贝回来。因此在算法的最初时候也应该开辟一个与待排列数组等大的临时数组。

至此,合并排序已经很清晰了。接下来上代码

void Merge(int arr[],int temp[],int left,int right,int mid){
		int tcount = left,lcount = left,rcount = mid+1;
		while(lcount<=mid&&rcount<=right){
				if(arr[lcount]>arr[rcount])
							temp[tcount++] = arr[rcount++];
				else
							temp[tcount++] = arr[lcount++];
		}
		while(lcount>mid&&rcount<=right){
				temp[tcount++] = arr[rcount++];
		}
		while(lcount<=mid&&rcount<=right){
				temp[tcount++] = arr[lcount++];
		}
		for(int i = left;i<=right;i++){
			arr[i] = temp[i];
	}



}

void MergeSort(int arr[],int temp[],int left,int right){
		if(left == right)
			return ;
		else
		{
			int mid = (left+right)/2;
			MergeSort(arr,temp,left,mid);
			MergeSort(arr,temp,mid+1,right);
			Merge(arr,temp,left,right,mid);
		}	
}

你可能感兴趣的:(算法)