精华内容
下载资源
问答
  • JS递归的用法JavaScript递归

    万次阅读 多人点赞 2018-09-16 20:18:10
    递归: 函数中用调用函数自己,此时就是递归递归一定要有结束条件 function f1() { console.log("从前有座山,山里有个庙,庙里有个老和尚给小和尚讲故事:"); }; f1();//浏览器崩溃,因为没有...

    递归:

    函数中用调用函数自己,此时就是递归,递归一定要有结束条件

        function f1() {
            console.log("从前有座山,山里有个庙,庙里有个老和尚给小和尚讲故事:");
            f1();
        };
        f1();//浏览器崩溃,因为没有结束条件——死循环
    
    	改进如下:
    	    var i=0;
        function f1() {
            i++;
            if (i<5){
                f1();
            }
            console.log("从前有座山,山里有个庙,庙里有个老和尚给小和尚讲故事:");
        };
        f1();
    

    小栗子:

    递归实现:求n个数字的和 n=5 ------->5+4+3+2+1

    //for 循环写法:
        var sum=0;
        for (var i=0;i<=5;i++){
            sum+=i;
        }
        console.log(sum);
    ----------------------分割线---------------------------
    
       function getSum(x) {
            if (x==1){
              return 1
            }
            return x+getSum(x-1);
        };
    
        var sum1=getSum(5);
        console.log(sum1);
        console.log(getSum(10));
    

    执行过程:
    代码执行getSum(5)—>进入函数,此时的x是5,执行的是5+getSum(4),此时代码等待
    此时5+getSum(4),代码先不进行计算,先执行getSum(4),进入函数,执行的是4+getSum(3),等待, 先执行的是getSum(3),进入函数,执行3+getSum(2),等待,先执行getSum(2),进入函数,执行 2+getSum(1);等待, 先执行getSum(1),执行的是x==1的判断,return 1,所以,
    此时getSum(1)的结果是1,开始向外走出去
    2+getSum(1) 此时的结果是:2+1
    执行:
    getSum(2)---->2+1
    3+getSum(2) 此时的结果是3+2+1
    4+getSum(3) 此时的结果是4+3+2+1
    5+getSum(4) 此时的结果是5+4+3+2+1

        结果:15
    

    再来几个:

        //递归案例:求一个数字各个位数上的数字的和:  123   --->6 ---1+2+3
        //523
        function getEverySum(x) {
            if(x<10){
                return x;
            }
            //获取的是这个数字的个位数
            return x%10+getEverySum(parseInt(x/10));
        }
        console.log(getEverySum(1364));//5
    
     //递归案例:求斐波那契数列
    
        function getFib(x) {
            if(x==1||x==2){
                return 1
            }
            return getFib(x-1)+getFib(x-2);
        }
        console.log(getFib(12));
    
    展开全文
  • var arrs=[];   function getinfo(items) { for (var item of items){ if (item.children){ arrs.push({ id: item.id, parentid:...

    var arrs=[];

     

    function getinfo(items) {
        for (var item of  items){
            if (item.children){
                    arrs.push({
                            id: item.id,
                            parentid:item.parentId,
                            name:item.title,
                            children:getinfo(item.children)
                        }
                    )
    
            }else {
                   arrs.push({
                           id: item.id,
                           parentid:item.parentId,
                           name:item.title
                       }
                   )
            }
        }
    }

     

    数据结构如下:

     

    {
        id: 13,
        parentId: -1,
        children: [
            {
                id: 5,
                parentId: 13,
                children: [
                    {
                        id: 1,
                        parentId: 5,
                        children: [],
                        icon: "fa-user",
                        title: "用户管理",
                        href: "/admin/user",
                        spread: false,
                        path: "/adminSys/baseManager/userManager",
                        code: "userManager"
                    }
    ]
    
    icon: "setting", title: "基础配置管理", href: "/admin", spread: false, path: "/adminSys/baseManager", code: "baseManager"

    }]

    ,
            icon: "setting",
            title: "权限管理系统",
            href: "/base",
            spread: false,
            path: "/adminSys",
            code: "adminSys"
        }
    

     

     

     

     

     

     

     

    展开全文
  • js递归

    万次阅读 多人点赞 2018-07-06 16:50:10
    js递归调用// 一个简单的阶乘函数 var f = function (x) { if (x === 1) { return 1; } else { return x * f(x - 1); } }; Javascript中函数的巨大灵活性,导致在递归时使用函数名遇到困难,对于上面的...

    js递归调用

    方法一:

    
    // 一个简单的阶乘函数  
    var f = function (x) {  
        if (x === 1) {  
            return 1;  
        } else {  
            return x * f(x - 1);  
        }  
    };  

    Javascript中函数的巨大灵活性,导致在递归时使用函数名遇到困难,对于上面的变量式声明,f是一个变量,所以它的值很容易被替换:

    var fn = f;  
    f = function () {};  

    函数是个值,它被赋给fn,我们期待使用fn(5)可以计算出一个数值,但是由于函数内部依然引用的是变量f,于是它不能正常工作了。

    所以,一旦我们定义了一个递归函数,便须注意不要轻易改变变量的名字。

    上面谈论的都是函数式调用,函数还有其它调用方式,比如当作对象方法调用。

    我们常常这样声明对象:

    var obj1 = {  
        num  5  
        fac  function (x) {  
            // function body  
        }  
    };  

    声明一个匿名函数并把它赋值给对象的属性(fac)。

    如果我们想要在这里写一个递归,就要引用属性本身:

    var obj1 = {  
        num : 5,  
        fac : function (x) {  
            if (x === 1) {  
                return 1;  
            } else {  
                return x * obj1.fac(x - 1);  
            }  
        }  
    }; 

    当然,它也会遭遇和函数调用方式一样的问题:

    var obj2 = {fac: obj1.fac};  
    obj1 = {};  
    obj2.fac(5); // Sadness  

    方法被赋值给obj2的fac属性后,内部依然要引用obj1.fac,于是…失败了。

    换一种方式会有所改进:

    var obj1 = {  
         num : 5,  
         fac : function (x) {  
            if (x === 1) {  
                return 1;  
            } else {  
                return x * this.fac(x - 1);  
            }  
        }  
    };  
    var obj2 = {fac: obj1.fac};  
    obj1 = {};  
    obj2.fac(5); // ok  

    通过this关键字获取函数执行时的context中的属性,这样执行obj2.fac时,函数内部便会引用obj2的fac属性。

    可是函数还可以被任意修改context来调用,那就是万能的call和apply:

    obj3 = {};  
    obj1.fac.call(obj3, 5); // dead again  

    于是递归函数又不能正常工作了。

    我们应该试着解决这种问题,还记得前面提到的一种函数声明的方式吗?

    var a = function b(){};  

    这种声明方式叫做内联函数(inline function),虽然在函数外没有声明变量b,但是在函数内部,是可以使用b()来调用自己的,于是

    var fn = function f(x) {  
        // try if you write "var f = 0;" here  
        if (x === 1) {  
            return 1;  
        } else {  
            return x * f(x - 1);  
        }  
    };  
    var fn2 = fn;  
    fn = null;  
    fn2(5); // OK  
    // here show the difference between "var f = function f() {}" and "function f() {}"  
    var f = function f(x) {  
        if (x === 1) {  
            return 1;  
        } else {  
            return x * f(x - 1);  
        }  
    };  
    var fn2 = f;  
    f = null;  
    fn2(5); // OK  
    var obj1 = {  
        num : 5,  
        fac : function f(x) {  
            if (x === 1) {  
                return 1;  
            } else {  
                return x * f(x - 1);  
            }  
        }  
    };  
    var obj2 = {fac: obj1.fac};  
    obj1 = {};  
    obj2.fac(5); // ok  
    
    var obj3 = {};  
    obj1.fac.call(obj3, 5); // ok  

    就这样,我们有了一个可以在内部使用的名字,而不用担心递归函数被赋值给谁以及以何种方式被调用。

    Javascript函数内部的arguments对象,有一个callee属性,指向的是函数本身。因此也可以使用arguments.callee在内部调用函数:

    function f(x) {  
        if (x === 1) {  
            return 1;  
        } else {  
            return x * arguments.callee(x - 1);  
        }  
    }

    但arguments.callee是一个已经准备被弃用的属性,很可能会在未来的ECMAscript版本中消失,在ECMAscript 5中"use strict"时,不能使用arguments.callee。

    最后一个建议是:如果要声明一个递归函数,请慎用new Function这种方式,Function构造函数创建的函数在每次被调用时,都会重新编译出一个函数,递归调用会引发性能问题——你会发现你的内存很快就被耗光了。

    js递归函数应用

    最近在做项目的时候,用到了递归函数,用来调用json的子节点,把所有json中的子节点中包含某个数的object,都push到一个数组中,然后对其进行绑定。

    我是通过如下递归调用的

    var new_array=[];
         function _getChilds(data){
             if(data.ObjType=="某个数"){
                new_array.push(cs_data);
            }
            if(data.Childs){
              if(data.Childs.length>0){
                  getChilds(data.Childs)
              }
           }
         }
        function getChilds(data){
            for(var i=0;i<data.length;i++){
                _getChilds(data[i]);
            }
        }
    
    使用方法:getChilds"json数据"

    就把json中所有包含某个数的数据push到new_array数组当中了。


    方法二:

    递归函数是在一个函数通过名字调用自身的情况下构成的,如下所示。

    function factorial(num){
      if (num <= 1){
        return 1;
      } else {
      return num * factorial(num-1);
    }
    }
    

    这是一个经典的递归阶乘函数。虽然这个函数表面看来没什么问题,但下面的代码却可能导致它出错。

    var anotherFactorial = factorial;
    factorial = null;
    alert(anotherFactorial(4)); //出错!
    

    以上代码先把 factorial()函数保存在变量 anotherFactorial 中,然后将 factorial 变量设置为 null,结果指向原始函数的引用只剩下一个。但在接下来调用 anotherFactorial()时,由于必须执行 factorial(),而 factorial 已经不再是函数,所以就会导致错误。在这种情况下,使用 arguments.callee 可以解决这个问题。
    我们知道, arguments.callee 是一个指向正在执行的函数的指针,因此可以用它来实现对函数的递归调用,例如:

    function factorial(num){
      if (num <= 1){
        return 1;
       } else {
        return num * arguments.callee(num-1);
      }
    }
    

    使用 arguments.callee 代替函数名,可以确保无论怎样调用函数都不会出问题。因此,在编写递归函数时,使用 arguments.callee 总比使用函数名更保险。但在严格模式下,不能通过脚本访问 arguments.callee,访问这个属性会导致错误。不过,可以使用命名函数表达式来达成相同的结果。例如:

    var factorial = (function f(num){
      if (num <= 1){
        return 1;
      } else {
        return num * f(num-1);
      }
    });
    

    var factorial = (function f(num){
      if (num <= 1){
        return 1;
      } else {
        return num * f(num-1);
      }
    })(3);
    console.log(factorial);

    以上代码创建了一个名为 f()的命名函数表达式,然后将它赋值给变量 factorial。即便把函数赋值给了另一个变量,函数的名字 f 仍然有效,所以递归调用照样能正确完成。这种方式在严格模式和非严格模式下都行得通。

    方法三:

    Question1—Fibonacci数列第N项

    1. var fib = function (n){
    2. if(n<= 2){
    3. return 1;
    4. }
    5. return fib(n -1) + fib(n -2);
    6. }
    7. console.log(fib( 5));
    上面是递归实现。

    1. var fib = function (n){
    2. var a1= 1,a2= 1,a3= 0;
    3. if(n<= 2){
    4. return 1;
    5. }
    6. for( var i = 0;i < n -1;i++){
    7. a3 = a1 + a2;
    8. a1 = a2;
    9. a2 = a3;
    10. }
    11. return a3;
    12. }
    13. console.log(fib( 5));
    上面是循环实现。

    Question2—一共10级楼梯,每次可以走一步或两步,求一共多少种走法。

    思路:

    要想走到N(N=10)级,可以分为2种情况。

    1. 从n-2级迈两步
    2. 从n-1级迈一步

    那么对于n-2和n-1的情况也是各自分为两种,以此类推。

    那么走法的和就是n-2的走法和n-1的走法之和。

    那么递归到最基本的(当前人在第0阶台阶)

    第0阶台阶:0

    第1阶台阶:1

    第2阶台阶:2(1+1或者2)

    得到公式,也就是斐波那契数列。


    1. var fib = function (n){
    2. if(n == 1){
    3. return 1;
    4. } else if(n== 2){
    5. return 2;
    6. } else if(n> 2){
    7. return fib(n -1) + fib(n -2);
    8. }
    9. }
    10. console.log(fib( 10));

    Question3—1个细胞,一个小时分裂一次,生命周期是3小时,求n小时后容器内,有多少细胞。


    思路:

    细胞的生存周期是3个小时,那我们就可以把细胞在题目中状态分为以下几个状态:

    • a:刚分裂态——由前一小时的a,b,c分裂出
    • b:分裂1小时态——由前一小时a长成
    • c:分裂2小时态——由前一小时b长成
    • d:分裂3小时态——死亡的细胞。由前一小时c长成,和之前的d一起组成。

    那么,我们就可以根据细胞状态设定函数。分析每一个状态的来源是哪里即可。


    容器中存活的细胞数目就是a、b、c三种状态数量的总和。

    1. var afib = function (n){
    2. if(n=== 0){ return 1;} //初始的那个细胞
    3. return afib(n -1)+bfib(n -1)+cfib(n -1);
    4. }
    5. var bfib = function(n){
    6. if(n=== 0){ return 0;} //一个小时之后才会生成
    7. return afib(n -1);
    8. }
    9. var cfib = function(n){
    10. if(n=== 0||n=== 1){ return 0;} //前两小时还没生成
    11. return bfib(n -1);
    12. }
    13. var time = 3;
    14. console.log(afib(time)+bfib(time)+cfib(time));


    总结:

    递归的两个必要因素:

         递归方程,递归结束条件。

    算法核心:

    • 在有限次可预见性结果中,找到结果与上一次结果之间的关系。
    • f(n)与f(n-1)的关系有时候很简单,如同走楼梯,状态单一;又有时如同细胞分裂,多种状态组合影响结果。
    • 关键在于梳理清楚本次结果和上一次结果的关系有哪些方面或是因素。
    • 在草稿纸上写出前几次的结果,或者画图,这样更容易找到规律,这种规律实际上就是递归方程。
    • 在算法的分析中,当一个算法中包含递归调用时,其时间复杂度的分析会转化成为一个递归方程的求解



    展开全文
  • JS递归

    2021-02-11 14:27:09
    JS递归一、什么是递归二、递归的作用 一、什么是递归 函数内部调用自己,这个函数就是递归函数。 必须有return或者结束条件,不然会无限调用自己,发送栈溢出,形成死递归。return 可以退出循环,也能退出递归函数。...

    一、什么是递归

    函数内部调用自己,这个函数就是递归函数。
    必须有return或者结束条件,不然会无限调用自己,发送栈溢出,形成死递归。return 可以退出循环,也能退出递归函数。

    二、递归的作用

    1.求阶乘

    //1*2*3*4*。。。n
    function fn(n){
    if(n==1){
     return 1
    }
      reurn n*fn(n-1)
    
    }
    var a = fn(5);
    

    2.求斐波那契数列

    function fb(n){ 
    if(n ==1 || n ==2){
    return 1
    
    }
    
    return fb(n-1)+fb(n-2)
    
    }
    
    展开全文
  • Javascript 递归

    2021-10-09 19:55:24
    1.什么是递归 如果一个函数爱内部可以调用其本身,那么这个函数就是递归函数. (函数内部自己调用 自己) 注: 递归函数的作用和循环效果一样,由于递归很容易发生'栈溢出' 错误(stark overflow) ,所以必须要加退出...
  • javascript递归

    2017-04-05 09:42:00
    javascript递归 function recursion(number){ if(number == 1){ return number; }else{ return number * recursion(number-1); } } console.log(recursion(5)); 运行:5*4*3*2...
  • js 递归

    2017-02-27 11:57:07
    js 递归 思想:递归就是将一个大问题分解成 n 个相似的小问题,然后不断地调用自身去解决这些小问题,从而求出结果。 实践: 汉诺塔 塔的设备包括三根柱子和一套直径各不相同的空心圆盘。开始时源柱子上的所有...
  • JavaScript 递归

    2021-08-28 22:31:53
    递归: 函数运行时,自己调用自己 必须有终止条件,否则就会进入死循环
  • javascript 递归

    2020-07-23 09:57:17
    1.什么是递归递归习题——利用递归求1~n的阶层斐波那契数列 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ...
  • JavaScript递归

    2019-04-03 09:41:54
    递归的定义很简单,就是在函数体内调用本函数。递归对于解决一些算法问题有很大的优势,但是递归必须慎重使用,递归函数如果判断条件无法终止,很容易造成内存溢出,报错stack overflow,使程序崩溃。 递归最经典...
  • JS 递归

    2019-08-12 17:09:00
     然后还发现一个问题,对于集合下面有子集合,子集合下面还有子集合的情况,读取数据应该考虑使用递归,因为层层for循环仅适用于知道层级数的场景,但是这种做法代码量很冗余,没有递归简洁。  以下是demo...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 124,133
精华内容 49,653
关键字:

js递归