当一个函数解决一个任务时,在解决的过程中它可以调用很多其它函数。在部分情况下,函数会调用 自身。这就是所谓的 递归。
两者都是存放临时数据的地方。
栈:先进后出,就像一个桶,后进去的先出来(它下面的东西要等前面出来之后才能出来)。
堆:是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。对于堆,我们可以随心所欲的进行增加变量和删除变量,不用遵循次序。
栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
堆区(heap) 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
堆(数据结构):堆可以被看成是一棵树,如:堆排序;
栈(数据结构):一种先进后出的数据结构。
我们在调用递归函数时,每一次的递归调用都会进入栈,最上层的函数调用只能访问自己的变量,不能访问其它调用变量。每一次的调用都会占据一定的内存来存储变量,如果递归没有终止的话,就会把内存占满,从而死机。因此,递归必须有一个终止条件。
写递归,遵循这三要素来写,写出正确的递归函数
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
- function calcNum(n) {
- let sum = 0
- function dfs(n) {
- if (n > 5) {
- return
- }
- sum += n
- n++
- console.log(n, '递归前的n')
- dfs(n)
- console.log(n, '递归后的n')
- }
- dfs(n)
- return sum
- }
-
- //递归前打印12345,入栈的过程,1在栈底,5在栈顶
- //递归后打印54321,出栈过程,5在顶,1在底