递归调用

C_函数_递归

我们两清 提交于 2019-11-28 03:13:56
1.定义 一个函数直接或间接地调用自己 2.不同函数间的相互调用 ​ 1 #include<stdio.h> 2 3 void a(void); //函数声明 4 void b(void); 5 void c(void); 6 7 void a(void) 8 { 9 printf("aaaa\n"); //②执行完这一步,然后跳转到b()函数 10 b(); 11 printf("1111\n"); //⑥执行完a()剩下语句后回到main函数 12 } 13 14 void b(void) 15 { 16 printf("bbbb\n"); //③执行完这一步跳转到c()函数 17 c(); 18 printf("2222\n"); //⑤执行完b()剩下的语句后回到a() 19 } 20 21 void c(void) 22 { 23 printf("cccc\n"); 24 printf("3333\n"); //④执行完c()后回到b()函数执行剩下语句 25 } 26 27 int main(void) //①程序从main函数开始 28 { 29 a(); 30 31 return 0; 32 } 输出:​ ​aaaa bbbb cccc 3333 2222 1111 3.递归举例 1 #include<stdio.h> 2 3 void f(int n) 4 { 5

Python学习日记(十三) 递归函数和二分查找算法

限于喜欢 提交于 2019-11-28 03:11:51
什么是递归函数? 简单来说就是在一个函数中重复的调用自己本身的函数 递归函数在调用的时候会不断的开内存的空间直到程序结束或递归到一个次数时会报错 计算可递归次数: i = 0 def func(): global i print('i = {}'.format(i)) i += 1 return func() func()            #.....i = 994 i = 995 RecursionError: maximum recursion depth exceeded while calling a Python object 在这里我们修改我们可递归的次数: import sys sys.setrecursionlimit(1000000) i = 0 def func(): global i print('i = {}'.format(i)) i += 1 return func() func() #...i = 3924 i = 3925 如果还想递归更多的次数,就必须要提升计算机的性能了 递归函数的 优点 就是能让一个问题变得简单,但 缺点 就是太占用内存,因此递归函数不适合解决需要大规模递归运算的问题 二分查找算法: 这个被查询的列表必须是一个 有序 的列表 def find(l,aim,start = 0,end = None): end = len(l

尾调用与尾递归优化

倖福魔咒の 提交于 2019-11-28 01:57:32
  〇、是为序  以前也看到过尾递归及其优化,但在当时并不完全能够理解,最近几天陆陆续续复习了一下《汇编语言》和《自己动手写操作系统》两本书,对于函数调用背后的栈机制有了更加清晰的理解,回过头来看尾递归就觉得容易理解多了。   就像 阮一峰 老师在下文中所写的那样,栈溢出在递归程序编写过程中是常会出现的错误,但有时把递归程序改写成非递归可能并非易事,此时考虑一下采用尾递归或者相关优化技术就非常有必要,虽然这篇文章是使用javascript为例写的,但对于C++等也完全适用,特转载此文以备忘。    以下转自http://www.ruanyifeng.com/blog/2015/04/tail-call.html   尾调用 (Tail Call)是函数式编程的一个重要概念,本文介绍它的含义和用法。 一、什么是尾调用?   尾调用的概念非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。 function f(x){ return g(x); }    上面代码中,函数f的最后一步是调用函数g,这就叫尾调用。 以下两种情况,都不属于尾调用。 // 情况一 function f(x){ let y = g(x); return y; } // 情况二 function f(x){ return g(x) + 1; }    上面代码中,情况一是调用函数g之后

尾调用优化和尾递归改写

