递归调用

递归与非递归及其相互转换

蓝咒 提交于 2020-01-18 15:48:13
一、什么是递归 递归是指某个函数直接或间接的调用自身。问题的求解过程就是划分成许多相同性质的子问题的求解,而小问题的求解过程可以很容易的求出,这些子问题的解就构成里原问题的解了。 二、递归的几个特点 1. 递归式,就是如何将原问题划分成子问题。 2. 递归出口,递归终止的条件,即最小子问题的求解,可以允许多个出口。 3. 界函数,问题规模变化的函数,它保证递归的规模向出口条件靠拢 三、递归的运做机制 很明显,很多问题本身固有的性质就决定此类问题是递归定义,所以递归程序很直接算法程序结构清晰、思路明了。但是递归的执行过程却很让人费解,这也是让很多人难理解递归的原因之一。由于递归调用是对函数自身的调用,在一次调用没有结束之前又开始了另外一次调用, 按照作用域的规定,函数在执行终止之前是不能收回所占用的空间,必须保存下来,这也就意味着每一次的调用都要把分配的相应空间保存起来。 为了更好管理这些空间,系统内部设置一个栈,用于存放每次函数调用与返回所需的各种数据, 其中主要包括函数的调用结束的返回地址,返回值,参数和局部变量等。 其过程大致如下: 1. 计算当前函数的实参的值 2. 分配空间,并将首地址压栈,保护现场 3. 转到函数体,执行各语句,此前部分会重复发生(递归调用) 4. 直到出口,从栈顶取出相应数据,包括,返回地址,返回值等等 5. 收回空间,恢复现场

递归题目

