递归调用

函数递归调用过程中的调用堆栈的情况

我与影子孤独终老i 提交于 2019-12-04 08:14:08
为了加深对函数递归调用过程中的理解,本Demo程序特意在VS2008 C#控制台程序实现了阶乘的计算功能,用于观察函数递归调用过程中的调用堆栈的情况。 源码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace RecursiveTset { class Program { //阶乘的定义:n!=n*(n-1)!,特别的,1!=1;0!=1 //阶乘的实现:采用递归调用方式。主要测试和观察递归过程中的函数堆栈的调用情况! public static int JiechengFun(int num) { int result=1; if (num == 0) result = 1; if (num >= 1) result = num * JiechengFun(num - 1); return result; } static void Main(string[] args) { int res = Program.JiechengFun(4); System.Console.WriteLine(res); } } } 函数递归调用过程中的调用堆栈的情况截图如下: 源码下载: https://pan.baidu.com/s

针对递归函数进行优化的方案

末鹿安然 提交于 2019-12-04 06:01:19
相信递归函数大家都写过,下面就是个典型的递归函数: function fibonacci(n) { return n < 2 ? n : fibonacci(n - 2) + fibonacci(n - 1); } 但是像这样的递归函数有个很明显的问题,每次调用的时候都需要重新计算结果,这样过深的递归就会占有过多内存导致堆栈溢出。 针对这种情况,我们可以使用缓存策略来缓存中间的计算值。 var fibonacci = function(){ let cache = {}; return function(n){ if(!cache[n]){ cache[n] = n < 2 ? n : fibonacci(n-2) + fibonacci(n-1); } return cache[n]; } }(); 上述方法使用了一个闭包,声明了一个局部变量cache来保存缓存中间的计算值,大家可以在控制台试一下递归层级比较多的时候性能已经得到了很大的提升。 这里解释一下,为什么用的是cache = {},而不是cache = [],是因为cache = {}的性能会更高一些(其实使用场景也会多一些,key不用局限于数字),如果设置了cache = [],在设置cache[100]的时候,目标其实只是想设置一个key为100的value,结果数组会将0-99都会被初始化为empty

PHP使用递归按层级查找数据

