概述

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

function f($n){if($n <= 1) return 1;return $n * f($n-1);
}

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

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发现这种情况,会复用函数栈,也就是说,函数栈大概是这么个情况:

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


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

递归函数两种方式的区别相关推荐

  1. vue 路由传参 params 与 query两种方式的区别(转载)

    vue 路由传参 params 与 query两种方式的区别 初学vue的时候,不知道如何在方法中跳转界面并传参,百度过后,了解到两种方式,params 与 query.然后,错误就这么来了:  ro ...

  2. java两种绑定方式_Javascript绑定事件的两种方式的区别

    命名函数 function check(){ //code } 匿名函数 window.onload = function(){ //先获取元素对象,再绑定事件,绑定的是匿名函数不可重用 var bt ...

  3. vue 路由传参 params 与 query两种方式的区别

    vue 路由传参 params 与 query两种方式的区别 初学vue的时候,不知道如何在方法中跳转界面并传参,百度过后,了解到两种方式,params 与 query.然后,错误就这么来了:  ro ...

  4. 多线程实现的两种方式及其区别

    继承Thread public class Demo2_Thread {public static void main(String[] args) {MyThread mt = new MyThre ...

  5. docker容器运行mysql持久化_docker容器实现数据持久化的两种方式及其区别

    前言 这篇博文是我对docker实现数据持久化几种方式的特征进行一个总结. 在docker中,它的存储文件系统是在dockerhost上原有的xfs或ext4架设了一层文件系统:overlay2(将此 ...

  6. MySQL 清空表数据的两种方式和区别

    在MySQL中删除数据有两种方式:truncate table 表名.delete from 表名. 它们在以下方面存在区别: 执行效率 truncate不扫描表,相当于重新创建了表,只保留了表的结构 ...

  7. java创建线程的两种方式及区别

    本文将介绍创建线程的两种方式,示例代码在下面,复制粘贴即可 继承Thread类方式和实现Runnable接口方式 区别:由于在开发的过程中,很多的类都会用到继承的方式,如果采用继承的方式会让各个类之间 ...

  8. Qt创建线程两种方式的区别

    使用QT创建线程有两种方式,方式A使用moveToThread,方式B是直接继承QThread.差异主要在于方式A的槽函数将会在新线程中运行,而方式B的槽函数在旧线程中运行. 结论如下: PS:旧线程 ...

  9. 关于利用qrcode生成二维码的两种方式的区别

    首先以下内容是查找网上资料后了解的利用qrcode.js生成二维码的额两种方式,canvas(即画布)方式和table方式(原文地址http://www.helloweba.com/view-blog ...

最新文章

  1. ROS控制无人机offboard模式
  2. 四路服务器芯片组,四路服务器主板配置
  3. Timus 1204 Idempotents
  4. post install error,please remove node_moules before retry
  5. mysql外表内表_mysql 子查询 将最外表带入子查询内2层 的另一种解决方法
  6. php和mysql一键安装包_iis+php+mysql一键安装教程和安装包
  7. 【UVA - 10037】Bridge(过河问题,经典贪心)
  8. C语言宏定义取得两数的最大值和最小值
  9. VirtualBox在win10下安装一个国产深度os桌面系统的操作教程
  10. C++ I/O 流 格式控制(上)
  11. Android 10如何增强移动安全性
  12. 零基础学习java------day1------计算机基础以及java的一些简单了解
  13. 第四季-专题1-课程规划与学习方法
  14. 桌面版 Linux 为什么打不过 Windows?Linus 现身说法!
  15. 微信怎么接龙?手把手教你使用微信群接龙功能
  16. 【STM32学习】(21)STM32实现步进电机
  17. Building Worlds In Unreal 学习笔记——07-11 岩石树落木灌木绘制/溪水着色器/潮湿与焦散贴花/后处理
  18. NS2协议分析与仿真
  19. 网络通信之如何广播发送
  20. 学会了使用计算机之后作文,我学会了计算机

热门文章

  1. mysql索引(b+tree)小记
  2. iOS中的异步和多线程概况
  3. 清华大学 lt;现代软件工程gt; 项目小组名单
  4. 顶级程序员的心得ndash;Coders at Work
  5. android studio导入eclipse项目各种问题,eclipse项目导入android studio 各类问题及解决方法...
  6. android远程桌面软件毕设_向日葵远程管理软件
  7. Java的文件流操作
  8. matlab实现图片区水印,怎么在含有水印的图像中提取出水印
  9. yolov4 开发环境搭建_YOLOv4 的各种新实现、配置、测试、训练资源汇总
  10. xshell vim 不能粘贴_linux基础知识:vim(vi)的知识