【分治策略与递归详解】

1、分治策略

分治策略: 是将规模比较大的问题可分割成规模较小的相同问题。问题不变,规模变小。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。

分治法所能解决的问题一般具有以下四个特征:

  • 该问题的规模缩小到一定的程度就可以容易地解决。
  • 该问题可以分解为若干个规模较小的相同问题。
  • 使用小规模的解,可以合并成,该问题原规模的解。
  • 该问题所分解出的各个子规模是相互独立的。
1.1 分治法步骤: 在分治策略中递归地求解一个问题,在每层递归中应用如下三个步骤:

分解 : 将问题划分成一些子问题,子问题的形式与原问题一样,只是规模更小。
解决 : 递归地求解子问题。如果子问题的规模足够小,则停止递归,直接求解。
合并 : 将小规模的解组合成原规模问题的解
示例: 求解n的阶乘。(不考虑int 溢出)

分析:
在这里插入图片描述
在这里插入图片描述
代码,用循环完成:

// 不考虑整型溢出
int fun(int n)
{
 	int sum = 1; // 0;
 	for(int i = 1;i<=n;++i)
	{
		sum = sum * i;
	}
	return sum;
}

用递归完成:

// 不考虑整型溢出
int fac(int n)
{
	if(n <= 1) //每次调用发生时都,首先判断递归终止条件。
		return 1;
 	else
		return fac(n-1) *n;
}

2、递归

递归: 若一个函数直接地或间接地调用自己, 则称这个函数是递归的函数。(简单地描述为“自己调用自己”)。

  • 递归函数的执行分为 “递推”“回归” 两个过程,这两个过程由递归终止条件控制,即逐层递推,直至递归终止条件满足,终止递归,然后逐层回归。
  • 递归调用同普通的函数调用一样,每当调用发生时,就要分配新的栈帧(形参数据,现场保护,局部变量);而与普通的函数调用不同的是,由于递推的过程是一个逐层调用的过程,因此存在一个逐层连续的分配栈帧过程,直至遇到递归终止条件时,才开始回归,这时才逐层释放栈帧空间,返回到上一层,直至最后返回到主调函数。
2.1、图解递归过程(代码的调动过程)

在这里插入图片描述

2.2、 图解递归过程(栈帧的动态调动过程)

在这里插入图片描述
总结:
函数被调用,不管是自己调用自己,还是被其它函数调用,都将会给被调用函数分配栈帧。
不存在无穷递归。即递归函数必须要有一个是递归结束的出口(要有递归中止的条件语句)。
问题的规模不要过大,递归过深,引起栈溢出。

3、练习示例

示例 :输入一个整数(无符号整型),用递归算法将整数倒序输出。

分析:现在用递归过程的递推步骤中用求余运算将整数的各个位分离,并打印出来。
代码:
在这里插入图片描述
图解调用过程
在这里插入图片描述

  • 求余总是取当前整数的最右一位,所以先输出余数后递归可实现倒序输出。如果先递归后输出余数,则是在回归的过程中输出,实现的就是正序输出。
  • 从以上几例可以看出,递归算法一般不需要借助循环,但通过不断递推和回归的过程实现了其他算法用循环完成的功能。因此,递归的终止条件非常重要,否则将会无休止地递归下去,陷入死循环状态,最终会导致栈空间被耗尽,报StackOverflow 错误。

4、注意事项

  1. 限制条件: 在设计一个递归过程时,必须至少有一个可以终止此递归的条件,并且还必须对在合理的递归调用次数内未满足此类条件的情况进行处理。如果没有一个在正常情况下可以满足的条件,则过程将陷入执行无限循环的高度危险之中。
  2. 内存使用:应用程序的局部变量所使用的空间有限。过程在每次调用它自身时,都会占用更多的内存空间以保存其局部变量的附加副本。如果这个进程无限持续下去,最终会导致 StackOverflowException 错误。
  3. 效率:几乎在任何情况下都可以用循环替代递归。循环不会产生传递变量、初始化附加存储空间和返回值所需的开销,因此使用循环相对于使用递归调用可以大幅提高性能。
  4. 相互递归:如果两个过程相互调用,可能会使性能变差,甚至产生无限递归。此类设计所产生的问题与单个递归过程所产生的问题相同,但更难检测和调试。
  5. 调用时使用括号:当 Function 过程以递归方式调用它自身时,您必须在过程名称后加上括号(即使不存在参数列表)。否则,函数名就会被视为表示函数的返回值。
  6. 测试:在编写递归过程时,应非常细心地进行测试,以确保它总是能满足某些限制条件而终止递归过程。您还应该确保不会因为过多的递归调用而耗尽内存。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千北@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值