递归是个神奇的东西,有时明白,有时候不明白。
写的多了便会总结。
总结两种常用的模式:
- 队列递归
- 级联递归
简单的说,一个是返回平坦的队列,一个是返回有层级关系的Map。以取得文件的目录树为例:
1 # 取得文档整体目录树 2 function tree( $path , $cutfix = 0 , $regexp = '/.*/' , $flat = 0 , $result = array() , $level = 0 ){ 3 $level = $level+1; 4 $dirs = scandir( $path ); 5 foreach($dirs as $d) { 6 $realpath = joinp( $path ,$d ); 7 $current = array(); 8 if( !is_dir($realpath) ){ continue ;} 9 if ($d == '.' || $d == '..') {} 10 else if( preg_match( $regexp , $d ) ){ 11 if( is_int( $flat ) ){ 12 $id = $this->gid('tree'); 13 $result[] = array( 'id'=>$id, 'pid'=> $flat, 'name' => $d , 'path' => substr( $realpath ,$cutfix ),'level'=>$level ); 14 $result = $result + $this -> tree( $realpath ,$cutfix , $regexp, $id , $result ,$level); 15 }else{ 16 $result[] = array( 'name' => $d , 'path' => substr( $realpath ,$cutfix ) , 'child' => $this->tree( $realpath ,$cutfix , $regexp , $flat ,$result ) ); 17 } 18 } 19 } 20 return $result; 21 }
队列递归返回:
[
-
-
id: 1,
-
pid: 0,
-
name: "first-1",
-
path: "/first-1",
-
level: 1
-
-
-
id: 2,
-
pid: 1,
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
level: 2
-
-
-
id: 3,
-
pid: 0,
-
name: "first-2",
-
path: "/first-2",
-
level: 1
-
-
-
id: 4,
-
pid: 3,
-
name: "sec-2-1",
-
path: "/first-2/sec-2-1",
-
level: 2
-
-
-
id: 5,
-
pid: 3,
-
name: "sec-2-2",
-
path: "/first-2/sec-2-2",
-
level: 2
-
-
-
id: 6,
-
pid: 5,
-
name: "thr",
-
path: "/first-2/sec-2-2/thr",
-
level: 3
-
]
级联递归返回
[
-
-
name: "first-1",
-
path: "/first-1",
-
child:
-
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
child: [ ]
-
-
-
-
-
name: "first-2",
-
path: "/first-2",
-
child:
-
-
name: "first-1",
-
path: "/first-1",
-
child:
-
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
child: [ ]
-
-
-
-
-
name: "sec-2-1",
-
path: "/first-2/sec-2-1",
-
child:
-
-
name: "first-1",
-
path: "/first-1",
-
child:
-
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
child: [ ]
-
-
-
-
-
-
-
name: "sec-2-2",
-
path: "/first-2/sec-2-2",
-
child:
-
-
name: "first-1",
-
path: "/first-1",
-
child:
-
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
child: [ ]
-
-
-
-
-
name: "sec-2-1",
-
path: "/first-2/sec-2-1",
-
child:
-
-
name: "first-1",
-
path: "/first-1",
-
child:
-
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
child: [ ]
-
-
-
-
-
-
-
name: "thr",
-
path: "/first-2/sec-2-2/thr",
-
child:
-
-
name: "first-1",
-
path: "/first-1",
-
child:
-
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
child: [ ]
-
-
-
-
-
name: "sec-2-1",
-
path: "/first-2/sec-2-1",
-
child:
-
-
name: "first-1",
-
path: "/first-1",
-
child:
-
-
name: "sec-do",
-
path: "/first-1/sec-do",
-
child: [ ]
-
-
-
-
-
-
-
-
-
-
-
]