首页
学习
活动
专区
圈层
工具
发布

尾递归函数

怯懦的朋友在叛离之后,会成为最凶残的仇敌——埃·斯宾塞 中文文档 Kotlin 支持一种称为尾递归的函数式编程风格。 这允许一些通常用循环写的算法改用递归函数来写,而无堆栈溢出的风险。...当一个函数用 tailrec 修饰符标记并满足所需的形式时,编译器会优化该递归,留下一个快速而高效的基于循环的版本: val eps = 1E-10 // "good enough", could be...x) if (Math.abs(x - y) < eps) return x x = Math.cos(x) } } 要符合 tailrec 修饰符的条件的话,函数必须将其自身调用作为它执行的最后一个操作...在递归调用后有更多代码时,不能使用尾递归,并且不能用在 try/catch/finally 块中。目前在 Kotlin for JVM 与 Kotlin/Native 中支持尾递归。

1.4K20

将非尾递归函数转换为循环或尾递归形式

1、问题背景在 Python 中,非尾递归函数可能会导致递归深度限制问题。当递归深度超过限制时,程序将引发 RecursionError 异常。...为了避免这个问题,我们可以将非尾递归函数转换为循环或尾递归形式。2、解决方案2.1 循环形式我们可以使用循环来实现非尾递归函数的功能。...尾递归函数可以很容易地转换为循环形式,因为递归函数的最后一步可以被一个循环来代替。...然而,尾递归形式更易于理解和维护,因为它是直接递归的。2.4 转换技巧将非尾递归函数转换为循环或尾递归形式时,我们可以使用以下技巧:确定递归函数的基线情况,即不需要递归调用的情况。...在递归函数中,将递归调用放在函数的最后一步。使用循环来代替递归函数的最后一步。

