首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 從二維數組構建 N 層分類樹(單次遍歷 + 內存引用)

     編輯:PHP 綜合知識

電商分類、CMS 欄目、組織架構等層級數據常以「扁平數組 + pid 指向父級」形式存儲。構建樹形結構的最優解是「單次遍歷 + 內存引用」,無需遞歸、無需多次查庫,時間複雜度 O(n)。

數據源格式要求

  • 一維鍵 = 記錄 ID(如 $items[3]['id'] === 3)
  • 每項包含 id、pid(父級 ID,頂級為 0)
$items = [ 
    1 => ['id'=>1, 'pid'=>0, 'name'=>'江西省'], 
    2 => ['id'=>2, 'pid'=>0, 'name'=>'黑龍江省'], 
    3 => ['id'=>3, 'pid'=>1, 'name'=>'南昌市'], 
    4 => ['id'=>4, 'pid'=>2, 'name'=>'哈爾濱市'], 
    5 => ['id'=>5, 'pid'=>2, 'name'=>'雞西市'], 
    6 => ['id'=>6, 'pid'=>4, 'name'=>'香坊區'], 
    7 => ['id'=>7, 'pid'=>4, 'name'=>'南崗區'], 
    8 => ['id'=>8, 'pid'=>6, 'name'=>'和興路'], 
    9 => ['id'=>9, 'pid'=>7, 'name'=>'西大直街'], 
    10 => ['id'=>10, 'pid'=>8, 'name'=>'東北林業大學'], 
    11 => ['id'=>11, 'pid'=>9, 'name'=>'哈爾濱工業大學'], 
    12 => ['id'=>12, 'pid'=>8, 'name'=>'哈爾濱師范大學'], 
    13 => ['id'=>13, 'pid'=>1, 'name'=>'贛州市'], 
    14 => ['id'=>14, 'pid'=>13, 'name'=>'贛縣'], 
    15 => ['id'=>15, 'pid'=>13, 'name'=>'於都縣'], 
    16 => ['id'=>16, 'pid'=>14, 'name'=>'茅店鎮'], 
    17 => ['id'=>17, 'pid'=>14, 'name'=>'大田鄉'], 
    18 => ['id'=>18, 'pid'=>16, 'name'=>'義源村'], 
    19 => ['id'=>19, 'pid'=>16, 'name'=>'上壩村'], 
];

極簡版(5 行核心邏輯)

function genTree5($items) { 
    foreach ($items as $item) 
        $items[$item['pid']]['son'][$item['id']] = &$items[$item['id']]; 
    return isset($items[0]['son']) ? $items[0]['son'] : []; 
}

標準版(含根節點收集、健壯性檢查)

function genTree9($items) { 
    $tree = []; 
    foreach ($items as $item) { 
        if (isset($items[$item['pid']])) { 
            // 父級存在,掛載到父級的 son 數組 
            $items[$item['pid']]['son'][] = &$items[$item['id']]; 
        } else { 
            // 父級不存在(pid=0 或數據不全),作為根節點 
            $tree[] = &$items[$item['id']]; 
        } 
    } 
    return $tree; 
}

輸出結構示例

Array 
( 
    [0] => Array 
        ( 
            [id] => 1 
            [pid] => 0 
            [name] => 江西省 
            [son] => Array 
                ( 
                    [0] => Array ([id]=>3, [pid]=>1, [name]=>南昌市) 
                    [1] => Array 
                        ( 
                            [id] => 13 
                            [pid] => 1 
                            [name] => 贛州市 
                            [son] => Array 
                                ( 
                                    [0] => Array 
                                        ( 
                                            [id] => 14 
                                            [pid] => 13 
                                            [name] => 贛縣 
                                            [son] => Array 
                                                ( 
                                                    [0] => Array 
                                                        ( 
                                                            [id] => 16 
                                                            [pid] => 14 
                                                            [name] => 茅店鎮 
                                                            [son] => Array 
                                                                ( 
                                                                    [0] => Array ([id]=>18, [pid]=>16, [name]=>義源村) 
                                                                    [1] => Array ([id]=>19, [pid]=>16, [name]=>上壩村) 
                                                                ) 
                                                        ) 
                                                    [1] => Array ([id]=>17, [pid]=>14, [name]=>大田鄉) 
                                                ) 
                                        ) 
                                    [1] => Array ([id]=>15, [pid]=>13, [name]=>於都縣) 
                                ) 
                        ) 
                ) 
        ) 
    [1] => Array 
        ( 
            [id] => 2 
            [pid] => 0 
            [name] => 黑龍江省 
            [son] => Array 
                ( 
                    [0] => Array 
                        ( 
                            [id] => 4 
                            [pid] => 2 
                            [name] => 哈爾濱市 
                            [son] => Array 
                                ( 
                                    [0] => Array 
                                        ( 
                                            [id] => 6 
                                            [pid] => 4 
                                            [name] => 香坊區 
                                            [son] => Array 
                                                ( 
                                                    [0] => Array 
                                                        ( 
                                                            [id] => 8 
                                                            [pid] => 6 
                                                            [name] => 和興路 
                                                            [son] => Array 
                                                                ( 
                                                                    [0] => Array ([id]=>10, [pid]=>8, [name]=>東北林業大學) 
                                                                    [1] => Array ([id]=>12, [pid]=>8, [name]=>哈爾濱師范大學) 
                                                                ) 
                                                        ) 
                                                ) 
                                        ) 
                                    [1] => Array 
                                        ( 
                                            [id] => 7 
                                            [pid] => 4 
                                            [name] => 南崗區 
                                            [son] => Array 
                                                ( 
                                                    [0] => Array 
                                                        ( 
                                                            [id] => 9 
                                                            [pid] => 7 
                                                            [name] => 西大直街 
                                                            [son] => Array 
                                                                ( 
                                                                    [0] => Array ([id]=>11, [pid]=>9, [name]=>哈爾濱工業大學) 
                                                                ) 
                                                        ) 
                                                ) 
                                        ) 
                                ) 
                        ) 
                    [1] => Array ([id]=>5, [pid]=>2, [name]=>雞西市) 
                ) 
        ) 
)

核心技巧解析

技巧作用
&$items[$item['id']]引用賦值,父子節點指向同一內存,修改任意一處即生效
$items[$item['pid']]利用一維鍵 = ID 特性,O(1) 直接定位父節點
單次 foreach無遞歸、無二次查詢,時間 O(n),空間 O(n)
isset($items[$item['pid']])兼容 pid=0(頂級)與髒數據(父級缺失)

適用條件與擴展

  • 必要條件:數組鍵 = 記錄 ID,否則需先 $map = array_column($items, null, 'id') 重建索引
  • 字段名可配置:genTree($items, 'id', 'pid', 'children')
  • 排序需求:遍歷前 uasort($items, fn(a,b)=>a['sort']-b['sort'])
  • 大數據量:10萬+ 節點建議分批處理或用遞歸 CTE (MySQL 8.0+ / PostgreSQL) 直接在庫裡構建

遞歸版對比(僅作教學參考,勿生產用)

function buildTreeRecursive($items, $pid = 0) { 
    $tree = []; 
    foreach ($items as $item) { 
        if ($item['pid'] == $pid) { 
            $item['son'] = buildTreeRecursive($items, $item['id']); 
            $tree[] = $item; 
        } 
    } 
    return $tree; 
} 
// 缺點:O(n²) 時間、深層棧溢出風險、每層遍歷全量數據

「單次遍歷 + 內存引用」是 PHP 構建樹形結構的標準最優解,掌握後可應用於所有「扁平轉樹」場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved