博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简单易懂的现代魔法-递归
阅读量:6834 次
发布时间:2019-06-26

本文共 1630 字,大约阅读时间需要 5 分钟。

平时在前端开发中,好像也没啥用到递归的地方。不过这并不代表递归不重要,如果你看过一些框架的源码,就会经常见到它的影子:比如渲染虚拟DOM的render函数,webpack中require依赖分析,Koa2洋葱式的中间件模型,其实都运用到了递归算法。

递归概念

那么递归到底是啥?先上两张图:

图1:

图2:

递归,就是在运行的过程中调用自己

我们来看个最简单的阶乘函数:

5! = 5 * 4 * 3 * 2 * 1
function factorial(num) {    if (num === 1) { // 基线条件        return 1;    }    // 递归条件    return num * factorial(num-1);}factorial(5);

一个常规的递归函数都有两部分:

  1. 基线条件(if (num === 1)):保证函数不再调用自己,避免无限循环
  2. 递归条件(num * factorial(num-1)):保证函数能够调用自己

调用栈

栈是一种先进后出的数据结构,它只有两种操作,出栈和入栈

const nekopara = ['chocolat', 'Coconut'];nekopara.push('vanilla'); // 入栈nekopara.pop(); // 出栈

代码在运行过程中,会有一个叫做调用栈(call stack)的概念。

function greet(name) {    console.log(`hello, ${name}!`)    greet2(name);    console.log(`getting ready to say bye`);    bye();}function greet2(name) {    console.log(`how are you, ${name}?`);}function bye() {    console.log(`bye`);}greet('deepred');

调用greet('deepred')时,计算机会首先给该函数分配一块内存,并将变量名name设置为deepred

greet

每当调用函数时,都会分配一个内存块并将涉及到的变量值存储到内存中。

打印hello, deepred后,调用了greet2('deepred')。同样,计算机再次分配了一块内存,并且该内存块位于第一个内存块上面。

greet

调用栈的最上面表示当前运行的函数,如图所示,现在正在运行的是greet2函数,打印输出how are you, deepred?后,函数greet2执行完毕,栈顶的内存块被弹出。

现在栈顶的内存块又变回greet,这意味着我们从greet2的函数中跳出,再次返回到了greet。

我们在greet中调用了greet2时,greet只执行了一部分。

特别注意:调用另外一个函数时,当前函数暂停并且处于未完成状态,暂停函数的所有变量的值仍然在内存中

执行完greet2后,我们回到了greet,并从离开的地方开始接着往下执行:首先打印getting ready to say bye,然后调用bye函数。

在栈顶添加了bye函数的内存块后,开始执行bye函数,打印bye,然后函数返回,内存块被弹出。

我们又再次回到了greet中,这次没有其他要运行的代码了,于是从greet函数中返回,内存块被弹出,调用栈最后为空。

完整的一次调用流程

greet

递归调用栈

递归同样使用调用栈

我们来分析下阶乘fact(3)的调用栈

function fact(num) {   if (num === 1) {        return 1;   }   return num * fact(num-1);}fact(3);

直接看图:

greet

递归注意事项

递归会导致程序的性能变低

如果递归嵌套很深,那么调用栈会很长,这将占用大量内存,可能会导致栈溢出

转载地址:http://tcxkl.baihongyu.com/

你可能感兴趣的文章
浅谈算法学习
查看>>
前端知识点——图片
查看>>
thinkphp源码分析(三)—自动加载篇(Loader的分析)
查看>>
Blink 真香
查看>>
一块听听:Mixin 主网上线语音直播文字稿
查看>>
brew安装错误brew Error: /usr/local must be writable!
查看>>
可应用于实际的14个NLP突破性研究成果(三)
查看>>
[LeetCode] 41. First Missing Positive
查看>>
阿里如何将“高峰前扩容、高峰后缩容”的梦想照进现实?
查看>>
分布式系统关注点——初识「高可用」
查看>>
Node.js学习之路22——利用cheerio制作简单的网页爬虫
查看>>
聊一聊我对 React Context 的理解以及应用
查看>>
很多程序员都不会的问题,你知道多少?
查看>>
Scrapy-redis分布式组件
查看>>
package.json里的一些属性讲解
查看>>
leetcode 12 Integer to Roman
查看>>
Swoole+Lumen:同步编程风格调用MySQL异步查询
查看>>
探索 JUC 之美---Future 与 FutureTask
查看>>
《Java RESTful Web Service实战》第一章的实现补漏
查看>>
smarty 中的for循环
查看>>