开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情
递归
谈到递归。大家应该不陌生。在开发中可能经常会使用到递归函数。一般开发场景递归调用次数较少。不会有什么问题。但是如果把递归用在算法中。当递归调用次数过多时。就出出现报错。这也是javascript的一种自我保护机制。比如说大多数人的算法入门,斐波那契数列。
function fibonacci(n){
if(n<=2) return 1
return fibonacci(n-1)+fibonacci(n-2)
}
console.log(fibonacci(10))
如果把这个函数在本地或者浏览器执行。n传入值较大,则会直接导致浏览器卡死。
写一个函数把n以下的数字相乘的函数。
function test(n){
if(n<1) return 1
return n*test(n-1)
}
console.log(test(10))
console.log(test(10000))
函数传入参数10的时候会正常执行。在1后面多加几个0之后。则无法正常输出结果。会得到报错。Maximum call stack size exceeded。我在本地执行代码的。在chrome中运行也是一样的结果。
那怎么能把这个函数优化。使浏览器可以输出正常的值呢?
PTC(Proper Tail Call)
下面的这种改写方式为尾调用。尾调用
function test(n){
if(n===0){
return 1
}
return n*test(n-1)
}
console.log(test(100))
在函数内部我们也可以使用console.trace()方法来观察调用栈。
PTC尾调用可以被优化。
TCO(Tail Call Optimization) 尾递归优化
PTC可以优化为TCO的方式。
function test(n, total = 1) {
if (n === 0) {
return total
}
return test(n - 1, n * total)
}
注意执行上面代码输入大数据是。依然会抛出error。必须要实现ES6引擎中运行代码。才会得到真实的结果。
总结
TC0优化并非唯一的优化手段。通过其他的方式优化。也可以实现对于函数的优化。比如对于斐波那契数列的优化。
function fibonacci(n){
if(n<=2) return 1
let n1 = 1
let n2=2
for(let i=3;i<n;i++){
let temp = n1
n1 = n2
n2 = temp+n2
}
return n2
}