js递归算法

js递归算法


递归作为算法的基础之一,如果需要学习算法,递归是避不开的, 今天就带大家理解递归的原理以及作用。

提示:以下是本篇文章正文内容,下面案例可供参考

一、递归是什么?

递归的核心在于‘递’和‘归’。
简单来讲就是在函数内部调用本函数,并将处理过的参数传递给自己处理,再通过自己返回的参数来执行,完成函数的需求。
ps:使用递归可以压缩代码量以及增加代码的可读性

二、步骤

1.递归的目的

说到递归,最经典的就是斐波那契数列(Fibonacci sequence):
斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……

从中可以提取出这个数列的规则:当前位数的数字等于前两位的和。

我们现在的需求是想通过传一个坐标就能获取当前坐标位的值,
效果为:

function rabbit(num){
        //各种方法
    }
    rabbit(6);//返回8

那么需要包装出这种效果的函数,就需要先看这个数列的规则,也就是“当前位数的数字等于前两位的和”;

思路:

既然这个数列的当前位等于前两位的和,那么计算当前位的值必定需要知道前两位的值,前两位的值则由更前面的数字来决定,
也就是说不管传入的位数是多少,除非是1或者2,否则我们都需要算到数列的开始,也就是第一位的“1”和第二位的“1”,由此来一步步计算到当前位

加一点细节以后,现在代码如下:

function rabbit(num){ //num:参数   代表需要获取数字的位数
        if(num<3)return 1  //如果位数小于3,则代表是第一位或者第二位,返回1
        return rabbit(num-1)+rabbit(num-2) //当前位数的数字等于前两位的和
    }

首先我们需要明白这个函数的目的:“传一个坐标就能获取当前坐标位的值”。
也就是说首先需要使第一位和第二位都为1,这已经通过第一行实现,接下来就到了最关键的时候,怎么计算后面的位数?
刚刚我们分析出计算这个数列的思路后得到一个线索“需要算到数列的开始”,由于此数列的特性,获取后面位数的数值需要知道此位数之前所有的值,那么也就是说需要从头算起,我们可以先用一个简单的方法来实现

function rabbit(num){
        if(num<3)return 1    
        let newArr = [1,1];
        for(let i=2; i<num; i++){
        	//效果为当前位的值 = 前两位的值相加
            newArr[i] = newArr[i-1]+newArr[i-2]
        }
        console.log(newArr);//更清晰的看到过程
        return newArr[num-1]
    }

第一行不变,在已知位数1,2都为1时,我们可以创建一个数组(有下标,方便操作),第一位和第二位都为1。
然后开始通过之前的思路写出for循环,最后返回需求的值。
这个方法的思路是:从开始算到结束(第num位)

而递归算法则更加简洁,且逻辑清晰

2.递归示意图

如下:
ps:线指向接下来要执行的函数
示意图

想搞懂递归首先要明白递归函数是怎么进行运算的,如图所示:
首先假设我们给函数传入一个6,本函数的目的是计算出当前传入位数的值,那么rabbit(6)就代表着数列第六位的值,

接着进行if判断,判断为false,然后本函数返回值为rabbit(5)+rabbit(4):第五位的值+第四位的值。

此时rabbit(6)因为返回的函数未执行,所以并未停止

然后计算机就理所当然的开始计算rabbit(5)和rabbit(4),不断重复上面的步骤,此时每个rabbit函数都在等待其他rabbit返回一个值让它计算(图中所有的rabbit(3,4,5,6)),能够不依靠其他rabbit()函数就可以返回值的只有rabbit(1)和(2)
这就是所谓的“出口”。

每个rabbit函数都将提供自己处理过的参数“递”给另一个自己,直到函数碰到出口,将返回值“归”回来,

最底层的函数结束后,函数将会一层层的结束自己的运算,并将结果“归”还(返回),从而得到需要的结果(返回值)。

这就是递归

	function rabbit(num){
	    if(num<3)return 1
	    return rabbit(num-1)+rabbit(num-2)
	}

现在来看这个函数,是不是清晰了许多呢,如果想学会怎么写递归,那就要先掌握for循环实现正向算法,然后通过逆向思维来倒推出递归算法即可。


总结

递归需要知道正确的逻辑,需要一个出口,需要将处理过的参数传递给自己,
正确使用递归将会很大程度压缩代码,以及增加函数的可读性


版权声明:本文为lonelyiiblack原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。