当前位置:首页 > PHP

php实现树

2026-01-13 12:32:49PHP

PHP实现树结构的方法

在PHP中实现树结构通常可以通过递归或迭代的方式完成。以下是几种常见的实现方法:

递归实现树结构

递归是处理树结构的自然方式,尤其适用于具有未知深度的树。

class TreeNode {
    public $data;
    public $children = [];

    public function __construct($data) {
        $this->data = $data;
    }

    public function addChild(TreeNode $node) {
        $this->children[] = $node;
    }
}

function buildTree($data, $parentId = 0) {
    $tree = [];
    foreach ($data as $item) {
        if ($item['parent_id'] == $parentId) {
            $node = new TreeNode($item['id']);
            $children = buildTree($data, $item['id']);
            if ($children) {
                $node->children = $children;
            }
            $tree[] = $node;
        }
    }
    return $tree;
}

使用数组实现树结构

对于简单的树结构,可以直接使用PHP数组来表示。

function buildArrayTree($items, $parentId = 0) {
    $branch = [];
    foreach ($items as $item) {
        if ($item['parent_id'] == $parentId) {
            $children = buildArrayTree($items, $item['id']);
            if ($children) {
                $item['children'] = $children;
            }
            $branch[] = $item;
        }
    }
    return $branch;
}

使用邻接列表模型

邻接列表是数据库中存储树结构的常见方式,可以通过单次查询获取所有节点。

function buildTreeFromAdjacencyList($pdo) {
    $stmt = $pdo->query('SELECT id, parent_id, name FROM tree_nodes');
    $items = $stmt->fetchAll(PDO::FETCH_ASSOC);

    $tree = [];
    $references = [];

    foreach ($items as &$item) {
        $references[$item['id']] = &$item;
        $item['children'] = [];
    }

    foreach ($items as &$item) {
        if ($item['parent_id'] && isset($references[$item['parent_id']])) {
            $references[$item['parent_id']]['children'][] = &$item;
        } else {
            $tree[] = &$item;
        }
    }

    return $tree;
}

使用嵌套集模型

嵌套集模型是另一种数据库存储树结构的方法,查询效率更高但更新较复杂。

function getNestedSetTree($pdo) {
    $stmt = $pdo->query('SELECT id, lft, rgt, name FROM nested_set ORDER BY lft');
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

function displayNestedSetTree($tree, $level = 0) {
    foreach ($tree as $node) {
        echo str_repeat(' ', $level * 4) . $node['name'] . "\n";
        // 这里可以根据lft和rgt值判断是否有子节点
    }
}

使用预排序遍历树算法(MPTT)

MPTT是对嵌套集模型的改进,适合频繁读取但较少更新的场景。

class MPTT {
    private $pdo;
    private $table = 'tree';

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function rebuildTree($parent = 0, $left = 1) {
        $right = $left + 1;
        $stmt = $this->pdo->prepare("SELECT id FROM {$this->table} WHERE parent_id = ?");
        $stmt->execute([$parent]);

        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $right = $this->rebuildTree($row['id'], $right);
        }

        $update = $this->pdo->prepare("UPDATE {$this->table} SET lft = ?, rgt = ? WHERE id = ?");
        $update->execute([$left, $right, $parent]);

        return $right + 1;
    }
}

使用第三方库

对于复杂项目,可以考虑使用专门的树结构处理库:

  1. NestedTree:基于Doctrine的嵌套集实现
  2. TreeBehavior:CakePHP的树行为扩展
  3. baum/baum:Laravel的嵌套集实现
// 使用baum/baum示例
use Baum\Node;

class Category extends Node {
    protected $table = 'categories';
}

// 创建树节点
$root = Category::create(['name' => 'Root']);
$child1 = Category::create(['name' => 'Child 1']);
$child1->makeChildOf($root);

性能考虑

  • 对于深度未知的大型树,递归可能导致栈溢出
  • 邻接列表查询简单但多次查询效率低
  • 嵌套集和MPTT查询高效但更新复杂
  • 考虑使用缓存机制减少数据库查询

以上方法可以根据具体需求选择,小型项目通常使用递归或数组实现,大型项目建议使用数据库优化方案或第三方库。

php实现树

标签: php
分享给朋友:

相关文章

php实现栈

php实现栈

栈的基本概念 栈(Stack)是一种遵循后进先出(LIFO)原则的数据结构。核心操作包括: push:元素入栈。 pop:元素出栈(返回并移除栈顶元素)。 peek:查看栈顶元素(不移…

php长连接实现

php长连接实现

PHP 长连接实现方法 长连接(Keep-Alive)允许客户端与服务器在一次TCP连接中发送和接收多个HTTP请求/响应,减少重复建立连接的开销。以下是PHP中实现长连接的几种方式: 配置HT…

php实现排序

php实现排序

PHP 数组排序方法 PHP 提供了多种内置函数用于数组排序,适用于不同的排序需求。以下是常见的排序方法: 按值升序排序 sort() 函数对数组按值升序排序,重置键名(索引数组适用): $num…

php实现异步

php实现异步

PHP 实现异步的方法 PHP 本身是同步执行的脚本语言,但可以通过以下方法模拟异步操作或实现异步效果: 使用多进程(pcntl_fork) 通过 pcntl_fork 创建子进程实现异步,适用于…

php实现一个

php实现一个

PHP 实现一个简单的计算器 创建一个基本的计算器,支持加、减、乘、除运算。以下是一个完整的实现代码示例: <?php $result = ""; if ($_SERVER["REQUEST_…

php 实现类

php 实现类

PHP 类的基本实现 在 PHP 中,类通过 class 关键字定义,后跟类名和一对花括号。类名通常遵循大驼峰命名法(如 ClassName)。以下是基本语法: class ClassName {…