一、预排序遍历树结构(MPTT,Modified Preorder Tree Traversal)
要显示树状结构,子节点应该比他们的父节点稍微缩进一些。我们可以通过保存一个右值的一个栈。每次你从一个节点的子节点开始时,你把这个节点的右值添加到栈中。你也知道子节点的右值都比父节点的右值小,这样通过比较当前节点和栈中的前一个节点的右值,你可以判断你是不是在显示这个父节点的子节点。当你显示完这个节点,你就要把他的右值从栈中删除。要获得当前节点的层数,只要数一下栈中的元素。(按照 left排序)
PHP代码:
function toHierarchy($collection)
{
// Trees mapped
$trees = array();
$l = 0;
if (count($collection) > 0) {
// Node Stack. Used to help building the hierarchy
$stack = array();
foreach ($collection as $node) {
$item = $node;
$item['children'] = array();
// Number of stack items
$l = count($stack);
// Check if we're dealing with different levels
while($l > 0 && $stack[$l - 1]['depth'] >= $item['depth']) {
array_pop($stack);
$l--;
}
// Stack is empty (we are inspecting the root)
if ($l == 0) {
// Assigning the root node
$i = count($trees);
$trees[$i] = $item;
$stack[] = & $trees[$i];
} else {
// Add node to parent
$i = count($stack[$l - 1]['children']);
$stack[$l - 1]['children'][$i] = $item;
$stack[] = & $stack[$l - 1]['children'][$i];
}
}
}
return $trees;
}
其他参考文章:www.cnblogs.com/kissdodog/p… mat1.gtimg.com/hb/js/commo…
二、path 数据库结构(领接表增强,比较简单)
id | name | pid | path | level(非必要) | order(非必要) |
1 | 总裁办 | 0 | /0/1/ | 1 | |
3 | 人事部 | 1 | /0/1/3/ | 2 | |
8 | 行政部 | 1 | /0/1/8/ | 2 | |
10 | 招聘一部 | 3 | /0/1/3/10/ | 3 | |
11 | 招聘二部 | 3 | /0/1/3/11/ | 3 | |
12 | 招聘专员 | 11 | /0/1/3/11/12/ | 4 | |
2 | 财务部 | 0 | /0/2/ | 1 | |
15 | 出纳 | 2 | /0/2/15/ | 2 | |
16 | 会计 | 2 | /0/2/16/ | 2 | |
9 | 技术部 | 0 | /0/9/ | 1 |
缺点:
- 树的级别会受「path」字段长度的限制,但是应付一般tree足矣,如果「path」为「varchar(255)」,20级树完全没有问题;
- 修改某节点父级时,其下属「path」、「level」均需要重新改变;
- 查询子孙集时,通过「LIKE %/{$id}/%」查询比较低效,但是相对于递归查询来说,效率已经算是不错了。