【软工作业】什么是分而治之?

        分而治之,出自《群经平议·周官二》。意思是分别治理;利用手段使国家、民族或宗教等产生分裂,然后对其进行控制和统治。而在计算机中,分治是一种分目标完成程序算法。分治算法的思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同,而求出子问题的解,就可得到原问题的解;简单问题可用二分法完成。

        当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。

        

        分治法主要由两部分构成:

        1、 分(divide):递归解决较小的问题。

        2、 治(conquer):然后从子问题的解构建原问题的解。

        分治法的三个步骤:

        1. 分解(Divide):将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
        2. 解决(Conquer):若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
        3. 合并(Combine):将各个子问题的解合并为原问题的解。

——【接下来通过一个例子来方便理解】——

题目:使用归并排序对一组数字按从小到大排列。

        归并排序的定义:分而治之,将一个无序的数列一直一分为二,直到分到序列中只有一个数的时候,这个序列肯定是有序的,因为只有一个数,然后将两个只含有一个数字的序列合并为含有两个数字的有序序列,这样一直进行下去,最后就变成了一个大的有序数列;递归的结束条件是分到最小的序列只有一个数字的时候。

        参考代码如下:

int merge(int SR[], int TR[], int s, int m, int t)
//SR代表两个有序序列构成的序列,s表示起始位置,m表示两个序列的分解位置,但是SR[m]仍是属于前面一个序列,t表示结束位置
{//TR是一个空数组,用来存放排序好之后的数字
	int i = s, j = m + 1, k = s;
	while (i <= m && j <= t)
	{
		if (SR[i] < SR[j])
		{
			TR[k++] = SR[i++];
		}
		else
		{
			TR[k++] = SR[j++];
		}
	}
	while (i <= m)//当前面一个序列有剩余的时候,直接把剩余数字放在TR的后面
	{
		TR[k++] = SR[i++];
	}
	while (j <= t)//当后面一个序列有剩余的时候,直接把剩余数字放在TR的后面
	{
		TR[k++] = SR[j++];
	}
	return 0;
}//该函数要求SR是由两个有序序列构成
void copy(int SR[], int TR[], int s, int t)//把TR赋给SR
{
	int i;
	for (i = s; i <= t; i++)
	{
		SR[i] = TR[i];
	}
}
int mergesort(int SR[], int s, int t)
{
	if (s < t)//表示从s到t有多个数字
	{
		int m = (s + t) / 2;//将序列一分为二
		mergesort(SR, s, m);//前一半序列继续进行归并排序
		mergesort(SR, m + 1, t);//后一半序列同时进行归并排序,
		//以上递归调用的结束条件是s!<t,也就是进行分到只有一个数字进行归并排序的时候,一个序列只有一个数字,那么这个序列肯定是有序的
		//以上都是属于“分”的阶段,目的是获得两个有序的数列
		merge(SR, TR, s, m, t);//对这两个有序的数列,进行排序,变成一个同样大小但是有序的数列
		copy(SR, TR, s, t);//将在TR中排序好的数列给SR,方便SR递归调用归并排序,因为每次两个归并排序的结果都是保存在TR中的,现在要进行下一步就必须在TR数列的基础上面=进行,所以我们把TR给SR
	}
	else//表示从s到t只有一个数字(s==t),或者没有数字(s>t)
	{
		;//空,也可省略,加一个else只是为了更好的理解程序
	}
	return 0;}

        测试结果如下图:

        

        归并排序(Merge Sort)完全遵循上述分治法三个步骤:
        1. 分解:将要排序的n个元素的序列分解成两个具有n/2个元素的子序列;
        2. 解决:使用归并排序分别递归地排序两个子序列;
        3. 合并:合并两个已排序的子序列,产生原问题的解。

        其时间复杂度是O(NlogN)。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值