递归

递归(英语:Recursion),又译为递回,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。递归一词还较常用于描述以自相似方法重复事物的过程。例如,当两面镜子相互之间近似平行时,镜中嵌套的图像是以无限递归的形式出现的。也可以理解为自我复制的过程。维基百科
特别是在计算机领域,很多问题用递归的解决都会有奇效,比如树的遍历(深度优先遍历、广度优先遍历等),下面以几个简单的例子通过JavaScript语言来了解一些递归的作用,其他计算机语言也是相似的。

处理树形结构的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// 树形结构的数据
let data = [
{
id: 1,
name: '家电',
goods: [
{
id: 11,
gname: '冰箱'
},{
id: 12,
gname:'洗衣机'
}
]
},
{
id: 2,
name:'服饰'
},
{
id: 3,
name:'手机',
goods:[
{
id: 31,
gname: '华为'
},
{
id: 32,
gname: "小米"
},
{
id: 33,
gname: "苹果"
}
]
}
]
// 方法一
let res;
function getElementById(array, id){
for (let index = 0; index < array.length; index++) {
const element = array[index];
if(id === element.id){
res = element;
break;
}else if(element.goods && element.goods instanceof Array){
getElementById(element.goods, id);
}
}
}
getElementById(data, 33)
// getElementById(data, 1)//undefined
console.log(res);
// 方法二
// 利用闭包把res作为内部变量,最终在函数体直接返回
const getElementById2 = (()=>{
let res;
return function (array, id){
for (let index = 0; index < array.length; index++) {
const element = array[index];
if(id === element.id){
res = element;
break;
}else if(element.goods && element.goods instanceof Array){
getElementById(element.goods, id);
}
}
return res;
}
})();

斐波那契额数列(兔子数列)1,1,2,3,5,8,13,21,34,…

1
2
3
4
5
6
7
8
function fb(n){
if(n===1 || n===2){
return 1;
}else{
return fb(n-1) + fb(n-2);
}
}

利用递归进行深复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function deepClone(object, target = {}){
/**
* for...in会遍历继承属性,但该属性必须是可以枚举的,比如数组的length属性就是不可枚举,所以就不能遍历,
* 但仍然可以通过[1,2,3].length继续获取该属性值,但是不能被for...in进行遍历出来,
* 为了避免继承属性的干扰,故而用Object.hasOwnProperty来排除继承继承属性
* */
for (const key in object) {
// Object.hasOwnProperty来排除继承继承属性,或者object.hasOwnProperty(key)也可以
// Object.prototype.hasOwnProperty === Object.hasOwnProperty //true
if (Object.hasOwnProperty.call(object, key)) {
const element = object[key];
if(typeof element !="object"){
target[key] = element;
}else if(element instanceof Array){
target[key] = deepClone(element)
}
}
}
return target;
}

总结:递归往往可以让代码更加简洁,而且使得解决问题的思路变得简单,但递归很消耗内存,而且递归一定要注意递归结束条件,否则容易造成栈溢出!


递归
https://zbdev.online/2023/02/27/递归/
作者
zzb
发布于
2023年2月27日
许可协议