递归的概念
- 在程序中函数直接或间接调用自己
- 直接调用自己
- 简介调用自己
- 跳出结构,有了跳出才有结果
递归的思想
- 递归的调用,最终还是要转换为自己这个函数
- 如果有个函数foo,如果他是递归函数,到最后问题还是转换为函数foo的形式
- 递归的思想就是将一个未知问题转换为一个已解决的问题来实现
递归的步骤(技巧)
1. 假设递归函数已经写好
2. 寻找递推关系
3. 将递推关系的结构转换为递归体
4. 将临界条件加入到递归体中7你
简单递归练习
求1-100的和
-
分析:
- 假设递归函数已经写好为sum,既sum(100),就是求1-100的和
-
寻找递推关系: 就是 n 与 n-1 ,或 n-2 之间的关系
sum(n) == sum(n-1) + n1 var res = sum(100); 2 var res = sum(99) + 100;
-
将递归结构转换成递归体
1 function sum(n){ 2 return sum(n-1) + n; 3 }
- 将临界条件加入到递归中
- 求100 转换为 求99
- 求99 转换为 求98
- 求98 转换为 求97
- ...
- 求2 转换为 求1
- 求1 转换为 求1
- 即 sum(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 项
-
分析:
假设已知 fib(n) 为第 n 项
递归关系 * fib(n) = fib(n-1) + fib(n-2)
递归体
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/)
- 分析
- 什么是拷贝
- 如果拷贝的时候, 只针对当前对象的属性进行拷贝, 而属性是引用类型这个不考虑, 那么就是浅拷贝
- 如果拷贝的时候, 将数据的所有引用结构都拷贝一份, 那么数据在内存中独立就是深拷贝(内存隔离,完全独立)
- 拷贝: 复制一份. 指将对象数据复制.
- 在讨论深拷与浅拷的时候一定要保证对象的属性也是引用类型.
- 实现方法:
- 如果要实现深拷贝那么就需要考虑将对象的属性, 与属性的属性,都拷贝过来
- 2个参数,简单实现
- 假设已经实现 clone ( o1, o2),将对象 o2 的成员拷贝一份交给 o1
- 递推关系
- 混合方法,将 o2 的成员拷贝到 o1 中
- 假设已经实现 clone ( o1, o2),将对象 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 }
-
总结: