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

PHP 無限分類排序:陣列資料轉樹狀結構輸出

     編輯:PHP 相關知識

問題場景

資料庫中儲存扁平化的分類資料(如省市區、商品分類),每筆記錄包含 id、parent_id、name。前端需以樹狀結構顯示(縮排層級)。本文示範一種不需遞迴、純陣列運算的排序演算法。

輸入資料格式

$array = [
    0 => ['', '河北'],      // 頂層,parent 為空
    1 => ['', '北京'],
    2 => [0, '保定'],       // parent_id = 0 (河北)
    3 => [1, '海澱'],       // parent_id = 1 (北京)
    4 => [3, '中關村'],     // parent_id = 3 (海澱)
    5 => [2, '涿州'],       // parent_id = 2 (保定)
];

核心演算法 typeArray()

<?php
function typeArray($array) {
    $pathMap = []; // key => '祖先路徑字串'

    // 1. 建立每個節點的完整祖先路徑(以 | 分隔)
    foreach ($array as $k => $v) {
        $parentKey = $v[0];
        if (is_numeric($parentKey)) {
            // 子節點:繼承父節點路徑 + 自己 key
            $pathMap[$k] = ($pathMap[$parentKey] ?? '') . $k . '|';
        } else {
            // 頂層節點:路徑為自己 key
            $pathMap[$k] = $k . '|';
        }
    }

    // 2. 依路徑字串排序(字典序即可保證父節點在前、同層按 key 排序)
    asort($pathMap);

    // 3. 輸出:依路徑中 | 的數量決定縮排層級
    $output = '';
    foreach ($pathMap as $k => $path) {
        $level = substr_count($path, '|') - 1; // 減 1 因結尾多一個 |
        $indent = str_repeat('-', $level);
        $output .= $indent . $array[$k][1] . "\n";
    }
    return $output;
}

echo typeArray($array);
/* 輸出:
河北
-保定
--涿州
北京
-海澱
--中關村
*/
?>

演算法解析

  1. 路徑編碼:將每個節點的祖先鏈編碼為字串 "0|2|5|",父節點路徑必為子節點路徑的前綴。
  2. 字典序排序:asort() 依路徑字串排序,天然保證「父先於子、同層按 key 順序」。
  3. 層級計算:substr_count($path, '|') - 1 即為深度(根節點深度 0)。

優缺點分析

優點缺點
無遞迴,不會爆堆疊 需先載入全部資料到記憶體
單次遍歷 + 排序,時間複雜度 O(n log n) 不支援動態新增/刪除節點即時更新
程式碼極簡,易維護 依賴 key 為數字索引,若為關聯陣列需調整

進階:輸出巢狀陣列(供 JSON/API 使用)

<?php
function buildTree($flat, $parentKey = 0) {
    $tree = [];
    foreach ($flat as $k => $v) {
        if ($v[0] == $parentKey || ($parentKey === 0 && $v[0] === '')) {
            $children = buildTree($flat, $k);
            $node = ['id' => $k, 'name' => $v[1]];
            if ($children) $node['children'] = $children;
            $tree[] = $node;
        }
    }
    return $tree;
}

$tree = buildTree($array);
echo json_encode($tree, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
?>

資料庫查詢優化建議

  • 欄位:id (PK)、parent_id (INDEX)、name、sort_order
  • 一次 SELECT id, parent_id, name, sort_order FROM categories ORDER BY sort_order 撈回全表
  • PHP 端以 typeArray() 或 buildTree() 組裝樹狀結構
  • 大量資料(>萬筆)考慮 Closure Table 或 Nested Set 模型

總結

利用「路徑字串編碼 + 字典序排序」即可將扁平分類資料高效轉為樹狀輸出,無需遞迴查詢資料庫,適合中小型分類系統。若需 API 回傳 JSON,再以遞迴函式組裝巢狀陣列即可。

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