安稳与你 提交于 2019-11-28 01:57:23
1 尾调用 尾调用就是指某个函数的最后一步是调用另一个函数。 # 是尾调用 def f(x): return g(x) # 不是尾调用,因为调用函数后还要执行加法,加法才是最后一步操作 def f(x): return 1+g(x) 2 尾调用优化 函数调用有一个调用栈,栈内保存了这个函数内部的变量信息。函数掉用就是切换不同的调用帧,从而保证每个函数有独立的运行环境。因为尾调用是函数的最后一步操作,所以在进入被尾调用函数之前并不需要保留外层函数的运行时环境,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。这就叫做"尾调用优化"(Tail call optimization),即只保留内层函数的调用记录。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用记录只有一项,这将大大节省内存。这就是"尾调用优化"的意义。 尾递归 如果尾调用自身,就称为尾递归。递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生"栈溢出"错误(stack overflow)。但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误。 def factorial(n) { if (n == 1) return 1; return n * factorial(n - 1); } factorial(5) // 120

尾调用和尾递归

佐手、 提交于 2019-11-28 01:57:03
尾调用 尾调用 (Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。 //尾调用 function f(x) {return g(x);} //上面代码中,函数f的最后一步是调用函数g,这就叫尾调用 //不属于尾调用举例 // 情况一 function f(x){ let y = g(x); return y; } // 情况二 function f(x){ return g(x) + 1; } // 情况三 function f(x){ g(x); } 尾调用优化 尾调用之所以与其他调用不同,就在于它的特殊的调用位置。 我们知道,函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B内部还调用函数C,那就还有一个C的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。 尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。 function f() { let m = 1; let n

尾调用和尾递归

感情迁移 提交于 2019-11-28 01:56:48
尾调用 1. 定义 尾调用是函数式编程中一个很重要的概念,当一个函数执行时的最后一个步骤是返回另一个函数的调用,这就叫做尾调用。 注意这里函数的调用方式是无所谓的,以下方式均可: 函数调用: func(···) 方法调用: obj.method(···) call调用: func.call(···) apply调用: func.apply(···) 复制代码 并且只有下列表达式会包含尾调用: 条件操作符: ? : 逻辑或: || 逻辑与: && 逗号: , 复制代码 依次举例: const a = x => x ? f() : g(); // f() 和 g() 都在尾部。 复制代码 const a = () => f() || g(); // g()有可能是尾调用,f()不是 // 因为上述写法和下面的写法等效: const a = () => { const fResult = f(); // not a tail call if (fResult) { return fResult; } else { return g(); // tail call } } // 只有当f()的结果为falsey的时候,g()才是尾调用 复制代码 const a = () => f() && g(); // g()有可能是尾调用,f()不是 // 因为上述写法和下面的写法等效: const

JavaScript函数尾调用与尾递归

安稳与你 提交于 2019-11-28 01:56:33
什么是函数尾调用和尾递归 函数尾调用与尾递归的应用 一、什么是函数的尾调用和尾递归 函数尾调用就是指函数的最后一步是调用另一个函数。 1 //函数尾调用示例一 2 function foo(x){ 3 return g(x); 4 } 5 //函数尾调用示例二 6 function fun(x){ 7 if(x > 0){ 8 return g(x); 9 } 10 return y(x); 11 } 调用最后一步和最后一行代码的区别,最后一步的代码并不一定会在最后一行,比如示例二。还有下面这一种不能叫做函数尾调用: 1 // 下面这种情况不叫做函数尾调用 2 function fu(x){ 3 var y = 10 * x; 4 g(y); 5 } 为什么这种情况不叫作函数的尾调用呢?原因很简单,因为函数执行的最后一步是return指令,这个指令有两个功能,第一个功能是结束当前函数执行,第二个功能是将指令后面的数据传递出去(函数返回值)。而这个return指令不管有没有声明都会执行,没有声明的情况下返回的数据是undefined,所以上面的代码实际上是以下结构: 1 function fu(x){ 2 var y = 10 * x; 3 g(y); 4 return undefined; 5 } return指令是先关闭函数,然后再返回数据。说到这里,就会引发一个问题出来

python函数参数、参数解构、作用域、递归及匿名函数

末鹿安然 提交于 2019-11-28 01:45:56
一、python函数 由若干语句组成的语句块,函数名称,参数列表构成,它是组织代码的最小单元,通过函数完成一定的功能 1、函数的作用 结构化编程对代码的最基本封装,一般按照功能组织一段代码 封装的目的是为了功能复用,减少冗余代码 使代码更加简洁美观,可读易懂 2、函数的分类 内建函数,如:max(),reversed()等 库函数,如math.ceil()等 3、函数的定义和调用 定义 def语句定义函数 函数名就是标识符,命名要求一样 语句块必须缩进,约定4个空格 python的函数若没有return语句,隐式会返回一个None值 定义中的参数列表成为形式参数,只是一种符号表达,简称形参 调用 函数定义只是声明了一个函数,它不会被执行,需要调用 调用方式,就是函数名加上小括号,括号内写参数 调用时写的参数是实际参数,是实实在在的传入的值,简称实参 二、函数参数 参数调用时传入的参数要和定义的个数相匹配(可变参数例外) 位置参数:按照参数定义顺序传入实参fn(1,2) 关键字参数:使用形参的名字来传入实参的方式,如果使用了形参名字,那么传参顺序就可以随意fn(x=1,y=1) 传参:要求位置参数必须在关键字参数之前传入,位置参数是位置对应的; 1、函数参数默认值 参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值 参数非常多的时候

说说尾递归

与世无争的帅哥 提交于 2019-11-28 01:15:50
微博上看到有人在讨论尾递归,想起以前曾看过老赵写的一篇相关的博客,介绍的比较详细了,相信很多人都看过,我也在下面留了言,但挑了个刺,表示文章在关键点上一带而过了,老赵自然是懂的,但看的人如果不深入思考,未必真正的明白,下面我说说我的理解。 什么是尾递归 什么是尾递归呢?(tail recursion), 顾名思议,就是一种“不一样的”递归,说到它的不一样,就得先说说一般的递归。对于一般的递归,比如下面的求阶乘,教科书上会告诉我们,如果这个函数调用的深度太深,很容易会有爆栈的危险。 // 先不考虑溢出问题 int func(int n) { if (n <= 1) return 1; return (n * func(n-1)); } 原因很多人的都知道,让我们先回顾一下函数调用的大概过程: 1)调用开始前,调用方(或函数本身)会往栈上压相关的数据,参数,返回地址,局部变量等。 2)执行函数。 3)清理栈上相关的数据,返回。 因此,在函数 A 执行的时候,如果在第二步中,它又调用了另一个函数 B,B 又调用 C.... 栈就会不断地增长不断地装入数据,当这个调用链很深的时候,栈很容易就满 了,这就是一般递归函数所容易面临的大问题。 而尾递归在某些语言的实现上,能避免上述所说的问题,注意是某些语言上,尾递归本身并不能消除函数调用栈过长的问题,那什么是尾递归呢?在上面写的一般递归函数

python装饰器与递归

落花浮王杯 提交于 2019-11-27 21:13:48
装饰器 开放封闭原则: 装饰器:装饰,装修,房子就可以住,如果装修,不影响你住,而且体验更加,让你生活中增加了很多功能:洗澡,看电视,沙发。 器:工具。 开放封闭原则: 开放:对代码的拓展开放的, 更新地图,加新枪,等等。 封闭:对源码的修改是封闭的。闪躲用q。就是一个功能,一个函数。 别人赤手空拳打你,用机枪扫你,扔雷.....这个功能不会改变。 装饰器:完全遵循开放封闭原则。 装饰器: 在不改变原函数的代码以及调用方式的前提下,为其增加新的功能。 装饰器就是一个函数。 推导见代码 标准版的装饰器; 标准版的装饰器; def wrapper(f): f=zz #第2步 def inner(*args,**kwargs):#第5步 '''添加额外的功能:执行被装饰函数之前的操作'''#第6步 ret = f(*args,**kwargs)#第7步 ''''添加额外的功能:执行被装饰函数之后的操作'''#第8步 return ret return inner #第3步 @weapper# zz=weapper(zz) 第一步 def zz()#第4步 此时zz 为 inner pass 带参数的装饰器 def wrapper_out(n,*args,sex="男") def wrapper(f): def inner(*args,**kwargs): ret = f(*args,*