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

PHP 無限級分類生成樹結構:引用賦值的極致優雅

     編輯:PHP 相關知識

告別遞歸遍歷:O(n) 單次遍歷建樹

傳統遞歸查詢資料庫、遞歸組裝樹形結構,不僅效率低、記憶體消耗大,還容易超過最大遞歸深度。利用 PHP 陣列引用特性,一次遍歷即可構建完整樹結構,效能提升數量級。

核心算法(標準版)

<?php
function generateTree(array $items): array {
    $tree = [];
    foreach ($items as $item) {
        // 關鍵:使用引用 &$items[$item['id']] 確保父子關聯同步更新
        if (isset($items[$item['pid']])) {
            $items[$item['pid']]['son'][] = &$items[$item['id']];
        } else {
            $tree[] = &$items[$item['id']];
        }
    }
    return $tree;
}

// 測試資料:id 為鍵值,方便 O(1) 查找父節點
$items = [
    1 => ['id' => 1, 'pid' => 0, 'name' => '安徽省'],
    2 => ['id' => 2, 'pid' => 0, 'name' => '浙江省'],
    3 => ['id' => 3, 'pid' => 1, 'name' => '合肥市'],
    4 => ['id' => 4, 'pid' => 3, 'name' => '長豐縣'],
    5 => ['id' => 5, 'pid' => 1, 'name' => '安慶市'],
];

$tree = generateTree($items);
print_r($tree);

輸出結構

Array
(
    [0] => Array
        (
            [id] => 1
            [pid] => 0
            [name] => 安徽省
            [son] => Array
                (
                    [0] => Array
                        (
                            [id] => 3
                            [pid] => 1
                            [name] => 合肥市
                            [son] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 4
                                            [pid] => 3
                                            [name] => 長豐縣
                                        )
                                )
                        )
                    [1] => Array
                        (
                            [id] => 5
                            [pid] => 1
                            [name] => 安慶市
                        )
                )
        )
    [1] => Array
        (
            [id] => 2
            [pid] => 0
            [name] => 浙江省
        )
)

極致精簡版(5 行)

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

原理:以 pid=0 作為虛擬根節點,所有頂層節點掛在 $items[0]['son'] 下。

前提條件與注意事項

  • 輸入陣列必須以 id 為鍵:$items[$id] = [...,確保 $items[$pid] 為 O(1) 查找。
  • 資料順序無關:子節點可先於父節點出現,引用機制自動關聯。
  • 記憶體效率:樹節點與原始陣列共享記憶體(引用),無重複複製。
  • 根節點 pid:約定為 0 或 null,不存在於實際資料中。

樹形資料的輸出/遍利用(仍需遞歸)

<?php
function printTree(array $tree, int $depth = 0): void {
    foreach ($tree as $node) {
        echo str_repeat('  ', $depth) . $node['name'] . "\n";
        if (!empty($node['son'])) {
            printTree($node['son'], $depth + 1);
        }
    }
}

printTree($tree);
/*
安徽省
  合肥市
    長豐縣
  安慶市
浙江省
*/

實戰應用場景

  • 後台選單/權限樹構建
  • 商品分類、地區選擇器
  • 組織架構、評論回覆巢狀結構
  • API 回傳樹形 JSON(配合 json_encode 自動處理引用)

此演算法廣泛應用於 Laravel、ThinkPHP 等框架的樹形構建工具中,是處理無限級分類的標準解法。

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