Javascript中递归的使用方法

简介: Javascript中递归的使用方法

个人理解:递归就是自己调用自己。递归需要一个条件,如果条件不满足他会继续执行,条件满足,递归返回

ps:回头使用调试工具,看看递归是怎么一步一步执行的。

1. 剖析利用递归算法,求斐波那契数列


1、1、2、3、5、8、13、21...
//第n个月有几对兔子,可以让前两个月的兔子数相加

image.png

2. 利用递归实现深拷贝


function clone(target) {
   if (typeof target === 'object') {            //如果target是复杂类型的话,
       let cloneTarget = Array.isArray(target) ? [] : {}; 
       //再次判断,是数组还是对象,并用cloneTarget保存
       for (const key in target) { 
       //遍历传进来的数据 cloneTarget[key] 是数组或对象的属性名 = 
           cloneTarget[key] = clone(target[key]);
       }
       return cloneTarget;
   } else {
       return target;
   }
};

image.png

3. 利用递归将数组转成树结构


 流程如下:

1.首先传入两个参数,一个是数组,一个是要查询的pid

2.进入函数,首先遍历数组,进行判断,看看这个要查询的pid

  和数组中的parentId一样不,如果一样,说明他有上级

3.使用递归,将这个要查询的pid的id当做刚开始的要查询的pid

  查询,再进入递归,查询他们有没有下属,有的话加入到

  直到没有下属为止,

const arr = [
    {id:1, parentId: null, name: 'a'},
    {id:2, parentId: null, name: 'b'},
    {id:3, parentId: 1, name: 'c'},
    {id:4, parentId: 2, name: 'd'},
    {id:5, parentId: 1, name: 'e'},
    {id:6, parentId: 3, name: 'f'},
    {id:7, parentId: 4, name: 'g'},
    {id:8, parentId: 7, name: 'h'},
]
//需要插入父节点id,pid为null或'',就是找root节点,然后root节点再去找自己的子节点
//代码提取版:
function array2Tree(data, pid){
    let res = [];
    data.forEach(item => {
        if(item.parentId === pid){
            let itemChildren = array2Tree(data,item.id);
            if(itemChildren.length) item.children = itemChildren;
            res.push(item);
        }
    });
    return res;
}
const arr = [
    {id:1, parentId: null, name: 'a'},
    {id:2, parentId: null, name: 'b'},
    {id:3, parentId: 1, name: 'c'},
    {id:4, parentId: 2, name: 'd'},
    {id:5, parentId: 1, name: 'e'},   思考过程版:
    {id:6, parentId: 3, name: 'f'},   1.首先传入两个参数,一个是数组,一个是要查询的pid
    {id:7, parentId: 4, name: 'g'},   2.进入函数,首先遍历数组,进行判断,看看这个要查询的pid
    {id:8, parentId: 7, name: 'h'},     和数组中的parentId一样不,如果一样,说明他有上级
]                                     3.使用递归,将这个要查询的pid的id当做刚开始的要查询的pid
                                        查询,再进入递归,查询他们有没有下属,有的话加入到
                                        直到没有下属为止,
//需要插入父节点id,pid为null或'',就是找root节点,然后root节点再去找自己的子节点
//先找他们有没有上级,根据parentID,接着找他们自己有没有下级
//总体流程是:先传一个pid,找pid等于pid的,找到了。再调函数,以这个pid当id,看看arr里面谁的pid等于id的
function array2Tree(data, pid){
    let res = [];
    data.forEach(item => { //遍历原数据,item代表每一个对象
        if(item.parentId === pid){ // 如果传过来的pid,有上级。下面是递归,一直往上找上级
            let itemChildren = array2Tree(data,item.id);//这句话是上级的id,定义变量接收
            if(itemChildren.length) item.children = itemChildren;//如果
            res.push(item);
        }
    });
    return res
}
let oop = array2Tree(arr,1)
console.log(oop)

4. 利用递归将数组转成树结构 (2)


 利用递归将数组转成树结构 *有问题
