php遞歸算法

遞歸函數是咱們經常使用到的一類函數,最基本的特色是函數自身調用自身,但必須在調用自身前有條件判斷,不然無限無限調用下去。實現遞歸函數能夠採起什麼方式呢?本文列出了三種基本方式。理解其原來須要必定的基礎知識水品,包括對全局變量,引用,靜態變量的理解,也需對他們的做用範圍有所理解。遞歸函數也是解決無限級分類的一個很好地技巧。若是對無限級分類感興趣,請參照php利用遞歸函數實現無限級分類。我習慣套用通俗的話解釋複雜的道理,您確實不明白請參見手冊。php

  利用引用作參數數組

  先無論引用作不作參數,必須先明白引用究竟是什麼?引用不過是指兩個不一樣名的變量指向同一塊存儲地址。原本每一個變量有各自的存儲地址,賦值刪除各行其道。如今可好,兩個變量共享一塊存儲地址。 $a=&$b; 。實際上指的是 $a 無論不顧本身原來的存儲地址,非要和 $b 共享一室了。於是任何對存儲地址數值的改變都會影響兩個值。  函數

  函數之間原本也是各行其是,即使是同名函數。遞歸函數是考慮將引用做爲參數,成爲一個橋樑,造成兩個函數間的數據共享。雖然兩個函數見貌似操做的是不一樣地址,可是實際上操做的是一起內存地址。spa

?.net

1code

2htm

3遞歸

4內存

5ci

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);

?>

相關文章
相關標籤/搜索