前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >递归函数两种方式的区别

递归函数两种方式的区别

作者头像
烟草的香味
发布2019-11-11 22:53:54
6520
发布2019-11-11 22:53:54
举报
文章被收录于专栏:烟草的香味烟草的香味

概述

递归函数都不陌生,比如计算n的阶乘:

代码语言:javascript
复制
function f($n){
    if($n <= 1) return 1;
    return $n * f($n-1);
}

当然,有人可能会这么写:

代码语言:javascript
复制
function f($n, $result){
    if($n <= 1) return $result;
    return f($n-1, $n*$result);
}

上面两种方式看着好像没什么区别,但是在cpu眼中,可就不一样了。

分析

函数在调用的时候会开辟一块函数栈,用来保存函数的局部变量、参数、上一个栈的指针、返回值等信息,当函数调用结束后会销毁。递归函数会一直递归下去,上层的函数栈一直不会销毁,知道递归结束,全部退出。

举个栗子,当调用f(3)的时候,对于上面的第一种情况,函数栈大概长这样(仅保留参数和返回值,忽略其他内容):

文字描述就是:

f(1)=1 f(2)=2*f(1)=2*1=2 f(3)=3*f(2)=3*2=6 f(4)=4*f(3)=4*6=24

也就是每一次调用,都会保存本次的变量n以及递归调用的返回值,这就会导致如果递归的太深,就会开辟太多的内存。

如果使用第二种写法,会有什么不同么?

套用刚才的分析,先用文字描述一下:

f(4, 1)=f(3, 4*1)=f(2, 3*4)=f(1, 2*12)=24

有没有发现区别,区别就是,前一种写法要保存一个局部变量n,而后一种写法,都写到下一个方法的参数中了。也就是说,第二种方式,可以直接返回下层方法,不需要退回去了。当然,cpu发现这种情况,会复用函数栈,也就是说,函数栈大概是这么个情况:

看着好像也没啥区别,但是!因为可以直接返回,上图的四个栈使用的都是同一个栈。完美优化。


当递归返回的是递归调用,并且讲调用直接返回,没有参与运算等,就会被这样优化,复用栈。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 烟草的香味 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档