php遞歸函數使用問題總結

 最近在使用遞歸函數時,遇到一個問題,先看代碼效果再分析

先給一個數組

$arr = array(
    0=>array(
        'cid'=>1,
        'pid'=>0,
        'name'=>'亞洲',
    ),
    1=>array(
        'cid'=>2,
        'pid'=>0,
        'name'=>'北美洲',
    ),
    2=>array(
        'cid'=>3,
        'pid'=>1,
        'name'=>'中國',
    ),
    3=>array(
        'cid'=>4,
        'pid'=>2,
        'name'=>'美國',
    ),
    4=>array(
        'cid'=>5,
        'pid'=>3,
        'name'=>'北京',
    ),
    5=>array(
        'cid'=>6,
        'pid'=>3,
        'name'=>'河北',
    ),
    6=>array(
        'cid'=>7,
        'pid'=>5,
        'name'=>'東城區',
    ),
    7=>array(
        'cid'=>8,
        'pid'=>5,
        'name'=>'海淀區',
    ),
    8=>array(
        'cid'=>9,
        'pid'=>5,
        'name'=>'大興區',
    ),
);

正確遞歸方法:

function tree($cate,$pid=0,$level=0,$html="└―"){
    global $list;
    foreach($cate as $v){
        if($v['pid']==$pid){
            $v['html'] = str_repeat($html,$level);
            $list[] = $v;
            tree($cate,$v['cid'],$level+1);
        }
    }
    return $list;
}

$lists = tree($arr);

foreach($lists as $v){
    echo $v['html'].$v['name'].'<br>';
}

顯示結果:

亞洲
└―中國
└―└―北京
└―└―└―東城區
└―└―└―海淀區
└―└―└―大興區
└―└―河北
北美洲
└―美國

 

錯誤遞歸方法:

function tree($cate,$pid=0,$level=0,$html="└―"){
    global $list;
    foreach($cate as $v){
        if($v['pid']==$pid){

            /* 問題出在下面兩行 */
            $html = str_repeat($html,$level);
            $v['html'] = $html;

            $list[] = $v;
            tree($cate,$v['cid'],$level+1);
        }
    }
    return $list;
}

$lists = tree($arr);

foreach($lists as $v){
    echo $v['html'].$v['name'].'<br>';
}


顯示結果:

亞洲
└―中國
└―└―北京
└―└―└―東城區
└―└―└―└―└―└―└―└―└―海淀區
└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―└―大興區
└―└―└―└―河北
北美洲
└―美國

個人分析:第二種錯誤情況是因爲中間使用了一個$html中轉賦值導致的。 在遍歷$arr數組過程中,如果在一個if循環過程中,由於$html賦的值在當前作用域下是一直有效的,所以有多個數據滿足$v['pid']==$pid條件時,此時$html是會被累計追加的。只有跳出一個if循環過程後,重新回到foreach循環中時,此時已跳出if中的$html的作用域,數據才被釋放,將會重新從初始值開始。

最後做了一個驗證:將if循環結構中的$html變量名換成另一個任意名稱如$htmls,確保跟遞歸函數中的$html參數不一致,這樣就不存在作用域的問題了,修改後顯示結果顯示正常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章