10
前端也要懂算法,阅《算法图解》有所得。

一、 递归

递归简而言之就是函数调用自己。比如说我们需要遍历一个文件夹,有2种思路:

  1. 循环
  2. 递归

2种实现方式就不细说,

二、 基线条件和递归条件

假设我们要写一个倒计时:

var a = 5;

cutdown= function(i){
    i-=1
    cutdown(i)

}

cutdown(a);

没错,上面的代码是个死循环。
每个递归都需要有2个条件,一个是基线条件,用于控制递归啥时候暂停,一个是递归条件,控制调用自己的方式。下面我们把倒计时函数改造一下:

cutDown = function (i){
    if(i === 1 ){   //基线条件
        return
    } else {  //递归条件
        i-=1;
        cutDown(i)
    }
    
}

三、 栈

1. 调用栈

调用栈就是我们调用一个函数的时候,计算机会单独分配一个内存块,用于存储函数的参数和变量,而如果我们调用多个函数,那么就会被分配多个内存块,每个内存块被压入栈中,最先调用的被压在最底层,而最后压入的最先执行完被弹出。因此,我们可以得出结论:

  • 栈只有压入和弹出2个操作
  • 栈的元素是先入后出的
  • 每一个函数执行都会被分配一个内存块
  • 同一个上下文的多个函数调用产生的内存块会被压入栈中。

2. 递归调用栈

递归的实现就是依赖栈的特性,比如我们需要算5的阶乘:

var func = function(i){
    if(i === 1){
        return 1;
    }else{
        return i*func(i-1);
    }

}


//执行 func(5)

//入栈
func(5);  //此时 i = 5 被压入栈中

//经过基线条件和递归条件,func(5)暂停,func(4)执行

func(4) '// 此时 i = 4 被压入栈中

...

func(1)

//出栈

func(1)  //执行完毕后,弹出, 返回 1

//上一个func(2)中的 func(i-1) 返回 1 

func(2) //返回 2X1= 2

...


func(5)


Nero
3.2k 声望2.5k 粉丝

前端搬砖者。