$data = mysql_....;
  
if($data === false || !isset($data))
exit;
$parents = array(); //记录每一层根的栈
$currentNode = array('children'=>array()); //整棵树的根(注意不是第一个节点,第一个节点会是它的第一个子节点)
$currentRight = 100000000; //保证这个数大于最大的右值,如果从1开始的连续节点,那也就是节点数的两倍。
foreach($data as $d)
{
while($d['lft'] > $currentRight)
{
//新节点不在当前节点内部
//出栈
$pvalue = array_pop($parents);
$pnode = $pvalue['node'];
$pnode['children'][$currentNode['id']] = $currentNode; //换成&$currentNode 使用引用也可以。不想要以id为索引的话,用[]=也可以
$currentNode = $pnode;
$currentRight = $pvalue['right'];
unset($pnode);
unset($pvalue);
}
//新节点在当前节点的内部
//保存当前节点
$parents[] = array('node'=>&$currentNode,'right'=>$currentRight);
$currentNode = array('id'=>$d['id'],'name'=>$d['name'],'children'=>array()); //要不要children分组依个人喜好,把子节点单组列出来遍历的时候比较方便,不用排除掉id和name
$currentRight = $d['rgt'];
}
while(count($parent) > 0)
{
//出栈
$pvalue = array_pop($parents);
$pnode = $pvalue['node'];
$pnode['children'][$currentNode['id']] = $currentNode; //换成&$currentNode 使用引用也可以。不想要以id为索引的话,用[]=也可以
$currentNode = $pnode;
$currentRight = $pvalue['right'];
unset($pnode);
unset($pvalue);
}
$root = $currentNode;
//如果需要第一个节点作为根:
$realroot = array_shift($root['children']);

不考虑PHP内部可能的复制(全用引用)的话,复杂度为O(n)

风吹裤裆毛飞扬 answered 11 years, 10 months ago

Your Answer