1K10
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    Kotlin中尾递归函数

    Kotlin尾递归函数理解 kotlin中,如果某个函数的末尾又调用了函数自身,这种就称为尾递归函数。 尾递归函数需要在 fun 前面添加 tailrec。...尾递归函数会使用循环的方式替代递归,从而避免栈溢出。 尾递归不能在异常处理的try、 catch 、 finally 块中使用 。...//定义计算阶乘的函数 fun fact (n : Int) : Int{ if (n == 1) { return l } else { return n * fact(n - 1) } } 上面函数将调用自身作为其执行体的最后一行代码...,且递归调用后没有更多代码,因此可 以将该函数改为尾递归语法。...此时,上面函数可改为如下形式 //使用尾递归函数的语法 tailrec fun factRec(n: Int, total : Int= 1): Int = if (n == 1) total else

    1.5K10

    匿名函数、高阶函数与尾递归优化

    匿名函数最吸引我的是它的简洁性。记得有次需要对一个数组进行过滤和映射操作,如果为每个操作都定义命名函数,代码会变得冗长。使用匿名函数后,代码量减少了三分之一,可读性反而提高了。...通过组合多个专门的高阶函数,我构建了一个既灵活又可维护的数据转换流程,后续需求变更时只需调整个别环节,而不必重写整个流程。...尾递归优化的核心是将递归调用作为函数的最后一个操作,这样编译器可以复用当前的栈帧而不是创建新的,从而避免栈溢出。...通过实践,我总结了普通递归与尾递归的主要区别:特性普通递归尾递归栈帧使用每次递归创建新栈帧可复用同一栈帧内存消耗与递归深度成正比常量级内存消耗代码风格通常更直观需要传递累加器参数易用性直接表达问题可能需要包装辅助函数风险栈溢出风险高取决于语言是否支持优化一个典型的例子是计算斐波那契数列...后来改写为尾递归版本:function fibTail(n, a = 0, b = 1) { if (n === 0) return a; return fibTail(n-1, b, a+b);

    26300

    递归函数

    递归 递归就是一个函数在它的函数体内调用它自身。执行递归函数将反复调用其自身,每调用一次就进入新的一层。递归函数必须有结束条件。...注: 递归的时候,每次调用一个函数,计算机都会为这个函数分配新的空间,这就是说,当被调函数返回的时候,调用函数中的变量依然会保持原先的值,否则也不可能实现反向输出。...特点: 递归函数特点 每一级函数调用时都有自己的变量,但是函数代码并不会得到复制,如计算5的阶乘时每递推一次变量都不同; 每次调用都会有一次返回,如计算5的阶乘时每递推一次都返回进行下一次; 递归函数中...,位于递归调用前的语句和各级被调用函数具有相同的执行顺序; 递归函数中,位于递归调用后的语句的执行顺序和各个被调用函数的顺序相反; 递归函数中必须有终止语句。...效率 1.系统栈(也叫核心栈、内核栈) 是内存中属于操作系统空间的一块区域,其主要用途为: (1)中断现场,对于嵌套中断,被中断程序的现场信息依次压入系统栈,中断返回时逆序弹出; (2)保存操作系统子程序间相互调用的参数

    1.5K30

    递归函数

    ,当然,我们需要能实际做事情的函数,有用的递归函数应该满足如下条件: (1)当函数直接返回值时有基本实例(最小可能性问题) (2)递归实例,包括一个或多个问题最小部分的递归调用 使用递归的关键在于将问题分解为小部分...还有一种方法,就是通过尾递归优化,事实上尾递归和循环的效果一样,把循环看成一种特殊尾递归函数也是可以的。...尾递归是指在函数返回时只能调用函数本身,return语句不能包含表达式,这样,编译器或解释器就可以对尾递归进行优化,使递归本身无论调用多少次都只占用一个栈帧,从而避免栈溢出的情况。...由于上面的fact(n)函数return n*(n-1)引入了乘法表达式,因此不是尾递归,要改成尾递归方式需要多一点代码,主要是把每一步乘积传入递归函数(通过把乘积结果传入函数参数的方式),看如下函数定义方式...遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

    1.7K10

    函数递归

    如果一个函数在内部调用自身本身,则该函数就是递归函数 递归优缺点   优点:使用递归函数的优点是逻辑简单清晰      理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰...,每当函数返回,栈就会减一层栈帧   由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出 尾递归   解决递归调用栈溢出的方法是通过尾递归优化   事实上尾递归和循环的效果是一样的...,所以,把循环看成是一种特殊的尾递归函数也是可以的   尾递归是指,在函数返回的时候,调用自身本身,并且return语句不能包含表达式   例如,def fun(n) : retrun n*fun(n-...  大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把函数改成尾递归方式,也会导致栈溢出   也就是说尾递归需要解释器提供帮助,单纯从代码上是无法彻底实现的 针对尾递归优化的语言可以通过尾递归防止栈溢出...尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环 Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题 使用示例: def fact(n):   return

    1.8K10

    python递归函数讲解_Python递归函数实例讲解

    Python递归函数实例讲解 Python递归函数实例 1、打开Python开发工具IDLE,新建‘递归.py’文件,并写代码如下: def digui(n): if n == 0 : print (”...一.递归 是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象.在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知.使用递归解决问题,思路清晰,代码少.但是在主流高级语言中...递归函数:在一个函数里在调用这个函数本身....,于是python为了杜绝此类现象,强制的将递归层数控制在了997(只要997!...,继续第一步操作 ③ 重复第二步操作直至找出目标数字 比如从1,3,9,23,54 中查找数字23, 首位置为0, 尾位置为4,中间位置就为2 值为9 版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人

    4.5K20

    Python 递归函数

    递归函数 在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。...,所以,把循环看成是一种特殊的尾递归函数也是可以的。....html) 尾递归基于函数的尾调用, 每一级调用直接返回函数的返回值更新调用栈,而不用创建新的调用栈, 类似迭代的实现, 时间和空间上均优化了一般递归!...对比反汇编代码如下(AT&T语法) 可以看到, 开启尾递归优化前, 使用call调用函数, 创建了新的调用栈(LBB0_3); 而开启尾递归优化后, 就没有新的调用栈生成了, 而是直接pop bp..._getframe() # 为什么是grandparent, 函数默认的第一层递归是父调用, # 对于尾递归, 不希望产生新的函数调用(即:祖父调用),

    2.3K30

    Python 递归函数

    递归函数 在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 举个例子,我们来计算阶乘 n!...* n = fact(n-1) * n 所以,fact(n)可以表示为 n * fact(n-1),只有n=1时需要特殊处理。...于是,fact(n)用递归的方式写出来就是: 1 2 3 4 def fact(n): if n==1:   return 1 return n * fact(n - 1) 上面就是一个递归函数...理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。 使用递归函数需要注意防止栈溢出。...在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

    1.9K20

    优化函数递归

    递归是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象。在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知。使用递归解决问题,思路清晰,代码少。...下面我们以 n = 5 代入上面的函数,手动执行一下这个函数。 我要计算 fib(5),那么我就需要计算 fib(4)和 fib(3)。...因为这个次数限制是可以修改的,直接使用 sys 模块中的 setrecursionlimit 函数来设置,这个函数接受一个参数,这个参数是新设置最大次数。...递归就是函数不断的调用自身,在内存中产生许多调用堆栈,这不就是传说中的数据结构——栈吗?...其中用循环实现这种方法并不通用,因为有些递归函数不能写成循环,比如阿克曼函数。下面我们直接来看使用 lru_cache 的效率。

    1.9K10

    函数的递归

    一、什么是递归 1.递归是什么 递归是学习C语⾔函数绕不开的⼀个话题,那什么是递归呢?递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。...,再除10去掉3,以此类推,不断的 %10 和 /10 操作,直到1234的每⼀位都得到; 在这个解题的过程中,我们就是使⽤了⼤事化⼩的思路把Print(12345)打印12345每⼀位,拆解为⾸...先Print(1234)打印1234的每⼀位,再打印得到的5; 把Print(1234)打印123每⼀位,在打印得到4;把Print(123)拆解为⾸先Print(12)打印12的每⼀位,再打印得到的...函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话,每⼀次递归函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。...举例:求第n个斐波那契数 我们也能举出更加极端的例⼦,就像计算第n个斐波那契数,是不适合使⽤递归求解的,但是斐波那契数的问题通过是使⽤递归的形式描述的,如下: 当我们n输⼊为50的时候,需要很

    24810

    函数的递归

    之前的文章中和大家分享了C语言中的函数,那么我们今天来讲讲函数的递归。 1. 什么是函数的递归 递归是我们学习C语言函数绕不开的一个话题,那么什么是递归呢?...每调用一次递归,我们会越来越接近这个限制条件。 那么且看下面的例子,我们来慢慢感受这两个必要条件。 3. 递归举例 3.1 求n的阶乘 计算n的阶乘(不考虑溢出的情况下),就是将1到n的数累计相乘。...例如我们输入:520 打印结果为:5 2 0 这个问题放到我们面前,我们首先思考的是怎么获得这个数的每一位呢?如果n是一位数,那么每一位就是它自己。如果n是多位数那就要拆分每一位。...函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话,每⼀次递归 函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。...例如:求第n个斐波那契数 我们也能举出更加极端的例⼦,就像计算第n个斐波那契数,是不适合使⽤递归求解的,但是斐波那契 数的问题通过是使⽤递归的形式描述的,看到这问题,很容易诱导我们将代码写成递归的形式,

    26210

    python递归函数

    python递归函数 英文的Recursion从词源上分析只是"re- (again)" + "curs- (come, happen)" 也就是重复发生,再次重现的意思。...而对应的中文翻译 ”递归“ 却表达了两个意思:”递“+”归“。 这两个意思,正是递归思想的精华所在。从这层次上来看,中文翻译反而更达意。 递归是静中有动,有去有回。 循环是动静如一,有去无回。...python递归常见使用 汉诺塔 Python第二十二课:python递归函数 树状 Python第二十二课:python递归函数 谢尔宾斯基三角形 Python第二十二课:python递归函数 常见的递归拍照...Python第二十二课:python递归函数 python递归代码实例 递归求阶乘 所谓的求阶层,简单的就是12345*6...一直乘下去 非递归版本的函数 def fac(n): result =...100,如需改变其深度,需要 import sys sys.setrecursionlimit(10000) #10000为递归的深度

    1.7K30

    函数的递归

    1.递归思想: 把一个复杂的问题拆分成一个一个小的问题,直到小的问题不能再被拆分。 递是传递的意思,归是回归的意思,下文举例说明。 1条件: (1)递归存在条件,当不满足这个条件时就停止递归 。....*1,这是一道数学问题,要把他转化为编程逻辑,一般 先想到的是循环,从1一开始一直乘到n结束,使用递归也同样简单,如图 利用这种方法完成递归,首先创建一个子函数Fact() 子函数分析 最后完成主函数...} 要想完成1234的分离,首先把4分离出来,其次在分离3,一直分离到1,传递参数进入子函数,1234>9,在进入123,,123也大于9,进入12,还是大于9,在进入1,1递归结束,首先完成1的打印...利用图来解释更为直观一些,函数递归一直执行到限制条件为止,正如开头所说,执行到1为止,依次回归,打印各位数字 最后完成程序 #include void Print(long n) {...,却能执行复杂的计算,一定程度上为程序员节省了时间,但是递归有时也有缺点,计算过程复杂导致计算慢,更多的需要程序员去探索

    1.3K10

    递归函数和匿名函数

    一、递归 1.1 递归的应用场景 递归是一种编程思想,应用场景: 在我们日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现; 在后续的算法课程中,很多算法都离不开递归,例如:快速排序...1.1.1 递归的特点 函数内部自己调用自己 必须有出口 1.2 应用:3以内数字累加和 代码 # 3 + 2 + 1 def sum_numbers(num): # 1.如果是1,直接返回1...1 # 2.如果不是1,重复执行累加并返回结果 return num + sum_numbers(num-1) sum_result = sum_numbers(3) # 输出结果为6...2.2 lambda语法 lambda 参数列表 : 表达式 注意 lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。...10, 20)) 2.4.4.可变参数:*args fn1 = lambda *args: args print(fn1(10, 20, 30)) 注意:这里的可变参数传入到lambda之后,返回值为元组

    71550
    领券