算法图解第三章--递归的深层次理解(学习笔记)

《算法图解》读书笔记 第三章 递归 调用栈(函数调用时进入的调用栈) 文章目录关注我的公众号~ 一起学习1.本章内容 关注我的公众号~ 一起学习 欢迎大家扫码关注我的公众号~ 获取更多学习资源与内容 目前学习内容: 前端基础知识点学习-JS红宝书/CSS权威手册(这个就不发了哈哈哈当个兴趣) 跟着《算法图解》扎实学习数据结构与算法 从0.1开始的C++编程小练习 吴恩达深度学习课程笔记 人工智能领域研究&学习 关注我 一起在代码之路上前行 最重要的 是互相督促着一起学习鸭~ 1.本章内容 学习递归 递归是很多算法都使用的一种编程方法 是理解本书后续内容的关键 阅读详情

一、推荐:

如果想更好的理解本文章,你可以看往期文章:

算法图解第二章–选择排序法(数组,链表的进一步理解)(学习笔记)

二、基线条件和递归条件

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

这个代码会出现一直运行的情况(你可以按Ctrl+C停止运行),之所以会出现这样的情况是因为没有告诉它何时停止递归,所以每个递归函数都应该包含两部分:基线条件和递归条件,去避免形成无限循环。改良后的代码:

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

三、栈

大部分人学函数时就了解了递归,诸如的经典例子便是汉诺塔问题,如果想要了解的点击下面:
用递归来解决汉诺塔问题(超详细的个人解读)(Python)

我们先来理解一个重要的编程概念——调用栈(call stack)。

调用栈不仅对编程来说很重要,使用递归时也必须理解这个概念。

那什么是栈呢?
在这里插入图片描述
(如果想要全本电子书可以去我的主页里简介获取)
这是书上的解释,可能你没有耐心去理解,我总结了一下,看图理解:

在这里插入图片描述

你可以假设这是一个只有一个出口,三面封闭的盒子。

你如果往里面放东西,先放进去的东西就会被后放进去的东西压在下面,而当你想要去拿出被压在下面东西的时候,你就必须先取出上面的东西(也就是你后放进去的东西).

其实书上的例子就好比你写了一堆标签,然后一个钉子把他们钉在了墙上,你就只能从外面一个一个拿(注意后面写的标签在外面,也就是先依次写一堆标签,然后反向依次处理)。

四、调用栈

既然你都理解了“栈”,那么如何调用它呢?我们先写一段简单代码辅助理解。

def greet2(name):
    print("你好!{}".format(name))
def bye(name):
    print("再见!{}".format(name))
def greet(name):
    print("Hello!{}".format(name))
    greet2(name)
    print("最近好吗?")
    bye(name)
greet("maggie")

结果:

Hello!maggie
你好!maggie
最近好吗?
再见!maggie

下面来详细介绍函数运行情况(我觉得这本书这里写得很明白,就照着书说一下):
首先,你调用greet(“maggie”),计算机将首先为该函数调用分配一块内存。如图:
在这里插入图片描述

我们来使用这些内存。

变量name被设置为“maggie”,这需要存储到内存中。
在这里插入图片描述

每当你调用函数时,计算机都像这样将函数调用涉及的所有变量的值存储到内存中。

接下来,你打印 Hello!maggie,再调用greet2(“maggie”)。

同样,计算机也为这个函数调用分配一块内存。
在这里插入图片描述

计算机使用一个栈来表示这些内存块,其中第二个内存块位于第一个内存块上面。

你打印 你好!maggie,然后从函数调用返回。

此时,栈顶的内存块被弹出。

在这里插入图片描述

现在,栈顶的内存块是函数greet的,这意味着你返回到了函数greet。

当你调用函数greet2时,函数greet只执行了一部分。

这是本节的一个重要概念:调用另一个函数时,当前函数暂停并处于未完成状态。该函数的所有变量的值都还在内存中。执行完函数greet2后,你回到函数greet,并从离开的地方开始接着往下执行,

