JavaScript 递归算法


前言

第一次认识递归这个概念在两年前, 一个递归函数(不是深拷贝)看了好久才看懂, 在函数内部再次调用自己, 返回一个新的值, 再此期间还涉及多次对自己的调用, 这对于当时的我还是太过超前了.

不过直到最近, 我对’递归’的认知也几乎只是这些, 我还是希望能有更深刻的理解.


一、何为’递归’

递归并不像我理解的那样只是’自己调自己’这种, 正相反, '对自身的调用’这一行为包含在递归的范畴内.
在第三版《学习JavaScript数据结构与算法》里对递归的定义是:

递归是一种解决问题的办法, 它从解决问题的各个小部分开始, 直到解决最初的大问题. 递归通常涉及函数调用自身.

但是对于递归函数, 就是特指能够直接或者间接调用自身的函数了.
比如:

function recursiveFunction1 (someParam) {
   
  recursiveFunction2(someParam);
}

但是很明显不能在开发中使用上面这个函数——它会一直执行下去, 无休无止.
因此一个完整的递归函数应当具备基线条件, 即一个不再递归调用的条件, 就像while那样.

如果换成这样的话:

function understandRecursion (doIunderstandRecursion) {
   
  const recursionAnswer = confirm('understand');
  if (recursionAnswer === true) return; // 基线条件
  understandRecursion();
}

是一个合格的JavaScript递归函数了.


二、调用栈

每当一个函数被一个算法调用, 该函数会进入调用栈的顶部, 而递归函数对自身的调用也将导致更多的自己被压入调用栈, 因为每一次调用都可能依赖上一次调用的结果.

1.观察调用栈运作

调用栈的情况可以通过浏览器探查, 用一个递归阶乘函数作为例子:

function factorial (n) {
   
  if (n === 1 || n === 0) {
    // 基线条件
	return 1;
  }
  return n * factorial(n - 1);
}
console.log(factorial(5));

在基线打断点, 暂停执行, 然后刷新页面, 让调用栈回到初始状态:

在这里插入图片描述

factorial(3)调用.

在这里插入图片描述

factorial(3): 等待factorial(2)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值