什么是尾调用优化和尾递归?

10 篇文章 0 订阅

尾调用:某个函数的最后一步是调用另一个函数。
尾递归:如果尾调用自身,则是尾递归。

尾调用优化:
函数调用会在内存中形成一个“调用记录”,又称为“调用帧”,保存调用位置和内部变量信息。当函数嵌套的层级比较深,调用栈中的调用帧比较多,对内存的消耗很大。浏览器的调用栈的大小都有限制。
尾调用是函数的最后一步,所以不需要,保留外层函数的调用记录,因为调用位置、内部变量的信息不会再用到,可以直接用内层函数的调用记录,取代外层函数的调用记录。可以删除外层无用的调用帧,来节约浏览器的内存。

如何查看调用栈,
1.console.trace
2.debugger (Call Stack) (Local 局部变量)(Global 全局变量)

案例
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

解法:最后一步可以选择爬1个或2个台阶,则爬n阶等于爬(n-1)+(n-2)个台阶之和。当n=1,2;有1,2种方法;
用递归的方式

function f(n:number):number{
	if(n===1){return 1;}
	if(n===2){return 2}
	return f(n-1)+f(n-2)
}

但递归求解,当n很大时,会出现超时和调用堆栈溢出问题,则可以用尾递归进行优化,如下:

function f(n:number,ac1=1,ac2=1):number{
	if(n<=1){
		return ac2;
	}
	return f(n-1,ac2,ac1+ac2);
}

每次的结果都保留在参数中,只保留一个调用记录,复杂度 O(1),不需要保留每一步的调用记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值