尾递归

递归与尾递归

假如想象 提交于 2020-04-06 23:54:02
下面两个程序是scheme写的计算阶乘的递归和尾递归实现 线性递归: (define (factorial n) (if (=n 1) 1 (* n (factorial (- n 1))))) 尾递归: (define (factorial n) (fact-iter 1 1 n)) (define (fact-iter product counter max-count) (if (> counter max-count) product (fact-iter (* counter product) (+ counter 1) max-count))) 用C写出来就是这样的: 线性递归: long factorial(long n) { return(n == 1) ? 1 : n * factorial(n - 1); } 尾递归: long fact_iter(long product, long counter, long maxcount) { return (counter > maxcount) ? product : fact_iter(product*counter, counter+1, maxcount); } long factorial(long n) { return fact_iter(1, 1, n); } 线性递归程序基于阶乘的递归定义,即

【Python学习笔记】递归函数

余生颓废 提交于 2020-04-06 21:50:38
★特殊的一种函数——递归函数 通常,函数是靠调用其他函数完成自己的功能的,但是还存在一种调用方式是:函数调用它自身,这样的函数称为递归函数 递归函数是利用'栈'实现的,递归函数的优点是定义简单,逻辑清晰,缺点是比较占用资源,且容易造成栈溢出,甚至导致崩溃 # 常见的递归函数是计算阶乘 def fact(n): if n==1: return 1 return n * fact(n - 1) print fact(5) 运行效果: # 理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。 # ★★★如非必须,尽量不用递归函数★★★ #每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。 # print fact(1000) # 报错 # 解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。 # 尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况# # 使用尾递归优化的计算阶乘 def fact(n): return fact_iter(n, 1) def fact_iter

Java中尾递归

你。 提交于 2020-03-22 15:25:03
在以往解决需要递归求解的问题上一直使用传统递归,而不久前老师讲解了尾递归感觉需要记录一下(好记性不如烂笔头) 尾递归特点:在普通尾调用上,多出了2个特征。 1. 在尾部调用的是函数自身(Self-called) 2. 可通过优化,使得计算仅占常量栈空间(Stack Space) 举个例子: 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用。 下面代码仅求斐波那契数列的第n项为多少,而不求前n项和。 1 public class Fibonacci { 2 3 public static void main(String[] args) { 4 int n = 50; 5 long begin1 = System.currentTimeMillis(); 6 System.out.printf("%d\n", fibonacci(n)); 7 long end1 = System

python-递归函数

蹲街弑〆低调 提交于 2020-03-15 23:20:32
#recursion_function.py #-*- coding:utf-8 -*- def recursion(x): if x == 1: return 1 return x * recursion(x - 1) f1 = recursion(1) f2 = recursion(2) f3 = recursion(3) f4 = recursion(4) print f1, f2, f3, f4 递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。 使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。 解决递归调用栈溢出的方法是通过 尾递归 优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。 尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。 上面的 fact(n) 函数由于 return n * fact(n - 1) 引入了乘法表达式,所以就不是尾递归了

Tail Recursion尾递归

为君一笑 提交于 2020-03-15 22:38:00
什么是尾递归 Tail Recursion /teɪl rɪˈkɜːrʒn/ In traditional recursion , the typical model is that you perform your recursive calls first, and then you take the return value of the recursive call and calculate the result. In this manner, you don't get the result of your calculation until you have returned from every recursive call. In tail recursion , you perform your calculations first, and then you execute the recursive call, passing the results of your current step to the next recursive step. This results in the last statement being in the form of ( return (recursive-function params) ). Basically,

C Primer Plus 第9章 函数 9.3 递归

情到浓时终转凉″ 提交于 2020-03-01 06:13:05
9.3.1 递归的使用 为了具体说明,请看下面的例子。程序清单9.6中函数main()调用了函数up_and_down()。 我们把这次调用称为“第一级递归”。然后up_and_down()调用其本身,这次调用叫做“第二级递归”。 第2级递归调用第3级递归,依此类推。为了深入其中看看究竟发生了什么, 程序不仅显示出了变量n的值,还显出出了存储n的内存的地址&n(本章稍后部分将更全面的讨论&运算符。 printf()函数使用%p说明符来指示地址 )。 程序清单9.6 recur.c程序 /*recur.c --递归举例*/ #include <stdio.h> void up_and_down(int); int main(void) { up_and_down(1); return 0; } void up_and_down (int n) { printf("Level %d : n location %p\n",n,&n); /*1*/ if(n<4) up_and_down(n+1); printf("Level %d : n location %p\n",n,&n); /*2*/ } 我们来分析程序中递归的具体工作过程。首先main()使用参数1调用了函数up_and_down()。于是up_and_down()中形式参量n的值为1,故打印语句#1输出了Leve 1。 然后

什么是尾递归

安稳与你 提交于 2020-02-26 14:35:13
递归算法想必大家都已经很熟悉了。递归算法虽然简单,但是容易导致一些性能问题,于是就有了尾递归这种优化算法。 首先我们先看看递归算法的性能问题是在哪里? 比如我们有一个常见的算法,叫做阶乘算法。 f ( x ) = 1 ⋅ 2 ⋅ 3 ⋯  ⁣ x f(x)=1\cdot2\cdot3\cdots\!x f ( x ) = 1 ⋅ 2 ⋅ 3 ⋯ x 他的递归实现是这样子的 KaTeX parse error: Unknown column alignment: 1 at position 15: \begin{array}{1̲}f(x)=x f(x-1)\… 实现代码如下 //C#实现 int Foo ( int x ) { if ( x == 1 ) { return 1 ; } return x * Foo ( x - 1 ) ; } #python 实现 def foo ( x ) : if ( x == 1 ) : return 1 return x * foo ( x - 1 ) 我们看到每次调用foo方法的时候,又会执行一次foo方法。 此时程序会将当前上下文压栈,计算出下一个foo的值,然后再出栈和x进行相乘 所以对于foo(3)的调用,整个栈的情况是这样的 KaTeX parse error: Unknown column alignment: 1 at

递归、尾递归和使用Stream延迟计算优化尾递归

ε祈祈猫儿з 提交于 2020-02-13 10:41:58
我们在学数据结构的时候必然会接触栈(Stack),而栈有一个重要的应用是在程序设计语言中实现递归。递归用途十分广泛,比如我们常见的阶乘,如下代码: 1234 public static int (int n) { if (n == 1) return 1; return n * func1(n - 1);} 就可以用递归实现,而且实现相当简洁。如果要计算n的阶乘,那么只需知道n-1的阶乘再乘以n,同理依次类推,直到当我们计算2的阶乘的时候,只需知道1的阶乘,显然这是递归终止条件,再层层向上返回,直至计算出n的阶乘即可。 从上面的分析可以看出,如果我们要进行递归求解某一问题,需要满足以下两个条件: 能将一个问题转变为另一个新问题,而新问题的解法与原问题相同或者类同,并且新问题的数据规模更小,问题简化。 使用递归的情景是当前数据规模较大,直接计算比较困难,那么可以将该问题进行分解,数据规模越来越小,计算也越来越容易,其实这是“分治法”的体现。 存在递归终止条件,或者说递归的边界。 递归的终止条件是必须的,既然当前问题可以分解,那么就必须存在一个“极限”,分解到什么程度?到哪里停止? “分治法”求解递归问题算法有一个一般形式: 1234 void p(参数列表) { if (递归终止条件成立) 直接求解; // 递归终止条件 else p(较小的参数) // 递归步骤}

Continuation Passing Style

孤者浪人 提交于 2020-02-07 12:08:24
CPS(Continuation Passing Style, 后续传递风格), 是指将程序的控制流显示地用 Continuation 来传递,而不是像 direct style 那样明确指出下一条语句的编码风格。符合 CPS 的函数需要一个额外的参数:一个显式的Continuation (通常为一个只有一个参数的函数)。一个CPS函数通过以返回值为参数,调用Continuation的方式来返回函数值。当我们调 用一个CPS函数式,被调用的函数需要一个额外的 return procedure 来供被调用的函数使用。用CPS的方式来表达代码可 以使普通程序中很多不明确的内容变得明确。例如,函数的返回值看起来就像是对Continuation的调用,参数的求值顺序也 变得明确,同时,尾调用(tail call)也被直接传递给调用者(caller)。 一个函数可以被自动地从 direct style 转换成 continuation passing style。当在命令式或者过程式语言的编译器中 需要表达SSA(事实上,SSA可以被视作CPS的一个子集)时,编译器可以使用CPS来表达中间代码。 正常函数的返回都隐含一个continuation,就是利用这个函数的返回值来 做的后续事情,而cps的本质就是将这个隐式的 continuation显式的当做参数传递进去

Python递归函数如何写?正确的Python递归函数用法!

こ雲淡風輕ζ 提交于 2020-02-01 14:29:49
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 一、举个例子,我们来计算阶乘n! = 1 x 2 x 3 x … x n,用函数fact(n)表示,可以看出: fact(n) = n! = 1 x 2 x 3 x … x (n-1) x n = (n-1)! x n = fact(n-1) x n 所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。 ps:另外很多人在学习Python的过程中,往往因为没有好的教程或者没人指导从而导致自己容易放弃,为此我建了个Python交流.裙 :一久武其而而流一思(数字的谐音)转换下可以找到了,里面有最新Python教程项目可拿,不懂的问题多跟里面的人交流,都会解决哦! 于是,fact(n)用递归的方式写出来就是: def fact(n): if n==1: return 1 return n * fact(n - 1) 上面就是一个递归函数。可以试试: fact(1) 1 fact(5) 120 fact(100)