数据结构与算法之PHP递归函数
一、递归函数的定义
递归函数即自调用函数,在函数体内部直接或者间接的自己调用自己,即函数的嵌套调用是函数本身。
通常在此类型的函数题中会附加一个条件判断叙述,以判断是否需要执行递归调用,并且在特定的条件下终止函数的递归调用动作,把目前流程的主控权交回到上一层函数来执行。
<?php //声明一个函数,用于测试递归 function test($n){ echo $n . " "; //在函数开始处输出参数的值 if ($n > 0) { //判断参数是否大于0 test($n-1); //如果参数大于0则调用自己,并将参数减1后再次传入 } else { //判断参数不大于0 echo "<-------->"; } echo $n." "; //在函数结束处输出参数的值 } //调用test函数将整数10传给参数 test(10);
该程序执行后输出如下结果:
10 9 8 7 6 5 4 3 2 1 0 <--------> 0 1 2 3 4 5 6 7 8 9 10
解释:
第1步,执行test(10),echo 10,然后因为10>0,执行test(9),后面还有没来得及执行的echo 10;
第2步,执行test(9),echo 9,然后因为9>0,执行test(8),同样后面还有没来得及执行的 echo 9;
第3步,执行test(8),echo 8,然后因为8>0,执行test(7),同样后面还有没来得及执行的 echo 8;
第4步,执行test(7),echo 7,然后因为7>0,执行test(6),同样后面还有没来得及执行的 echo 7;
第5步,执行test(6),echo 6,然后因为6>0,执行test(5),同样后面还有没来得及执行的 echo 6;
...........
第10步,执行test(0),echo 0,此时0>0的条件不满足,不再执行test()函数,而是echo “<-------->”,并且执行后面的 echo 0;
这时,函数不再调用自己,将流程的主控权交回到上一层函数来执行,也就是开始执行刚刚所有test()函数没来得及输出的最后一个echo。
流程如下图:
在函数执行的第1步~第10步,函数输出的的是绿色部分,红色部分还“没来得及”输出,就调用自己执行操作,依次类推,直到流程执行到不再满足调用自己的条件,输出“<-->”,此时,流程该执行前面“没来得及”输出的代码。
二、实现递归的三种基本方式
1. 利用引用做参数
function test($a = 0, &$result = array()) { $a++; if ($a < 10) { $result[] = $a; test($a, $result); } echo $a; return $result; }
该程序执行后,
-
$result数组是Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 ) 。以a赋给result的引用传入函数,会将每一次递归产生的result中。
-
echo $a的值是10987654321,而不是12345678910。这是因为当a前就进行了下一次的函数递归。当a<10的条件时,echo result,并执行前几次递归函数中的echo $a。
2. 利用全局变量
global在函数内申明变量是外部变量的同名引用。
function test($a = 0, $result = array()) { global $result; $a++; if ($a < 10) { $result[] = $a; test($a, $result); } return $result; }
3. 利用静态变量
static仅在第一次调用函数的时候对变量进行初始化,并且保留变量值。
function test($a = 0) { static $result = array(); $a++; if ($a < 10) { $result[] = $a; test($a); } return $result; }
三、PHP实现递归与无限分类的方法
$area = array( array('id'=>1,'area'=>'北京','pid'=>0), array('id'=>2,'area'=>'广西','pid'=>0), array('id'=>3,'area'=>'广东','pid'=>0), array('id'=>4,'area'=>'福建','pid'=>0), array('id'=>11,'area'=>'朝阳区','pid'=>1), array('id'=>12,'area'=>'海淀区','pid'=>1), array('id'=>21,'area'=>'南宁市','pid'=>2), array('id'=>45,'area'=>'福州市','pid'=>4), array('id'=>113,'area'=>'亚运村','pid'=>11), array('id'=>115,'area'=>'奥运村','pid'=>11), array('id'=>234,'area'=>'武鸣县','pid'=>21) ); function t($arr,$pid=0,$lev=0){ static $list = array(); foreach($arr as $v){ if($v['pid']==$pid){ echo str_repeat(" ",$lev).$v['area']."<br />"; //这里输出,是为了看效果 $list[] = $v; t($arr,$v['id'],$lev+1); } } return $list; } $list = t($area); echo "<hr >"; // print_r($list);
该程序执行后输出如下结果:
北京
朝阳区
亚运村
奥运村
海淀区
广西
南宁市
武鸣县
广东
福建
福州市
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现