首先打印 最近好吗?,再调用函数bye。

在这里插入图片描述

在栈顶添加了函数bye的内存块。然后,你打印再见!maggie,并从这个函数返回。在这里插入图片描述

现在你又回到了函数greet。由于没有别的事情要做,你就从函数greet返回。这个栈用于存储多个函数的变量,被称为调用栈。

五、递归调用栈

先写一段阶乘代码辅助理解下:

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

简单理解的话就是:
假如x=3,,先运行else语句,就会得到 xfact(x-1),此时x为3,也就是3fact(2),

fact(2)函数会运行else语句则返回xfact(x-1),此时x为2,也就是2fact(1),综合上一句就是32fact(1),

fact(1)函数会运行if 语句,则返回1,综上所述便是311=6,

其实递归的话就是只有运行到fact(1)语句才会运行基线条件,也只有运行了基线条件,递归才会结束,

然后反向依次返回(就是依次返回1,2,6)。

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

.这是我的理解,可能有一些不足,下面放上书上的理论理解:

在这里插入图片描述
在这里插入图片描述

再次注意:
每个fact调用都有自己的x变量。在一个函数调用中不能访问另一个的x变量。
其实学下来,你会发现,使用栈虽然很方便,但是也要付出代价

存储详尽的信息可能占用大量的内存。每个函数调用都要占用一定的内存

如果栈很高,就意味着计算机存储了大量函数调用的信息

所以递归只是让解决方案更清晰,并没有性能上的优势。

实际上,在有些情况下,使用循环的性能更好。

《算法图解》——第三章 递归                                  第三章    递归1    递归大佬说:“如果使用循环,程序的性能可能更高;如果使用递归,程序可能更容易理解。如何选择要看什么对你来说更重要。”2    基线条件和递归条件每个递归函数都有两部分:基线条件(base case)和递归条件(recursive case)。递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,... 阅读详情

相关推荐

《算法图解》观后感

算法,我该拿你怎么办? 写这篇博客倒不是为了蹭现在算法的热度,而主要是为了下面两个目的: 推荐一本算法幼儿园级别的入门书籍《算法图解》 思考算法跟业务开发程序员的关系 如果是像我一样干业务型的程序员,对算法估计都没有什么很深的感觉,因为一般的难点都在于如何快速响应产品那边来的各种需求,还有修复自己亲手写的Bug,算法,好像在我们的生活中真的不常见,但是一旦去刷招聘信息,就会发现别家公司面试时都会考算法,甚至自己公司都会考,但是,既然在工作中不常见,那么为什么要对算法有这么深的执念呢?展现一个技术人员对于

TROUBLE I AM IN 741

如何跳出深层递归调用(不使用异常)

如何跳出深层递归调用 背景 我在刷leetcode时,遇到了一道简单的罗马数字转整数的问题,想到之前遇到的正则匹配规则问题的递归解法,我自然而然想到了用递归来解决问题,代码并不复杂,主要是if-else结合switch-case判断,但是在最后想要返回结果的时候遇到了麻烦。 罗马数字转整数问题 给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。具体规则在这里就不赘述了。 错...

weixin_44388094的博客 5046

算法-数据结构入门(三)——《算法图解》

今天简单聊聊递归,递归还是比较难理解的,虽然它很好用。在《算法图解》的帮助下,我也是简单的理解了一下,下面把书上大佬的想法及我自己的收获整理一下。 先介绍一种新的数据结构:栈 栈 是一种简单的数据结构,可以看成是一个桶,从顶部插入数据,也从顶部弹出数据,且只有这两种操作 递归,就是自己调用自己,可以理解为一个函数内部调用了自己本身,下面举一个简单的例子: 求10以内的阶乘,代码如下: ...

churijituan的博客 349

递归的深层次理解+初始搜索算法

