php 迭代和递归,实战PHP数据结构基础之递归
什么是递归?
之前说到,递归是一种将大问题分解为小问题的解决方案。一般来说,递归被称为函数自身的调用。这么说可能听起来很奇怪,事实上在递归中,函数确实必须调用自己。
一个栗子
例如在数学中,我们都知道“阶乘”的概念。例如5的阶乘就是5*4*3*2*1。
5!= 5 * 4!
4!= 4 * 3!
3!= 3 * 2!
2!= 2 * 1!
1!= 1 * 0!
0!= 1
我们可以总结出求n的阶乘的规律,即 n! = n * (n -1) !
这就体现了递归。你可以从中发现,我们把求5的阶乘一步一步转化成了另外一个个的小问题。
递归算法的特性
每一个递归调用都必须基于一个小的子问题。例如5的阶乘就是5乘4的阶乘。
递归必须有一个Base case。例如阶乘的Base case就是0,当条件是0的时候,就停止递归。
递归中避免循环调用,否则最后计算机会显示栈溢出的错误。
function factorial(int $n): int
{
if ($n = 0) {
return 1;
}
return $n * factorial($n - 1);
}
看上面的代码,我们可以看到对于阶乘问题的解决方案我们有一个基础的条件就是当n为0的时候,我们返回1。如果不符合这个条件,我们返回n 乘 factorial(n) ,这符合递归特性的第一条和第三条。我们避免了循环调用,因为我们把每一次的递归调用都分解成了大问题的一个小的子问题。上面的算法思想可以表达成:
递归Vs迭代
上面的递归代码我们同样可以使用迭代的方法实现
function factorial(int $n): int
{
$result = 1;
for ($i = $n; $i > 0; $i--) {
$result*= $n;
}
return $result;
}
如果一个问题可以很容易的使用迭代来解决,我们为何要使用递归?
递归是用来处理更加复杂的问题的,不是所有的问题都可以简单的使用迭代来解决的。递归使用函数调用来管理调用栈,所以相比于迭代递归会使用更多和时间以及内存。此外,在迭代中,我们每一步都会有一个结果,但是在递归中我们必须等到base case执行结束才会有任何结果。看上面的例子,我们发现在递归算法中我们没有任何变量或者声明来保存结果,而在迭代算法中,我们每一次都用$result来保存了返回结果。
斐波那契数列
在数学中,斐波那契数列是一个特殊的整数数列,数列中的每一个数的是由另外两个数求和产生的。规则如下:
function fibonacci($n)
{
if ($n == 0) {
return 0;
}
if ($n == 1) {
return 1;
}
return fibonacci($n - 1) + fibonacci($ - 2);
}
最大公因数
另外一个使用递归算法的常见问题是求两个数的最大公因数。
function gcd(int $a, int $b)
{
if ($b == 0) {
return $a;
}
return gcd($b, $a % $b);
}
递归类型
线性递归
在每一次递归调用中,函数只调用自己一次,这就叫做线性递归。
二分递归
在二分递归中,每一次递归调用函数调用自己两次。求解斐波那契数列的算法就是二分递归,除此之外还有二分查找、分治算法、归并排序等也使用了二分递归。
尾递归
当一个递归返回的时候没有等待的操作的时候就称为尾递归。斐波那契算法中,返回值需要乘以前一个递归的返回值,因此他不是尾递归,而求解最大公因式的算法是尾递归。尾递归是线性递归的一种形式。
相互递归
例如在每一次递归调用中 有 A() 调用 B(), B() 调用 A() ,这样的递归就叫做相互递归。
嵌套递归
当一个递归函数把自己作为一个参数进行递归调用时,就叫做嵌套递归。一个常见的栗子就是阿克曼函数,看下面的表达。
看最后一行的,可以看到第二个参数就是递归函数自己。
下一节
下一篇内容会使用递归解决一些实际开发中会遇到的问题,例如构建N级分类、构建嵌套评论、目录文件的遍历等等。
更多内容
PHP基础数据结构专题系列目录地址:地址 主要使用PHP语法总结基础的数据结构和算法。还有我们日常PHP开发中容易忽略的基础知识和现代PHP开发中关于规范、部署、优化的一些实战性建议,同时还有对Javascript语言特点的深入研究。
php 迭代和递归,实战PHP数据结构基础之递归相关推荐
- 实战PHP数据结构基础之队列
什么是队列 队列是另外一种遵循先进先出原则的线性数据结构.队列有两端可供操作,一端出队,一端入队.这个特点和栈不同,栈只有一端可以用来操作.入队总是在后端,出队在前端. 常见操作 enqueue -& ...
- 简洁笔记-Java数据结构基础(5.递归和斐波那契数列、汉诺塔)
什么是递归 递归简单来说就是方法调用自己 例子1: 从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山.. 例子2:美女拿着自己的照片, ...
- python画树递归_用递归的方式绘制小树_Python数据结构实战(1):递归(算法面试)_Python视频-51CTO学院...
购买本课程后,可以加51CTO学院李宁老师官方交流群:550369460注意,该群只允许购买李宁老师课程的学员进行技术交流,加群时需要提供在51CTO购买李宁老师课程的订单编号(任何一个课程的订单编号 ...
- 【数据结构基础】图的遍历方法与应用
前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...
- 数据结构基础知识核心归纳(一)
数据结构基础知识核心归纳(一) 转载请声明出处:http://blog.csdn.net/andrexpert/article/details/77900395 Android ...
- 阿里云Kubernetes实战2–搭建基础服务
前言: 在系列的第一篇文章中,我已经介绍过如何在阿里云基于kubeasz搭建K8S集群,通过在K8S上部署gitlab并暴露至集群外来演示服务部署与发现的流程.文章写于4月,忙碌了小半年后,我才有时间 ...
- Algorithm:【Algorithm算法进阶之路】之数据结构基础知识
Algorithm:[Algorithm算法进阶之路]之数据结构基础知识 相关文章 Algorithm:[Algorithm算法进阶之路]之数据结构二十多种算法演示 Algorithm:[Algori ...
- 由任意二叉树的前序遍历序列和中序遍历序列求二叉树的思想方法_算法与数据结构基础 - 二叉树(Binary Tree)...
二叉树基础 满足这样性质的树称为二叉树:空树或节点最多有两个子树,称为左子树.右子树, 左右子树节点同样最多有两个子树. 二叉树是递归定义的,因而常用递归/DFS的思想处理二叉树相关问题,例如Leet ...
- 【数据分析与挖掘】数据分析学习及跟课学习 | csdn_Part 02 数据结构基础
依旧是整理笔记的一天,纸质笔记为了简便很多东西没有完全写上,一些小练习也没跟上,再进行练习的时候好像有点问题.尽量打字熟悉吧,并且对于这方面知识可以以专业角度去深挖,不要仅限于分析的理论层面.另外数据 ...
最新文章
- 支付宝 php rsa算法,:PHP支付宝接口RSA验证
- Tomcat 处理 HTTP 请求源码分析(下)【转】
- 图形图像显示研究(一)
- SEO按天关键词计费排名查询系统源码
- 第三十一章 考试作弊
- linux中 centos6 文件误删如何恢复
- 安装 SQL Server 2005 时出现性能计数器要求安装错误的解决办法
- Selenium的定位元素
- python 特征选择卡方_4. 机器学习之特征选择-Python代码
- micropython开发idethonny_esp32 micropython using uPycraft IDE
- Ubuntu 手动挂载U盘
- 小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_11、SpringBoot2.x目录文件结构讲解...
- Windows 10搜集的用户隐私数据全部在此
- Python转Java程序(1)
- 算法精解:C语言描述
- 定向寻宝亲子活动设计思路和实操(附2019最新教程)
- 19【推荐系统16】CTRCVR联合学习
- scipy中使用linalg.inv函数计算矩阵的逆矩阵
- 学会这招,小姐姐看你的眼神将不一样
- Javase day06_作业
热门文章
- 进程、地址空间、文件、I/O、保护、虚拟内存
- srsLTE源码学习:逻辑信道多路复用与MAC CE分解pdu_queue.h,pdu_queue.cc
- 百度地图获取河流_想要提高学生对地理的兴趣,就要多利用地图,培养学生的思维能力...
- nohttp网络框架
- assets和res/raw的用法
- easy connect电脑版_北师大版小学英语六年级上册Unit4课文听力+翻译+单词录音跟读+高清课本(一起点)...
- solr 高并发_预防帕金森病的运动并发症,比治疗更重要!
- java讲对象放在常量池的方法_java的常量池里面都放了些神马东西
- 浅析python中的main函数_浅的意思
- 容器安全 - 利用特权模式运行的容器,实现容器逃逸和入侵