数据结构与算法之PHP递归函数
一、递归函数的定义
递归函数即自调用函数,在函数体内部直接或者间接的自己调用自己,即函数的嵌套调用是函数本身。
通常在此类型的函数题中会附加一个条件判断叙述,以判断是否需要执行递归调用,并且在特定的条件下终止函数的递归调用动作,把目前流程的主控权交回到上一层函数来执行。
在函数执行的第1步~第10步,函数输出的的是绿色部分,红色部分还“没来得及”输出,就调用自己执行操作,依次类推,直到流程执行到不再满足调用自己的条件,输出“<-->”,此时,流程该执行前面“没来得及”输出的代码。
二、实现递归的三种基本方式
1. 利用引用做参数
2. 利用全局变量
global在函数内申明变量是外部变量的同名引用。
<?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。 流程如下图:
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<10作为判断条件,条件成立,就把$a赋给$result[];将$result的引用传入函数,会将每一次递归产生的$a添加到结果数组$result中。
- echo $a的值是10987654321,而不是12345678910。 这是因为当$a<10的时候,在echo $a前就进行了下一次的函数递归。当$a不满足$a<10的条件时,echo $a,返回$result,并执行前几次递归函数中的echo $a。
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']."
"; //这里输出,是为了看效果 $list[] = $v; t($arr,$v['id'],$lev+1); } } return $list; } $list = t($area); echo "
"; // print_r($list);
该程序执行后输出如下结果:
北京 朝阳区 亚运村 奥运村 海淀区 广西 南宁市 武鸣县 广东 福建 福州市