并排序来说,我们写一个函数实现归并排序,这个函数的目的就是为了实现归并排序,也就是让数组的某一段区间有序,整体思路就是先划分数组的中间元素,从左端点到中间元素排序的,从中间元素到右端点排序的,左区间有序,有区间有序,那么在整体合并两个有序数组即可,终止条件就是数组没有元素或者只有一个元素;5.1)先找到相同的子问题,函数头的参数的传递和某一个子问题是一模一样的,归并排序的子问题就是给定数组的一段区间,把数组进行排一下序就可以了,二叉树的后续遍历是,跟定根节点进行后续遍历,正好适合函数头的功能是一模一样的;

weixin_61518137的博客 706

算法图解之递归(一)(JAVA版本)

一步一步学习算法图解里面的算法

m0_53318344的博客 969

汉诺塔递归算法的图解(自我总结)

汉诺塔算法的图解汉诺塔介绍递归的移动思路代码实现汉诺塔递归图解: 汉诺塔介绍 汉诺塔简单介绍: 有三根相邻的柱子,假定从左到右为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方。 递归的移动思路 将圆盘的移动分解看作三步: 第一步: 将最下面最大圆盘的上面所有圆盘视作n-1个圆盘,需要从借助C柱移动到B柱上 第二步: 将最大的圆盘移动到C柱上 第三步: 将n-1个圆盘借助A柱移动到C柱上 代码实现 co

qq_19697519的博客 4074

深度递归和广度递归

