递归的三种实现方式

递归函数最基本的特点是函数自身调用自身,但必须在调用自身前有条件判断,否则无限无限调用下去。

利用引用做参数

  先不管引用做不做参数,必须先明白引用到底是什么?引用不过是指两个不同名的变量指向同一块存储地址。本来每个变量有各自的存储地址,赋值删除各行其道。现在可好,两个变量共享一块存储地址。 $a=&$b; 。实际上指的是 $a 不管不顾自己原来的存储地址,非要和 $b 共享一室了。因而任何对存储地址数值的改变都会影响两个值。  

  函数之间本来也是各行其是,即便是同名函数。递归函数是考虑将引用作为参数,成为一个桥梁,形成两个函数间的数据共享。虽然两个函数见貌似操作的是不同地址,但是实际上操作的是一块儿内存地址。

1
2
3
4
5
6
7
8
9
10
function test( $a =0,& $result = array ()){
$a ++;
if ( $a <10) {
   $result []= $a ;
   test( $a , $result );
}
echo $a ;
return $result ;
 
}

上面的例子非常简答,以a<10作为判断条件,条件成立,则把a赋给result[];将result的引用传入函数,会将每一次递归产生的a添加到结果数组result。因而本例生成的$result数组是 Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 ) 。

本例比较有意思的是echo a的值。相信很多人认为是12345678910吧,其实不然,是1098765432。为什么呢?因为函数还没执行echoa前就进行了下一次的函数递归。真正执行echo a是当a<10条件不满足的时候,echo a,返回result,对于上一层而言,执行完递归函数,开始执行本层的echo $a,依次类推。

  利用全局变量

  利用全局变量完成递归函数,请确保你确实理解什么是全局变量。global在函数内申明变量不过是外部变量的同名引用。变量的作用范围仍然在本函数范围内。改变这些变量的值,外部同名变量的值自然也改变了。但一旦用了&,同名变量不再是同名引用。利用全局变量实现递归函数没必要理解到这么深的一层,还保持原有对全局变量的看法就可以顺理成章理解递归函数。

?
1
2
3
4
5
6
7
8
9
function test( $a =0, $result = array ()){
   global $result ;
   $a ++;
   if ( $a <10) {
     $result []= $a ;
     test( $a , $result );
   }
   return $result ;
}

  利用静态变量

  我们常常在类中见到static,今天我们把它利用到递归函数中。请记住static的作用:仅在第一次调用函数的时候对变量进行初始化,并且保留变量值。

  举个栗子:

?
1
2
3
4
5
6
7
8
9
10
11
function test(){
static $count =0;
echo $count ;
 
$count ++;
}
test();
test();
test();
test();
test();

  请问这一段代码的执行结果是多少?是00000么?必然不是。是01234。首先第一次调用test(),static对 $count 进行初始化,其后每一次执行完都会保留 $count 的值,不再进行初始化,相当于直接忽略了 static $count=0; 这一句。

  因而将static应用到递归函数作用可想而知。在将需要作为递归函数间作为“桥梁"的变量利用static进行初始化,每一次递归都会保留"桥梁变量"的值。

?
1
2
3
4
5
6
7
8
9
function test( $a =0){
   static $result = array ();
   $a ++;
   if ( $a <10) {
     $result []= $a ;
     test( $a );
   }
   return $result ;
}

  总结

  所谓递归函数,重点是如何处理函数调用自身是如何保证所需要的结果得以在函数间合理"传递",当然也有不需要函数之间传值得递归函数,例如:

?
1
2
3
4
5
6
7
8
function test( $a =0){
   $a ++;
   if ( $a <10) {
     echo $a ;
 
     test( $a );
   }
}

最后分享一个php实现递归与无限分类的方法,具体实现方法如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
echo "<pre>" ;
$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 );
?>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值