学习笔记
学习书目:《算法图解》- Aditya Bhargava


文章目录

  • 递归
  • 基线条件和递归条件
    • 调用栈
    • 递归调用栈

递归

首先,我们看一段代码:

def print_num(my_list):for i in my_list:print(i)print_num([1, 3, 5, 7, 9])

输出:

1
3
5
7
9

再看一段代码:

def print_num2(my_list):if my_list:print(my_list.pop(0))print_num2(my_list)print_num2([1, 3, 5, 7, 9])

输出:

1
3
5
7
9

我们看到的第一段代码使用的是循环,第二段代码使用的是递归,两种方法结果相同。一般来说,递归能让解决方案更清晰(虽然我举的例子好像没体现出来递归法更清晰),但并没有性能上的优势。实际上,在有些情况下,使用循环的性能更好。

如果使用循环,程序的性能可能更高;如果使用递归,程序可能更容易理解。如何选择要看什么对你来说更重要。

基线条件和递归条件

由于递归函数调用自己,因此编写这样的函数时很容易出错,进而导致无限循环。例如,假设我要编写一个像下面这样倒计时的函数:

def countdown(i): print(i) countdown(i-1)

如果我们运行上述代码,将发现一个问题:这个函数运行起来没完没了!

编写递归函数时,必须告诉它何时停止递归。正因为如此,每个递归函数都有两部分:基线条件(base case)和递归条件(recursive case)。递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。

我们来给countdown函数添加一个基线条件:

def countdown(i): print(i)if i <= 1:returnelse:countdown(i-1)

现在,这个函数就会像预期那样运行.

假设我们有一叠便条,这叠便条记录着我们马上要做的待办事项,我们简称这叠便条为清单。当我们插入的待办事项时,这个事件会放在清单的最上面;当我们读取待办事项时,也只读取清单最上面的那个,且读完就将其销毁。因此这个清单只有两种操作:压入(插入)和弹出(删除并读取)。

这种数据结构被称为栈。

调用栈

计算机在内部使用被称为调用栈的栈。

为了演示计算机是如何调用栈的,我们来看下面这个简单的函数:

def greet(name):print(name, '!')greet2(name)print('too late!')bye()def greet2(name):print(name, '?')def bye():print('bye!')greet('maggie')

注意!print是一个函数,但是出于简化考虑,我们假设它不是函数。

假设,我们调用greet('maggie'),计算机将首先为该函数调用分配一块内存空间:

变量name被赋值为maggie,这需要存储到内存中:

当我们调用函数时,计算机会将函数调用涉及的所有变量的值存储到内存中。接下来,我们再调用greet2('maggie').同样,计算机也为这个函数调用分配一块内存。

计算机使用一个栈来表示这些内存块,其中第二个内存块位于第一个内存块上面。我们打印maggie ?,然后从函数greet2的调用返回。此时,栈顶的内存块被弹出。

现在,栈顶的内存块是函数greet的,这意味着我们返回到了函数greet。当我调用函数greet2时,函数greet只执行了一部分。调用另一个函数时,当前函数暂停并处于未完成状态,该函数的所有变量的值仍在内存中。

当执行完greet2函数后,我们继续向下执行,首先打印too late!,再调用函数bye()。计算机在栈顶添加了函数bye的内存块,然后我们打印bye!,并从该函数中返回。

现在,我们又回到了greet函数,由于无事可做,我们就从greet函数中返回。这个栈用于存储多个函数的变量,故被称为调用栈。

递归调用栈

递归函数也使用调用栈,我们来看看下面这个递归函数fact:

def fact(x):if x == 1:return 1else:return x*fact(x-1)print(fact(3))

输出:

6

下面我们来看一下调用fact(3)时,调用栈的变化:

每个fact调用都有自己的x变量,在一个函数调用中不能访问另一个函数的x变量。

