理解递归
*有一句编程的至理名言是这样的:“要理解递归,首先要理解递归。”*,虽然话是这么说,但是想要理解递归先要理解栈结构想要,只有了解栈结构的特性,才能够做到理解递归
栈结构以及js执行栈
栈是一种数据结构,它的特性是先入后出,或者后入先出,他是一种存储数据的结构。
栈结构具体可以看这篇文章.
上下文(域)以及执行栈可以这篇文章.
递归的表现形式
递归是一种解决问题的方法,它从解决问题的各个小部分开始,直到解决最初的大问题。递归通常涉及函数调用自身。简单来说就是函数自己调用自己
function recursiveFunction(someParam){
recursiveFunction(someParam);
}
能够像下面这样间接调用自身的函数,也是递归函数
function recursiveFunction1(someParam){
recursiveFunction2(someParam);
}
function recursiveFunction2(someParam){
recursiveFunction1(someParam);
}
上面的递归没有设置停止基线因此会栈溢出,因此需要设置一个递归停止的条件
function understandRecursion(doIunderstandRecursion) {
const recursionAnswer = confirm('Do you understand recursion? ');
if (recursionAnswer === true) { // 基线条件或停止点
return true;
}
understandRecursion(recursionAnswer); // 递归调用
}
理解递归
通过阶乘来了解递归
function factorial(n) {
if (n === 1 || n === 0) { // 基线条件
return 1;
}
return n * factorial(n -1); // 递归调用
}
console.log(factorial(5)); // 120
- 递
当进行“递” 的时候 也就是开始执行这个阶乘的时候 factorial 函数入栈此时这个栈应该是如下,相当于执行push 方法
// 假设这是一个栈
let stack = []
stack = [factorial(5)]
stack = [factorial(5),factorial(4)]
stack = [factorial(5),factorial(4),factorial(3)]
stack = [factorial(5),factorial(4),factorial(3),factorial(2)]
stack = [factorial(5),factorial(4),factorial(3),factorial(2),factorial(1)]
- 归
当达到基线后,开始出栈 相当于 执行 pop 方法 从数组尾部开始出栈 以此类推直到全部出栈,将值全部返回。 此时是“归” 的一个过程
stack = [factorial(5),factorial(4),factorial(3),factorial(2),factorial(1)]
stack = [factorial(5),factorial(4),factorial(3),factorial(2)]
stack = [factorial(5),factorial(4),factorial(3)]
stack = [factorial(5),factorial(4)]
stack = [factorial(5)]
stack = []
递归的用处
递归主要用于处理树结构,处理树结构主要有两种方式分别是广度优先以及深度优先,两种算法,可以查看一下这篇文章(个人水平有限)
递归常用算法.