php遞歸實現無限級分類樹

PHP實現無限極分類的兩種方式,遞歸和引用

 1 $array = array(
 2 array('id' => 1, 'pid' => 0, 'name' => '河北省'),
 3 array('id' => 2, 'pid' => 0, 'name' => '北京市'),
 4 array('id' => 3, 'pid' => 1, 'name' => '邯鄲市'),
 5 array('id' => 4, 'pid' => 2, 'name' => '朝陽區'),
 6 array('id' => 5, 'pid' => 2, 'name' => '通州區'),
 7 array('id' => 6, 'pid' => 4, 'name' => '望京'),
 8 array('id' => 7, 'pid' => 4, 'name' => '酒仙橋'),
 9 array('id' => 8, 'pid' => 3, 'name' => '永年區'),
10 array('id' => 9, 'pid' => 1, 'name' => '武安市'),
11 );

遞歸算法php

 1     /**
 2      * 遞歸實現無限極分類
 3      * @param $array 分類數據
 4      * @param $pid 父ID
 5      * @param $level 分類級別
 6      * @return $list 分好類的數組 直接遍歷便可 $level能夠用來遍歷縮進
 7      */
 8 
 9     function getTree($array, $pid =0, $level = 0){
10 
11         //聲明靜態數組,避免遞歸調用時,屢次聲明致使數組覆蓋
12         static $list = [];
13         foreach ($array as $key => $value){
14             //第一次遍歷,找到父節點爲根節點的節點 也就是pid=0的節點
15             if ($value['pid'] == $pid){
16                 //父節點爲根節點的節點,級別爲0,也就是第一級
17                 $value['level'] = $level;
18                 //把數組放到list中
19                 $list[] = $value;
20                 //把這個節點從數組中移除,減小後續遞歸消耗
21                 unset($array[$key]);
22                 //開始遞歸,查找父ID爲該節點ID的節點,級別則爲原級別+1
23                 getTree($array, $value['id'], $level+1);
24 
25             }
26         }
27         return $list;
28     }
29 
30     /*
31      * 得到遞歸完的數據,遍歷生成分類
32      */
33     $array = getTree($array);
34 
35     foreach($array) as $value{
36        echo str_repeat('--', $value['level']), $value['name'].'<br />';
37     }

 

引用算法算法

function generateTree($array){
    //第一步 構造數據
    $items = array();
    foreach($array as $value){
        $items[$value['id']] = $value;
    }
    //第二部 遍歷數據 生成樹狀結構
    $tree = array();
    foreach($items as $key => $value){
        if(isset($items[$item['pid']])){
            $items[$item['pid']]['son'][] = &$items[$key];
        }else{
            $tree[] = &$items[$key];
        }
    }
    return $tree;
}

 

//通過第一步 數據變成了這樣
Array
(
    [1] => Array
        (
            [id] => 1
            [pid] => 0
            [name] => 河北省
            [children] => Array
                (
                )

        )

    [2] => Array
        (
            [id] => 2
            [pid] => 0
            [name] => 北京市
            [children] => Array
                (
                )

        )

    [3] => Array
        (
            [id] => 3
            [pid] => 1
            [name] => 邯鄲市
            [children] => Array
                (
                )

        )

    [4] => Array
        (
            [id] => 4
            [pid] => 2
            [name] => 朝陽區
            [children] => Array
                (
                )

        )

    [5] => Array
        (
            [id] => 5
            [pid] => 2
            [name] => 通州區
            [children] => Array
                (
                )

        )

    [6] => Array
        (
            [id] => 6
            [pid] => 4
            [name] => 望京
            [children] => Array
                (
                )

        )

    [7] => Array
        (
            [id] => 7
            [pid] => 4
            [name] => 酒仙橋
            [children] => Array
                (
                )

        )

    [8] => Array
        (
            [id] => 8
            [pid] => 3
            [name] => 永年區
            [children] => Array
                (
                )

        )

    [9] => Array
        (
            [id] => 9
            [pid] => 1
            [name] => 武安市
            [children] => Array
                (
                )

        )

)

//第一步很容易就能看懂,就是構造數據,如今我們仔細說一下第二步
 $tree = array();
 //遍歷構造的數據
    foreach($items as $key => $value){
    //若是pid這個節點存在
        if(isset($items[$value['pid']])){
            //把當前的$value放到pid節點的son中 注意 這裏傳遞的是引用 爲何呢?
            $items[$value['pid']]['son'][] = &$items[$key];
        }else{
            $tree[] = &$items[$key];
        }
    }

//這個方法的核心在於引用,php變量默認的傳值方式是按指傳遞
//也就是說 假如說 遍歷順序是 河北省 邯鄲市 當遍歷到河北省時 會把河北省放到tree中 遍歷到邯鄲市時 會把邯鄲市放到河北省的子節點數組中 可是!!! 這會兒的tree數組中 河北省已經放進去了 根據php變量按值傳遞的規則 你並無更改tree數組中的河北省的數據 因此這裏用到了引用傳遞
//當你對河北省作更改時,tree數組中的河北省也一併作了更改 下面咱們作個實驗 咱們把引用傳遞去掉,看一下結果

//使用普通傳值輸出結果
 Array
(
    [0] => Array
        (
            [id] => 1
            [pid] => 0
            [name] => 河北省
        )

    [1] => Array
        (
            [id] => 2
            [pid] => 0
            [name] => 北京市
        )

)
//能夠看到 只有河北省和北京市輸出出來了 由於他們倆是第一級節點 並且排行1和2,放到$tree數組中以後,沒有使用引用傳遞,那麼後續對他倆的子節點的操做都沒有在$tree中生效,如今咱們更改一下順序 把邯鄲市放到河北省的前面 那麼根據我們的推斷 那麼邯鄲市就應該出如今tree數組裏

//邯鄲市放到河北省前面的輸出結果
Array
(
    [0] => Array
        (
            [id] => 1
            [pid] => 0
            [name] => 河北省
            [son] => Array
                (
                    [0] => Array
                        (
                            [id] => 3
                            [pid] => 1
                            [name] => 邯鄲市
                        )

                )

        )

    [1] => Array
        (
            [id] => 2
            [pid] => 0
            [name] => 北京市
        )

)

//果真是這樣 那麼證實咱們的推斷是正確的 如今咱們把引用傳值改回去 再看一下

//使用引用傳值輸出結果
Array
(
    [1] => Array
        (
            [id] => 1
            [pid] => 0
            [name] => 河北省
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => 3
                            [pid] => 1
                            [name] => 邯鄲市
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 8
                                            [pid] => 3
                                            [name] => 永年區
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [id] => 9
                            [pid] => 1
                            [name] => 武安市
                        )

                )

        )

    [2] => Array
        (
            [id] => 2
            [pid] => 0
            [name] => 北京市
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => 4
                            [pid] => 2
                            [name] => 朝陽區
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 6
                                            [pid] => 4
                                            [name] => 望京
                                        )

                                    [1] => Array
                                        (
                                            [id] => 7
                                            [pid] => 4
                                            [name] => 酒仙橋
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [id] => 5
                            [pid] => 2
                            [name] => 通州區
                        )

                )

        )

)

---------------------
做者:12345987
來源:CSDN
原文:https://blog.csdn.net/tiansidehao/article/details/79025359 數組

相關文章
相關標籤/搜索