笔记:《算法图解》第三章:递归、栈

1.递归

递归指的是调用自己的函数。
1.1 递归与循环:
如果使用循环,程序的性能可能更高;如果使用递归,程 序可能更容易理解。如何选择要看什么对你来说更重要。

1.2 递归函数常见难点:
由于递归函数调用自己,因此编写这样的函数时很容易出错,进而导致无限循环。编写递归函数时,必须告诉它何时停止递归。正因为如此,每个递归函数都有两个条件基线条件(basecase)和递归条件(recursive case)。递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。

1.3 递归示例

编写一个倒计时函数
def countdown(i):
  # 基线条件
  if i <= 0:
    return 0
  # 递归条件
  else:
    print(i)
    return countdown(i-1)

countdown(5)

2.栈与调用栈

2.1栈:
栈(stack)作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。栈有两种操作:压入和弹出。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。

https://baike.baidu.com/item/%E6%A0%88/12808149?fr=aladdin

2.2调用栈
调用栈(英语:Call stack,英文直接简称为“栈”(the stack))别称有:执行栈(execution stack)、控制栈(control stack)、运行时栈(run-time stack)与机器栈(machine stack),是计算机科学中存储有关正在运行的子程序的消息的栈。有时仅称“栈”,但栈中不一定仅存储子程序消息。几乎所有计算机程序都依赖于调用栈,然而高级语言一般将调用栈的细节隐藏至后台。
调用栈最经常被用于存放子程序的返回地址。调用另一个函数(子程序)时,当前函数(主程序)暂停并处于未完成状态,该函数的所有变量的值都还在内存中。因此,如果被调用的子程序还要调用其他的子程序,其自身的返回地址就必须存入调用栈,在其自身运行完毕后再行取回。在递归程序中,每一层次递归都必须在调用栈上增加一条地址,因此如果程序出现无限递归(或仅仅是过多的递归层次),调用栈就会产生栈溢出

https://baike.baidu.com/item/%E8%B0%83%E7%94%A8%E6%A0%88

所有函数调用都进入调用栈。使用栈虽然很方便,但是也要付出代价:每个函数调用都要占用一定的内存,如果栈很高,就意味着计算机存储了大量函数调用的信息,将占用大量的内存。
在这种情况下,你有两种选择:
❑ 重新编写代码,转而使用循环。
❑ 使用尾递归。这是一个高级递归主题,不在本书的讨论范围内。另外,并非所有的语言都支持尾递归。

练习

3.1根据下面的调用栈,你可获得哪些信息?习题3.1
3.2 假设你编写了一个递归函数,但不小心导致它没完没了地运行。正如你看到的,对于每次函数调用,计算机都将为其在栈中分配内存。递归函数没完没了地运行时,将给栈带来什么影响?

答案

3.1 下面是一些你可获得的信息。
❑ 首先调用了函数greet,并将参数name的值指定为maggie。
❑ 接下来,函数greet调用了函数greet2,并将参数name的值指定为maggie。
❑ 此时函数greet处于未完成(挂起)状态。
❑ 当前的函数调用为函数greet2。
❑ 这个函数执行完毕后,函数greet将接着执行。
3.2 栈将不断地增大。每个程序可使用的调用栈空间都有限,程序用完这些空间(终将如此)后,将因栈溢出而终止。

《算法图解》- Aditya Bhargava

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值