傳統遞歸查詢資料庫、遞歸組裝樹形結構,不僅效率低、記憶體消耗大,還容易超過最大遞歸深度。利用 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] => 浙江省
)
)
<?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'] 下。
$items[$id] = [...,確保 $items[$pid] 為 O(1) 查找。<?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);
/*
安徽省
合肥市
長豐縣
安慶市
浙江省
*/
json_encode 自動處理引用)此演算法廣泛應用於 Laravel、ThinkPHP 等框架的樹形構建工具中,是處理無限級分類的標準解法。