PHP實現無限極分類之引用方法

本篇文章給大家帶來的內容是關於php實現無限極分類的方法:引用方法

面試的時候被問到無限極分類的設計和實現,比較常見的做法是在建表的時候,增加一個PID字段用來區別自己所屬的分類

數據在數據庫中存儲大概是這個樣子,怎麼實現無限極遞歸呢,有兩種常用的做法,遞歸和引用算法

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

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] => 通州區

                        )

 

                )

 

        )

 

)

//樹狀結構完美的輸出出來了 這個方法的核心就是引用傳值
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章