递归 递归算法在日常工作中算是用的比较多的一种,比如DOM树的遍历,多层级树状结构的生成,遍历寻找某个树节点等 1 先来看下数据结构 var result = { id:0, name:"张飞", item:[ {id:1,name:"关羽"}, {id:2,name:"刘备...

weixin_34342578的博客 1312

Android malloc_debug实现原理及使用

2)设置 __libc_globals 对象中的 libc_globals.default_dispatch_table 和 current_dispatch_table 指向 malloc_dispatch_table,以后在 malloc 库函数里都会通过 GetDispatchTable(),这个函数就是返回的 current_dispatch_table 指针;MAX_FRAMES 表示被抓取的 frames 的数量,如果设为0, 表示在分配空间被释放时,不会抓取任何调用栈。

专注于系统快稳省领域 3743

深度理解递归+递归经典问题实战

内涵 定义 在数学与计算机科学中,**递归(Recursion)是指在函数的定义中使用函数自身的方法。**实际上,递归,顾名思义,其包含了两个意思:递和归,这正是递归思想的精华所在 递归思想的内涵 递归就是有去(递去)有回(归来) **“有去”**是指:递归问题必须可以分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决,就像上面例子中的钥匙可以打开后面所...

weixin_34121304的博客 495

C++和蓝图1:Unreal Engine 中 C++ 与蓝图的桥梁

摘要: 本文介绍了Unreal Engine(UE)中C++与蓝图可视化脚本的结合机制,重点解析了宏系统(UCLASS、UPROPERTY、UFUNCTION)如何实现代码与蓝图的交互。相比Unity的纯C#脚本模式,UE的双轨制开发允许程序员用C++处理核心逻辑,同时通过蓝图让非程序员快速迭代。文章对比了两大引擎的编程范式差异,指出UE的反射系统和宏标记提供了更精细的控制,并给出了从Unity迁移到UE的具体思路。核心在于理解UE的混合编程优势:C++保证性能,蓝图提升开发效率,二者通过宏系统无缝协作。

qq_46348216的博客 1407

OpenHarmony系统参数权限配置避坑指南:从param get/set失败到SELinux标签实战

本文深入解析OpenHarmony系统参数权限配置的常见问题与解决方案,涵盖DAC和SELinux双重权限控制机制。通过实战案例演示如何配置`param get/set`权限,解决'Permission denied'错误,并提供三方应用访问参数的安全方案,帮助开发者高效完成系统调试与优化。

weixin_27013291的博客 449

递归深度实战

递归与回溯 1. 递归在程序设计中也常用于需要回溯算法的场合 2. 回溯算法的基本思想:(穷举搜索算法) 1> 从问题的某一种状态出发,搜索可以到达的所有状态 2> 当某个状态到达后,可向前回退,并继续搜索其它可达状态 3> 当所有状态都达到后,回溯算法结束 3. 程序设计中可利用函数活动对象保存回溯算法的状态数据,因此可以利用递归完成回溯算法 4. 回溯算法是递归应用的重要场合,同时利用函数调用的活动对象可以保存回溯算法中重要的变量信息,递归是回溯

coding__madman的博客 4886

高德地图JSAPI中旋转Marker点标签图片时候,且不旋转lable内容方法。

高德地图JSAPI中旋转Marker点标签图片时候,且不旋转lable内容方法

weixin_42960380的博客 2500

【学习】《算法图解》第三章学习笔记:递归的奥秘

《算法图解》第三章笔记探讨了递归的核心概念与应用。递归是将问题分解为更小的相同子问题,通过函数自我调用实现,包含基线条件(终止条件)和递归条件(自我调用)两个关键要素。调用栈机制管理递归过程中的函数调用,表现为后进先出的栈结构。递归的优势在于代码简洁、表达力强,但存在性能开销和栈溢出风险。与循环相比,递归更易理解而循环性能更优。阶乘计算作为经典示例展示了递归的实现方式。选择递归还是循环需权衡代码可读性与执行效率。

一个普通程序员的成长记录簿 992

OpenV2X 车路协同开源平台 Columbia 版本正式发布!

OpenV2X车路协同开源平台Columbia 版本正式发布!

weixin_65571684的博客 1198

字节跳动程序媛教你如何刷算法题:面试手撕代码我就没怕过

本人上一次刷题还是大一的C语言期末考试……但是面试中算法考核截止上岸前一直保持着100%正确率的光辉记录。 本文将给你指明一条刷题的决胜指南。并从算法的重要性、题库的选择以及刷题的三大步骤分别进行讲解,彻底解决你所有关于面试算法所有的困扰。

Stay Hungry Stay Foolish 求知若饥 虚心若愚 2万+

【学习】《算法图解》学习笔记总览

算法的效率通常用大O表示法来衡量。算法时间复杂度空间复杂度适用场景二分查找O(log n)O(1)有序数组中查找元素选择排序O(n²)O(1)小型数据集排序快速排序平均O(n log n),最坏O(n²)O(log n)通用排序场景广度优先搜索O(V+E)O(V)最短路径问题,V为顶点数,E为边数迪杰斯特拉算法O(V)带权图的最短路径贪心算法视具体问题而定视具体问题而定局部最优可导致全局最优的问题动态规划视具体问题而定视具体问题而定。

一个普通程序员的成长记录簿 1341

实战分享:如何利用svchost进程绕过360防护(附完整Shellcode注入教程)

本文深入解析系统进程安全防护机制,探讨svchost等关键进程的安全特性与防护策略。详细分析安全软件的行为检测和内存保护技术,提供系统加固与监控实践建议,助力企业构建多层次防御体系,有效应对潜在安全威胁。

weixin_30752699的博客 99

对于递归的理解

目录0.写在前面1.简单理解递归2.递归需要满足的三个条件3.如何用递归算法解决问题3.1 关注点3.2 例子4.使用递归的优缺点4.1优点4.2缺点4.3还有值得注意的地方5.参考资料 0.写在前面 说明一下,本篇博客偏向于理论,一些例子例题看参考博客就好了。 1.简单理解递归 首先抛开你脑中对递归的想法,单纯先来看看这一个问题。 汉诺塔问题 汉诺塔问题描述的是:有三根柱子,在第一根柱子自下而上的按大小顺序添加圆盘,要求依次取出圆盘添加到另一根柱子上,但是要保持原有的结构,就是自下而上从大到小叠加,而且

qingyuan 589

手把手教你用GNU Radio和PlutoSDR搭建FM收音机(附完整流程图)

本文提供了一份详细的实践指南,教你如何使用GNU Radio和PlutoSDR搭建一个功能完整的FM收音机。从软硬件环境准备、核心流程图构建,到运行调试与效果优化,手把手带你完成从射频信号接收、下变频、FM解调到音频输出的全过程,是入门软件定义无线电(SDR)的绝佳实践项目。

weixin_29189377的博客 750

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【读书笔记】《算法图解》第三章 递归

第三章 递归 1. 伪代码: 是对手头问题的简要描述,看着像代码,但其实更接近自然语言 2. 递归 例如:有一个盒子,这个盒子里有盒子,而盒子里的盒子又有盒子。钥匙在某个盒子中。为找到钥匙,你将使用什么算法? While 创建一个要查找的盒子堆 从盒子堆去除一个盒子,在里面找。 如果找到的是盒子,就将其加入盒子对中,一边以后再查找。 如果找到钥匙,则大功告成 回到第二步。 递归...

HarrietHai的博客 247

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【图解算法学习笔记】

只是对自己学习感觉重点的部分进行记录以及整理。递归只是让解决方案更加清晰,并没有性能上的优势。实际上某些情况下,使用循环的性能能更好。只是递归更加容易理解。

qq_24322029的博客 261

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

《算法图解》第三章笔记

第三章讲的是递归和栈。 书中对学习递归的人分为三个阵营:恨它的,爱它的,狠了几年后又爱上它的。 我认为我是第三种,恨是因为无法理解,爱上是因为它的优雅。 以前写递归主要问题都是递归出口条件不知道怎么写,什么时候调用自身。学习完这章后也只是大概了解了,具体应用还需要去leetcode磨练。 假设你在祖母的阁楼中翻箱倒柜发现了了一个上锁的神秘手提箱。 非递归式找钥匙 除了这个“创建盒子堆”的操...

海旋风的博客 233

图解算法—分而治之

文章目录分而治之图解示例1图解示例2 分而治之 在计算机科学中,分治法是建基于多项分支递归的一种很重要的算法范式。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。 下面将通过两个示例来理解分治法: 图解示例1 假设你是一位农场主,有一小块(1680m * 640m)土地,你要将这块地均匀地分成方块,...

u013010473的博客 1147

Java实现递归与回溯算法详解及图解

递归(Recursion)和回溯(Backtracking)是算法设计中的两个重要概念。递归通过函数调用自身来解决问题,而回溯是一种通过试探性的解决问题的方法,适用于组合问题和路径问题。本文将详细讲解递归与回溯的基本原理,并结合图解和实例代码,帮助您全面理解这些高级算法。递归是一种通过函数调用自身来解决问题的方法。一个递归函数通常包含两个部分:优点:缺点:阶乘是一个非常经典的递归问题。阶乘表示一个正整数的所有整数乘积,记作 (n!)。例如,5的阶乘记作 (5! = 54 3* 2 * 1 = 120)。以下

捕风捉你 · 星桥API接入与大模型实战 2509

二叉树先序遍历递归算法(图解)

前言 二叉树的遍历 是树结构插入、删除、修改、查找和排序运算的前提, 是二叉树一切运算的基础和核心。 二叉树的遍历分为先序、中序、后序遍历, 通过递归实现时, 三者的区别不大, 连代码都不需要修改, 只需要改动打印行 (cout<data) 的位置即可。 想必由许多人会对先序遍历的递归算法感到不解, 往深层说就是对递归的不理解。 在这里博主分享二叉树先序遍历的递归算法的图解 若有错误还请各...

雨化于画 9182
上一篇: try-except语句的应用(超详细的学习笔记)
下一篇: 第1章 程序设计基本方法 (单元测试题Python含答案)
不吃辣的IT男
博客等级 码龄7年 6560粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃辣的IT男

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值