给你一囗甜甜゛ 提交于 2019-12-04 03:48:52
今天主要介绍一下使用递归来按层级查找数据。 原理挺简单的,主要是通过父级id一级一级的循环查找子级,使用PHP循环代码也很容易实现,不过如果层级越多,PHP重复代码也越多,这时可以使用递归来实现这功能。 1、首先查出要使用的数据组成一个数组(避免递归里查询数据库,之后根据这个数组组成自己需要的数据就可以了) 比如得到如下数据: $data = [ ['id' => '1', 'pid' => '0', 'dsp' => '1'], ['id' => '2', 'pid' => '0', 'dsp' => '2'], ['id' => '3', 'pid' => '0', 'dsp' => '3'], ['id' => '4', 'pid' => '1', 'dsp' => '1-4'], ['id' => '5', 'pid' => '4', 'dsp' => '1-4-5'], ['id' => '6', 'pid' => '5', 'dsp' => '1-4-5-6'], ['id' => '7', 'pid' => '3', 'dsp' => '3-7'], ['id' => '8', 'pid' => '2', 'dsp' => '2-8'], ['id' => '9', 'pid' => '1', 'dsp' => '1-9'], ['id' => '10', 'pid'

树和二叉树一篇就搞定!

[亡魂溺海] 提交于 2019-12-04 03:42:46
二叉树铺垫——树 前面几篇文章我们主要介绍的线性表,栈,队列,串,等等,都是一对一的 线性结构 ,而今天我们所讲解的 “树” 则是一种典型的 非线性结构 ,非线性结构的特点就是,任意一个结点的直接前驱,如果存在,则一定是唯一的,直接后继如果存在,则可以有多个,也可以理解为一对多的关系,下面我们就先来认识一下树 树的概念 下图我们日常生活中所见到的树,可以看到,从主树干出发,向上衍生出很多枝干,而每一根枝干,又衍生出一些枝丫,就这样组成了我们在地面上可以看到的树的结构,但对于每一个小枝丫来讲,归根结底,还是来自于主树干的层层衍生形成的。 我们往往需要在计算机中解决这样一些实际问题 例如: 用于保存和处理树状的数据,例如家谱,组织机构图 进行查找,以及一些大规模的数据索引方面 高效的对数据排序 先不提一些复杂的功能,就例如对于一些有树状层级结构的数据进行建模,解决实际问题,我们就可以利用 “树” 这种结构来进行表示,为了更符合我们的习惯,我们一般把 “树” 倒过来看,我们就可以将其归纳为下面这样的结构,这也就是我们数据结构中的 “ 树” 树中的常见术语 结点 :包含数据项以及指向其他结点的分支,例如上图中圆 A 中,既包含数据项 A 又指向 B 和 C 两个分支 特别的,因为 A 没有前驱,且有且只有一个,所以称其为根结点 子树 :由根结点以及根结点的所有后代导出的子图称为树的子树

数据结构与算法之美学习笔记:第十讲

≡放荡痞女 提交于 2019-12-04 02:13:45
一、开篇问题 推荐注册返佣金的这个功能我想你应该不陌生吧?现在很多App都有这个功能。这个功能中,用户A推荐用户B来注册,用户B又推荐了用户C来注册。我们可以说,用户C的“最终推荐人”为用户A, 用户B的“最终推荐人”也为用户A,而用户A没有“最终推荐人”。 一般来说,我们会通过数据库来记录这种推荐关系。在数据库表中,我们可以记录两⾏数据,其中actor_id表示用户id,referrer_id表示推荐人id。 基于这个背景,我的问题是, 给定一个用户ID,如何查找这个用户的“最终推荐人”? 带着这个问题,我们来学习今天的内 容,递归(Recursion) 二、如何理解递归 1、电影院案例 周末你带着女朋友去电影院看电影,女朋友问你,咱们现在坐在第几排啊?电影院里面太黑了,看不清,没法数,现在你怎么办? 2、用递归解决你在第几排的问题 别忘了你是程序员,这个可难不倒你,递归就开始排上用场了: 于是你就问前面一排的人他是第几排,你想只要在他的数字上加一,就知道自己在哪一排了。 但是,前面的人也看不清啊,所以他也问他前面的人。就这样一排一排往前问,直到问到第一排的人,说我在第一排, 然后再这样一排一排再把数字传回来。直到你前面的人告诉你他在哪几排,于是你就知道答案了。 这就是一个非常标准的递归求解问题的分解过程: 去的过程叫“递”,回来的过程叫“归” 。基本上

递归和迭代

落爺英雄遲暮 提交于 2019-12-03 21:03:41
(1)定义: 程序调用自身称为递归。 利用变量的原值推出新值称为迭代。 (2)优缺点 递归 优点:大问题转化为小问题,可以减少代码量,同时代码精简,可读性好; 缺点:就是递归调用浪费了空间,而且递归太深容易造成堆栈的溢出。 迭代 优点:代码运行效率好,因为时间只因循环次数增加而增加,而且没有额外的空间开销; 缺点:代码不如递归简洁 来源: https://www.cnblogs.com/caohongchang/p/11808900.html

生成器递归解决八皇后问题(基本属于抄题,勉强理解)

十年热恋 提交于 2019-12-03 15:50:46
昨天失败了,看了一晚上还是没搞定,但至少有头目了。 讲八皇后之前,我还是先来一个简单的递归生成器: 我给自己标记下分析的思路,怕到时候又忘记了,这是一个多层列表的去除[]剥皮器。 def flatten(nested): try: for sublist in nested: for element in flatten(sublist):         # print(element)         yield element # 主输出,用for循环接受。 except TypeError: yield nested # 子返回 这个看似乎非常简单的递归生成器,本来我以为我看懂了,没仔细分析,后面仔细分析了一下,其实我没懂,再大把力气花下去,又懂了 这种递归生成器用了双yield,其实这里面会让人陷进去,我以前也写过一些简单的递归,一般都是用return,这次的双yield,把我还苦了 因为后面的八皇后递归生成器也是双yield的格式,如果用递归生成器可能也只能用yield, 记住一点yield的返回值需要用next, send(None), 或者案例里面通过for循环取值,其实案例用next取值,可能我分析的时候可以少走很多弯路。 经过测试next取值失败,next取值无法对列表套列表里面的元素全部返回值,只会返回列表套列表的元素里面第一个值。 这个可能跟for

JS学习笔记 之 递归

泪湿孤枕 提交于 2019-12-03 15:12:56
--> 除了让程序简洁没有任何好处 典型例子:求n的阶乘 找规律、找出口 1. 找递归规律 --> n! = n * (n-1)! 2. 写功能函数 例子:求阶乘 //n! = n * (n-1)! 1 function mul(n){ 2 //找出口,即已知的条件或者结果 3 if(n == 1){ 4 return 1; 5 } 6 //3. 写递归 7 //语句,调用自身 8 return = n * mul(n - 1); 9 } 10 mul(8); 例子:斐波那契数列 1 //斐波那契数列 2 //fb(n) = fb(n -1 ) + fb(n - 2) 3 4 function fb(n){ 5 if(n == 1 || n == 2){ 6 return 1; 7 } 8 9 return fb(n-1) + fb(n-2); 10 } 来源: https://www.cnblogs.com/seveinn/p/11801747.html

递归函数

大憨熊 提交于 2019-12-03 15:11:11
1.不断调用自己本身 (死递归) 2.有明确的终止条件 满足以上两个才是有效递归 官方声明:最大层次1000,实测 998/997 def age(n): if n == 4: return 18 else: return age(n+1)-2 print(age(1)) 把上面的展开 def age4(n): if n == 4: return 18 def age3(n): if n == 4: return 18 else: return age4(n+1)-2 def age2(n): if n == 4: return 18 else: return age3(n+1)-2 def age1(n): if n == 4: return 18 else: return age2(n+1)-2 print(age1(1)) 来源: https://www.cnblogs.com/lav3nder/p/11801675.html

递归函数

允我心安 提交于 2019-12-03 14:07:11
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 def fact(n): if n==1: return 1 return n * fact(n - 1) fact(3) 使用递归函数需要注意防止栈溢出 解决递归调用栈溢出的方法是通过尾递归优化 尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式 def fact(n): return fact_iter(n, 1) def fact_iter(num, product): if num == 1: return product return fact_iter(num - 1, num * product) 汉诺塔问题 不太懂 来源: https://www.cnblogs.com/g2thend/p/11798344.html