问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
你好,欢迎来到懂视!登录注册
当前位置: 首页 - 正文

递归与非递归

发布网友 发布时间:2022-05-04 21:24

我来回答

2个回答

热心网友 时间:2022-06-26 00:29

首先要理解递归本身其实是一项非常重要的算法技巧。
递归满足两个条件:
1,不断调用函数本身,也就是递归函数。
2,调用是有限的,也就是递归出口。

为了理解方便,下面是用一个最简单的例子:求N的阶乘。
n!(阶乘)定义:
n!数学意思为n! = n*(n-1)! & 1!=1;
其实根据上面递归定义结合分析下就可以n阶乘的递归算法:
1,构造一个递归函数,不断乘以自身和使用自身减一后调用同样函数.
2,定义出口,当函数参数等于1时结束;
如果用ISO C++语言描述如下:
int Factorial(int n){
if( n > 1){
return n*Factorial(n-1);//递归函数调用
}
else if(n == 1){
return 1; //递归出口
}
else{
return ERROR;//报告输入错误
}
}

这里讨论主要的不是上面这个简单的例子,而是下面的一些改良.
因为递归设计大量的堆栈操作,所以一般都会考虑将递归转为非递归来执行.
这里用上面这个程序作一个分析例子来分析.
假设这里执行Factorial(4),那么程序会按照下面方式来执行:

(1)执行Factorial(4)判断n > 1执行Factorial(3),并且将Factorial(4)函数相关信息存入一个堆栈.
(2)执行Factorial(3)判断n > 1执行Factorial(2),并且将Factorial(3)函数相关信息存入一个堆栈.
(3)执行Factorial(2)判断n > 1执行Factorial(1),并且将Factorial(2)函数相关信息存入一个堆栈.
(4)执行Factorial(1)判断n == 1执行返回1;
(5)将Factorial(2)函数从堆栈中弹出,执行2*1,并且返回2.
(6)将Factorial(3)函数从堆栈中弹出,执行2*3,并且返回6.
(7)将Factorial(4)函数从堆栈中弹出,执行6*4,并且返回24.

如下图所示:
Factorial(4)
-->Factorial(3);
-->Factorial(2);
-->Factorail(1);
<--Factorail(1);
<--Factorial(2);
<--Factorial(3);
<--结果
可以看到中间涉及的堆栈操作是很大的开销,每次需要保存当前函数的所有信息.
为了避免这样情况,可以使用下面这几种方法来实现递归到非递归的转换.

(1) 循环方法
循环方法是所有递归到非递归的转换中最理想的方法,可以将开销减少到最小.
不过也是分析起来最复杂的,对于简单的递归可以用这样的方法来处理.
例如:Factorial计算
这里回到n!(阶乘)定义上面来分析,这里将n!数学意思为n! = n*(n-1)! & 1!=1;做一个扩展可以到到n!另外一个表示方法n! = n*(n-1)*(n-2)*....*1;
这样就可以很容易得到另外一个定义:
n!表示执行n次循环计算一个增量k,初始k=1和结果t=1;每次t乘以k++的值.
ISO C++实现代码如下:
Factorial(int n){
int k = 1 ;//增量
int t = 1 ;//临时结果
while(k!=n){
t*=k;
k++;
}
return t;
}
这样可以避免递归带来的大量堆栈操作.

(2) 自定义堆栈
对于复杂逻辑的堆栈操作,需要借助外部堆栈来实现.
因为对于所有的递归操作最后分析出来都是形成的一颗树形结构.
下面是一个递归实现Factorial的一个方法,虽然在这个程序中对比循环来相对复杂,不过对于一些不能分析出来循环的递归操作来说自定义堆栈的方法可以达到空间开销可控.

Factorial(int n){
Stack s;
int t = 1;//临时变量
s.push(n);
while(s.top()!=1)[
t *= s.top();
s.push(s.top()-1);
s.pop();
}
return t;
}

除了上面这两种方法外,还可以使用一种迭代的方法实现递归到非递归的处理.

热心网友 时间:2022-06-26 00:29

用栈或者迭代
声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。
E-MAIL:11247931@qq.com
用手柄玩实况足球2012, 实况足球12如何进行手柄设置,以及窗口模式的设置? 带娃去感受乡村的夏天,这53条乡村游线要收藏好 一般签名用什么笔 怎么去追女孩的技巧 清朝有多少汉人被封王 《水滴石穿》告诉我们什么道理 重庆有哪些批发市场 重庆有哪些大型市场 重庆最大零食批发市场 C语言中递归函数是,非递归函数是?能否举例子? Barclays Stockbrokers CFD&FST Trader怎么样 200分 帮忙人式翻译一段计算机英文文档 这个轴承可以满足你提出的条件 用英语怎么翻译 翻译句子 人工翻译谢谢 我想系统的学习证券投资知识 电影&lt;华尔街&gt;的观后感? (高分求助)排列组合 之 篮球红球问题 为什么jsp代码onsubmit=“return check()”报错 技术分析实战工具的作者简介 急,Strangle在金融里是什么意思? 怎样识别手机数据线的型号,在哪儿可以买到适合自己手机的数据线? 怎么知道自己的USB数据线型号 求梁永琪的一首歌的歌名?;歌词有句是&#92;&#39;好想快点张大,不用看童话&#92;&quot;整首个有点童谣的感觉 我不不怕不怕我要快快长大是那首歌的歌词 小松树歌词 我想找一首歌,词里是这样唱的&quot;嗡嗡嗡蜜蜂在采蜜,爱爸爸,爱妈妈,我要快快长大 歌曲快快长大,是一首电视片插曲,歌词是:儿时的摇篮摇着那闪闪的煤油灯花,那灯下的妈妈为我逢着那布娃娃 快快长大 歌词 诺基亚x7微信4.2版本在哪下载了 如何将递归函数转化为非递归函数 程序的递归算法与非递归的区别 如何实现递归函数改写成非递归函数 将c++递归函数改为非递归函数 将递归函数化为非递归函数~ 递归与非递归两种函数程序设计好难做 请将下列递归函数变为非递归函数! 每一个递归版的函数都能写成一个非递归版的函数吗? 用非递归的函数调用形式求斐波那契数列第n项 画红线区域内为什么说递归函数象非递归函数那样保存信息会出错 求教,C语言非递归函数求斐波那契数列 读下列程序 说出程序的功能;将其改写为传递引用参数,将findmax()函数改写成非递归函数 C++ 先序中序后序层序 非递归函数 谁能帮我解释一下 编写非递归函数int Fibonacci(int n),返回斐波那契数列的第n项.C++!今早出答案给20分!!! 中国到底有没有修真者? 中国真的有修真者吗 现在中国到底有没有修真的人?还存不存在门派?一般怎么才有机会加入? 中国的修真者、古武者真的存在吗? 中国真的有修真者吗? 龙江健康码有过红码恢复后对以后会有影响吗
  • 焦点

最新推荐

猜你喜欢

热门推荐