递归的概念

  • 在程序中函数直接或间接调用自己
    1. 直接调用自己
    2. 简介调用自己
  • 跳出结构,有了跳出才有结果

递归的思想

  • 递归的调用,最终还是要转换为自己这个函数
    1. 如果有个函数foo,如果他是递归函数,到最后问题还是转换为函数foo的形式
    2. 递归的思想就是将一个未知问题转换为一个已解决的问题来实现

递归的步骤(技巧)

1. 假设递归函数已经写好
2. 寻找递推关系
3. 将递推关系的结构转换为递归体
4. 将临界条件加入到递归体中7你

简单递归练习

求1-100的和

  • 分析:

    1. 假设递归函数已经写好为sum,既sum(100),就是求1-100的和
    2. 寻找递推关系: 就是 n 与 n-1 ,或 n-2 之间的关系
      sum(n) == sum(n-1) + n

      1 var res = sum(100);
      2 var res = sum(99) + 100;
  1. 将递归结构转换成递归体

    1 function sum(n){
    2     return sum(n-1) + n;
    3 }
  2. 将临界条件加入到递归中
    • 求100 转换为 求99
    • 求99 转换为 求98
    • 求98 转换为 求97
    • ...
    • 求2 转换为 求1
    • 求1 转换为 求1
    • 即 sum(1) = 1
    1.   递归函数

      1 function sum(n){
      2     if(n==1) return 1;
      3     return sum(n-1) + n;
      4 }

求出斐波那契数列

  1,1,2,3,5,8,13,21,34,55,89...求第 n 项

  • 分析:

  1. 假设已知 fib(n) 为第 n 项
  2. 递归关系 * fib(n) = fib(n-1) + fib(n-2)
  3. 递归体
1 function fib(n){
2     return fib(n-1)+fib(n-2);
3 }
 4. 临界条件
    fib(0) == 1
    fib(1) == 1
 5. 递归函数
1 function fib(n){
2     if(n == 0 || n ==1) return 1;
3     return fib(n-1) + fib(n-2);
4 }

拷贝,使用递归方式(面试的时候有可能会问到)

(潘明老师:http://risky.love/2016/10/08/JavaScript%E6%B7%B1%E6%8B%B7%E8%B4%9D%E5%AE%9E%E7%8E%B0/)

  • 分析
  1. 什么是拷贝
    1. 如果拷贝的时候, 只针对当前对象的属性进行拷贝, 而属性是引用类型这个不考虑, 那么就是浅拷贝
    2. 如果拷贝的时候, 将数据的所有引用结构都拷贝一份, 那么数据在内存中独立就是深拷贝(内存隔离,完全独立)
    3. 拷贝: 复制一份. 指将对象数据复制.
    4. 在讨论深拷与浅拷的时候一定要保证对象的属性也是引用类型.
  2. 实现方法:
    1. 如果要实现深拷贝那么就需要考虑将对象的属性, 与属性的属性,都拷贝过来
  3. 2个参数,简单实现
    1. 假设已经实现 clone ( o1, o2),将对象 o2 的成员拷贝一份交给 o1
    2. 递推关系
    3. 混合方法,将 o2 的成员拷贝到 o1 中
1  function clone( o1, o2){
2             for(var key in o2){
3                 o1[key] = o2[key];
4             }
5         }

      * 假设方法已经实现,如果 o2[key] 是对象

      * 继续使用这个方法

      * 需要考虑 o2[key] 是引用类型,再一次使用clone函数

      * 如果 o2[key] 不是引用类型,那么直接赋值

      4.临界条件

        * 因为是 for in 循环,没有成员遍历时,自动结束

      5. 递归函数

 1 function clone(o1,o2){
 2     for(var key in o2){
 3         if(typeof o2[key] == 'object'){
 4             o1[key] = {};
 5             clone(o1[key],o2[key])
 6         }else{
 7             o1[key] = o2[key];
 8         }
 9     }
10 }

  4.复杂实现(一个参数)

    原理: clone(o) = new Object;

    返回一个对象 递归函数

 1 function clone(o){
 2     var temp = {};
 3     for(var key in o){
 4         if(typeof o[key] == 'object'){
 5             temp[key] = clone(o[key]);
 6         }else{
 7             temp[key] = o[key];
 8         }
 9     }
10     return temp;
11 }

使用递归实现 getElementsByClassName

  • 分析

    1. 实现一个方法byClass()需要的参数是: node: 在某个节点上寻找元素 className: 需要寻找的className arr: 找到的元素存储到这个数组中

    2. 遍历 node 的子节点,

    3. 查看这个子节点是否还有子节点,如果没有直接存储到数组中,如果有就继续递归

 1 var arr = [];
 2 function byClass(node, className, arr){
 3     //得到传入节点的所有子节点
 4     var lists = node.childNodes;
 5     for(var i = 0;i< lists.length;i++){
 6         //判断是否有相同className元素
 7         if(arr[i],className == className){
 8             arr.push(arr[i]);
 9         }
10         //判断子节点是否还有子节点
11         if(arr[i].childNodes.length > 0){
12             byClass(arr[i],className,arr);
13         }
14     }
15 }
  • 总结:

    js递归通俗的理解:所谓的递归函数就是在函数体内调用本函数。使用递归函数一定要注意,要有结束条件,处理不当就会进入死循环.

posted on 2017-04-13 21:57  手指间的舞动  阅读(483)  评论(0编辑  收藏  举报