optionData(data) {
    console.log('开始转换为树形数据');
    let cloneData = JSON.parse(JSON.stringify(data)); // 对源数据深度克隆
    return cloneData.filter(father => { // 循环所有项,并添加children属性
        let branchArr = cloneData.filter(child => father.value == child.parentId); // 返回每一项的子级数组
        branchArr.length > 0 ? father.children = branchArr : ''; //给父级添加一个children属性,并赋值
        return father.parentId == 0; //返回第一层
    });
}, //将查询到的list转为树形
let treedata = this.optionData(data);

5 利用递归求数组之和


总体思路分为两步:

第一步,写出口条件:这里的重点是利用数组的长度作为递归出口。长度为1 的时候递归出去

第二步,写递归条件:首先,递归是自己调用自己,必须得出去,不然死循环。那么,怎么让数组的长度变短呢?需要给一个条件,比如刚开始数组长度是5,那么他应该是第二次比第一次短,是4,然后3、2、1。最后等于1的时候递归就可以出去了。可以使用slice()方法,他的作用是返回一个新数组,里面两个参数,第一个是必须得从哪里开始,第二个是可选哪里结束,这里只需要利用第一个,从1开始,这样每次返回的新数组都会少一个,直至剩下一个,递归结束。

var arr = [1,5,2]
    function f(arr){ 
        var len = arr.length  //定义数组的长度
        if(len === 0){     //递归出口1                
            return 0
        }else if(len === 1){    //递归出口1          
            return arr[0]            
        }else{   
            return arr[0] + f(arr.slice(1))  
            //slice可以返回一个新数组,这个数组从下标第一个开始执行               
        }                                         
        return a         
    }
    var d = f(arr)
    console.log(d);

6.利用递归解决汉罗塔问题


如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数

image.png

思路:

将A柱子上的n-1个盘子暂时移到B柱子上

A柱子只剩下最大的盘子,把它移到目标柱子C上

最后再将B柱子上的n-1个盘子移到目标柱子C上

人话:

       把A上n-1个盘子通过借助辅助塔(C塔)移到了B上

       把最大的一个盘子由A移到C上去

       把B上n-1个盘子通过借助辅助塔(A塔)移到了C上

var index = 0;
function hanoi(num,A,B,C){
  index++;
  if(num==1){
    //柱子只底下只有一个盘子
    move(A,C)
  }else{
    //A的num-1个盘子通过C移动到B
    hanoi(num-1,A,C,B);
    //A的最底下的盘子移动到C
    move(A,C)
    //B的盘子通过A移动到C
    hanoi(num-1,B,A,C)
  }
}
function move(first,final){
  console.log('从',first,' 移动到 ',final);
}
hanoi(4,'第一根柱子','第二根柱子','第三根柱子');
console.log('一共移动了',index,'次');


相关文章
|
3月前
|
JSON JavaScript 前端开发
js树形菜单 如何用递归制作一个简单的树形菜单
js树形菜单 如何用递归制作一个简单的树形菜单
38 0
|
4月前
|
JSON JavaScript 数据格式
js递归树形菜单
js递归树形菜单
|
7月前
|
JSON JavaScript 数据格式
js递归树形菜单
js递归树形菜单
|
3天前
|
JavaScript
node.js递归拼凑成树形结构
node.js递归拼凑成树形结构
9 0
|
1月前
|
JavaScript 前端开发
JavaScript递归的理解(最详细)
JavaScript递归的理解(最详细)
|
3月前
|
Rust 前端开发 JavaScript
【面试题】JavaScript中递归的理解
【面试题】JavaScript中递归的理解
|
8月前
|
JavaScript 前端开发
js正则表达式的作用及使用方法
js正则表达式的作用及使用方法
74 1
|
4月前
|
JavaScript 前端开发 数据处理
【JavaScript 数据处理-番外篇】手写了几个数据处理,都是用的递归
【JavaScript 数据处理-番外篇】手写了几个数据处理,都是用的递归
|
4月前
|
JavaScript 前端开发
【JavaScript 递归】判断两个对象的键值是否完全一致,支持深层次查询,教你玩转JavaScript脚本语言
【JavaScript 递归】判断两个对象的键值是否完全一致,支持深层次查询,教你玩转JavaScript脚本语言
|
4月前
|
JSON JavaScript 数据格式
JS递归树形菜单
JS递归树形菜单
17 1