本秂侑毒 提交于 2020-01-18 00:42:39
一、递归和循环  1.理论上,任何循环都可以重写为递归形式  2.java不支持尾递归。 二、解决递归  1.问题相似性  2.递归出口。这里有时候可以通过添加参数来解决。 三、递归的原理 四、没写出口的时候,疯狂压栈,栈就会溢出。 循环、递归打印0-n package cn . itcast . suanfa ; public class Test { public static void fun1 ( int n ) { if ( n > 0 ) fun1 ( n - 1 ) ; /* * 如果n=0,会调用n=-1,错误 * 如果n=1,会调用n= 0,正确 * 所以应该是n>0 * */ System . out . println ( n ) ; } public static void fun2 ( int begin , int end ) { if ( begin > end ) return ; //这个return可以运用为,结束条件后停止该函数 System . out . println ( begin ) ; fun2 ( begin + 1 , end ) ; } public static void main ( String [ ] args ) { //方法一:递归打印0-n // fun1(10); //方法二:循环打印0-n /*for

二叉树---中续遍历(递归)

蓝咒 提交于 2020-01-17 23:04:25
@Adrian 二叉树中序遍历的实现思想是: 访问当前节点的左子树; 访问根节点; 访问当前节点的右子树; 以图 1 为例,采用中序遍历的思想遍历该二叉树的过程为: 访问该二叉树的根节点,找到 1; 遍历节点 1 的左子树,找到节点 2; 遍历节点 2 的左子树,找到节点 4; 由于节点 4 无左孩子,因此找到节点 4,并遍历节点 4 的右子树; 由于节点 4 无右子树,因此节点 2 的左子树遍历完成,访问节点 2; 遍历节点 2 的右子树,找到节点 5; 由于节点 5 无左子树,因此访问节点 5 ,又因为节点 5 没有右子树,因此节点 1 的左子树遍历完成,访问节点 1 ,并遍历节点 1 的右子树,找到节点 3; 遍历节点 3 的左子树,找到节点 6; 由于节点 6 无左子树,因此访问节点 6,又因为该节点无右子树,因此节点 3 的左子树遍历完成,开始访问节点 3 ,并遍历节点 3 的右子树,找到节点 7; 由于节点 7 无左子树,因此访问节点 7,又因为该节点无右子树,因此节点 1 的右子树遍历完成,即整棵树遍历完成; 二叉树采用中序遍历得到的序列为: 4 2 5 1 6 3 7 递归中序遍历: # include <stdio.h> # include <string.h> # define TElemType int //构造结点的结构体 typedef struct

javascript 算法 ---递归

老子叫甜甜 提交于 2020-01-17 18:18:56
“要理解递归,首先要理解递归。” ——佚名 递归函数是在函数内部能够直接或间接调用自身的方法或函数 。 假设一个函数一直调用自己结果是什么?单就上述情况而言,它会一直执 行下去。因此,每个递归函数都必须有基线条件,即一个不再递归调用的条件(停止点),以防 止无限递归。 function A(X) {   const recursionAnswer = confirm('Do you understand recursion?'); if (recursionAnswer === true) {     //基线条件 ,停止点    return true;  }   //递归调用   A(recursionAnswer); } 作为递归的第一个例子,我们来看看如何计算一个数的阶乘。数 n的阶乘,定义为 n!,表示 从 1到 n的整数的乘积。 5的阶乘表示为 5!,和 5 × 4 × 3 × 2 × 1相等,结果是 120。 (注意一个概念定义 0!= 1,不是等于 0) function factorial(x){ //基线 if(x == 0 || x==1){ return 1; } //递归调用 return x*factorial(x-1); } 斐波那契数列 0、1、1、2、3、5、8、13、21、 34等数组成的序列。数 2由 1 + 1得到,数 3由 1 + 2得到

SQL递归函数

房东的猫 提交于 2020-01-17 04:06:31
生成一张表,添加数据 DROP table IF EXISTS Dept ; create table Dept ( ID int , ParentID int , msg varchar ( 20 ) ) insert into Dept select 1 , 0 , '中国' insert into Dept select 2 , 1 , '上海' insert into Dept select 3 , 1 , '浙江' insert into Dept select 4 , 2 , '普陀区' insert into Dept select 5 , 3 , '杭州' insert into Dept select 6 , 5 , '西湖区' insert into Dept select 7 , 6 , '双浦镇' go 递归函数: Create function GetChild ( @ID varchar ( 10 ) ) returns @t table ( ID varchar ( 10 ) , ParentID varchar ( 10 ) , Level int , msg varchar ( 20 ) ) as begin declare @i int set @i = 1 --insert into @t select @ID,@ID,0 --当前级,本级

leetcode刷题记第17题解法(python解析)

空扰寡人 提交于 2020-01-17 02:08:01
leetcode刷题记--> 17题解法(python解析) 题目定义 解题 1. 使用reduce方法进行解决问题 2. 动态规划 3. 动态规划 4. 使用递归 实现 题目定义 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例: 输入:“23” 输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]. 说明: 尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。 来源:力扣(LeetCode) 链接: leetcode_17题 . 解题 本次使用4种方法,在leetcode上还有更多的方法,只能说真牛逼,真聪明。 1. 使用reduce方法进行解决问题 熟悉大数据的同学都知道map reduce 此处就使用reduce进行解决 2. 动态规划 使用列表生成式 3. 动态规划 同样是列表生成式,比较绕,仔细理解 4. 使用递归 对于打印"2345"这样的字符串: 第一次递归就是上图中最下面的方格,然后处理完第一个字符2之后,将输入的字符改变成"345"并调用第二个递归函数 第二次递归处理3,将字符串改变成"45"后再次递归 第三次递归处理4,将字符串改变成"5"后继续递归 第四次递归处理5,将字符串改变成"

递归获得指定文件夹下的所有文件夹、文件

爱⌒轻易说出口 提交于 2020-01-17 01:49:44
原文地址 因为有了一个想从一个大文件夹下find出所有的.doc文件的需求,这个需求的关键活动就是递归获得文件夹下的所有文件。通过一番找资料,整理出两种递归获取指定文件夹下所有文件夹、文件的方法。 方式一,使用os.walk(path)函数获取 使用该函数需要导入os模块。 import os 函数返回元素是 (文件夹,[文件夹下的文件夹列表],[文件夹下的文件列表]) 的一个列表,通过循环拼接可以获得指定路径下所有层次的文件夹和文件全路径。最后return文件夹列表和文件列表。 # 方式一,使用os.walk(path)方法 def getAllSub ( path ) : Dirlist = [ ] Filelist = [ ] for home , dirs , files in os . walk ( path ) : # 获得所有文件夹 for dirname in dirs : Dirlist . append ( os . path . join ( home , dirname ) ) # 获得所有文件 for filename in files : Filelist . append ( os . path . join ( home , filename ) ) return Dirlist , Filelist 方式二,通过递归调用一层层获取 # 方式二

lambda演算中的递归与Y组合子

邮差的信 提交于 2020-01-17 00:59:32
文章目录 lambda演算中的递归与Y组合子 λthis. 使用λthis.实现递归 Y组合子 lambda演算中的递归与Y组合子 λthis. 考虑在 λ \lambda λ 演算中实现一个递归的阶乘函数, f a c t ( n ) = { 1 , n = 0 n ⋅ f a c t ( n − 1 ) , n ≠ 0 fact(n)=\begin{cases} 1&,n=0 \\ n\cdot fact(n-1)&,n\neq0 \end{cases} f a c t ( n ) = { 1 n ⋅ f a c t ( n − 1 ) ​ , n = 0 , n  ​ = 0 ​ 按照习惯性的做法,可能会写成: λn.(if (= n 0) 1 (* n (this (- x 1)))) 其中 this 表示这个函数自身。 然而,对于这个函数而言, this 并没有意义,没有“调用自身的函数”这个实体存在 如果我们想要用 this ,就要在这个函数中实现 this 的功能,构造出一个“调用自身的函数” 我们顺着这个思路下去,构造 this : λthis.λn.(if (= n 0) 1 (* n (this (- x 1)))) 由于this从意义上应该是调用函数自身, λthis.λn.balabala 这个函数的第一参数应该是函数自身,第二参数才是数值,所以

【算法导论】第4章 分而治之 (3)

谁都会走 提交于 2020-01-17 00:19:54
Introduction to Algorithms - Third Edition Part I. Foundations Chapter 4. Divide-and-Conquer ★ \bigstar ★ 4.6 主定理的证明 4.6.1 取正合幂时的证明 假设 n n n 是 b > 1 b>1 b > 1 的正合幂,其中 b b b 不必是整数,分析主方法中的递归式 (4.20) T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T ( n ) = a T ( n / b ) + f ( n ) 。 将分析分成 3 个引理来说明。 第1个引理,将求解主递归式的问题,归约为对包含总和的表达式求值的问题。 第2个引理,确定这个总和的界限。 第3个引理,将前两个结合一起,证明:在 n n n 是 b b b 的正合幂的情况下,主定理成立。 引理 4.2 设 a ≥ 1 a \ge 1 a ≥ 1 和 b > 1 b > 1 b > 1 是常数,设 f ( n ) f(n) f ( n ) 是定义在 b b b 的正合幂上的非负函数。在 b b b 的正合幂上定义 T ( n ) T(n) T ( n ) : T ( n ) = { Θ ( 1 ) if n = 1 a T ( n / b ) + f ( n ) if

递归 VS 非递归 内涵

空扰寡人 提交于 2020-01-16 05:13:08
递归与非递归转换的基础知识是能够正确理解三种树的遍历方法:前序,中序和后序,第一篇就是关于这三种遍历方法的递归和非递归算法。 一、为什么要学习递归与非递归的转换的实现方法? 1)并不是每一门语言都支持递归的。 2)有助于理解递归的本质。 3)有助于理解栈,树等数据结构。 二、三种遍历树的递归和非递归算法 递 归与非递归的转换基于以下的原理:所有的递归程序都可以用树结构表示出来。需要说明的是,这个”原理”并没有经过严格的数学证明,只是我的一个猜 想,不过在至少在我遇到的例子中是适用的。学习过树结构的人都知道,有三种方法可以遍历树:前序,中序,后序。理解这三种遍历方式的递归和非递归的表达方 式是能够正确实现转换的关键之处,所以我们先来谈谈这个。需要说明的是,这里以特殊的二叉树来说明,不过大多数情况下二叉树已经够用,而且理解了二叉树的 遍历,其它的树遍历方式就不难了。 1)前序遍历 a)递归方式: void preorder_recursive(Bitree T) /* 先序遍历二叉树的递归算法 */ { if (T) { visit(T); /* 访问当前结点 */ preorder_recursive(T->lchild); /* 访问左子树 */ preorder_recursive(T->rchild); /* 访问右子树 */ } } b)非递归方式 void preorder