小白的算法初识课堂(part3)--递归相关推荐

  1. 小白的算法初识课堂(part4)--快速排序

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 分而治之 在这里,我想通过2个例子介绍一种著名的递归式问题解决方法–分而治之(D&C) 分蛋糕 假如,我要分一块 ...

  2. 小白的算法初识课堂(part9)--SHA及Simhash算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 安全散列算法(SHA) 在学SHA算法之前,我们先回顾一下前几个Blog所学的散列函数. 散列函数是这样的一个函数,即无 ...

  3. 小白的算法初识课堂(part8)--贪婪算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 教室调度问题 集合覆盖问题 近似算法 代码实现 NP完全问题 教室调度问题 假如我是一个学校的校长,我们学校有 ...

  4. 小白的算法初识课堂(part7)--狄克斯特拉算法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 狄克斯特拉算法 具体步骤实现 术语 跳蚤市场 具体步骤实现 负权边 python实现 狄克斯特拉算法 在上一个 ...

  5. 小白的算法初识课堂(part6)--广度优先搜索

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 图简介 图是啥 广度优先搜索 寻找最短路径 队列 实现图 实现算法 运行时间 图简介 今天是五一,假如我要从家 ...

  6. 小白的算法初识课堂(part5)--散列表

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 散列函数 防止重复 冲突 性能 填装因子 散列函数 散列函数是这样的一个函数,即无论你给它什么样的数据,它都还 ...

  7. 小白的算法初识课堂(part2)--选择排序

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 文章目录 选择排序 内存工作原理 数组 链表 读取 索引 插入 删除 是常见的数组和链表操作的运行时间 选择排序 pyt ...

  8. 小白的算法初识课堂(part1)--二分查找法

    学习笔记 学习书目:<算法图解>- Aditya Bhargava 二分查找法 算法是一组完成任务的指令,任何代码片段都可视为算法.二分查找是一种算法,其输入是一个有序的元素列表(必须有序 ...

  9. 小白的奇幻数学课堂(part3)--你能把一张纸对折7次以上吗

    学习笔记 学习书目:<x的奇幻之旅>–史蒂夫•斯托加茨 一张纸对折8次 把一张纸对折7次或8次以上,成为一个几乎不可能完成的任务.每对折一次,纸的厚度就会增加一倍,如果不断地对折一张纸,纸 ...

最新文章

  1. SQLServer查询指定日期
  2. SELECT LAST_INSERT_ID() 的使用和注意事项
  3. ubuntu创建文件夹和删除文件
  4. 如何通过OpenFace实现人脸识别框架
  5. 在 VS Code 中轻松 review GitHub Pull Requests
  6. C# numericUpDown控件用法总结及注意事项
  7. 降级安装_如何升级iOS13测试版,还有降级
  8. Visual Studio中相对路径中的宏定义,你不了解的宏定义都在这里!
  9. 安卓加java完成登录_从零学习安卓自动化(java+appium方向):完成登录操作+一个主流程(四)...
  10. 正则表达式,删除空行,删除特定字符所在行
  11. 如何实现公平的效绩考核?
  12. 【深度学习】卷积神经网络(Convolutional Neural Network)
  13. 【图像分割】基于matlab人工鱼群算法图像分割【含Matlab源码 1488期】
  14. python广州地图_广东省客户数量地图展示,如何通过python实现?
  15. 马斯克发布会视_马斯克会成为我们的救星还是驱逐舰?
  16. verilog从txt中读取_将Verilog中的二进制文件数据读入2D数组
  17. 报错:Unable to check if JNs are ready for formatting
  18. 华为AP 6050DN配置成家庭路由器
  19. XDOJ综合题 数字统计排序
  20. 【JVM · 字节码】指令集 解析说明

热门文章

  1. 机器学习(二)——广义线性模型、生成学习算法
  2. BZOJ1941:[SDOI2010]Hide and Seek(K-D Tree)
  3. 08.Eclipse下Ndk开发(使用fmod实现QQ变声功能)
  4. 必须学会使用的35个Jquery小技巧
  5. CRM的使用是讲究技巧的
  6. 一、spring mvc简介
  7. 解决VS2010子目录中的.cpp文件引用上一级目录的stdafx.h找不到定义的问题
  8. TianyaDL_4thread天涯帖子下载4线程版
  9. 笔记本关于虚拟机桥接小问题
  10. [收藏]61条面向对象设计的经验原则