一个很精妙的树生成代码

这是一段很好的树结构数据生成代码,摘自www.phpe.net,由xuzuning@phpe.net 所写。

很有学习价值,不过补充说明一下这段代码的前提是所有项目的pid>id,如果不符合这个前提,会导致结果出错。

受这段代码的启示,我后来写了一个新的实现方式,在pid大于id是情况也能工作


1,pid=>0),
array(id=>2,pid=>0),
array(id=>3,pid=>2),
array(id=>4,pid=>0),
array(id=>5,pid=>3),
array(id=>6,pid=>1),
array(id=>7,pid=>1),
array(id=>8,pid=>6),
array(id=>9,pid=>7),
array(id=>10,pid=>9)
);

//排序函数
function cmd($a,$b) {
if($a[pid]==$b[pid]) return 0;
return $a[pid]>$b[pid]?1:-1;
}

//排序,为避免数据中父节点在子节点后面出现,这种情况在多次修改数据后经常会发生的
//排序的目的就是防止这种情况造成的混乱
uasort($ar,cmd);

//定义目标数组
$d = array();
//定义索引数组,用于记录节点在目标数组的位置
$ind = array();

foreach($ar as $v) {
$v[child] = array(); //给每个节点附加一个child项
if($v[pid] == 0) {
$i = count($d);
$d[$i] = $v;
$ind[$v[id]] =& $d[$i];
}else {
$i = count($ind[$v[pid]][child]);
$ind[$v[pid]][child][$i] = $v;
$ind[$v[id]] =& $ind[$v[pid]][child][$i];
}
}
//检查结果
print_r($d);
?>


/**
* 这个函数是放在一类中的,名字叫TarrayTree
* $this->arrData 是数据存储数组,用id和pid的方式记录树结构,
* col_id 和col_pid分别id 和 pid的字段名称
* col_childs 是用来放子节点的字段名称
/**
* 初始化树的结构数据
* 1.根据col_id建立索引
* 2.建立父子关系连接(引用)
* 3.根据树结构进行平面化排序和其它数据初始化(删减了)
*/
function buildTree(){
//build key index
//这个地方是为了用数组的key的同步id,感觉还是不理想,有个复制的过程,数据量很大的话可以会影响性能,不知道还有没有其它好办法,也许可以直接用一个引用表来记录id索引,
$ar = $this->arrData;
$this->arrData = array();
foreach ($ar as $v){
$v[$this->col_childs] = array();
$this->arrData[$v[$this->col_id]] = $v;
}
unset($ar);

//link childs
foreach ($this->arrData as $k=>$v){
if(isset($this->arrData[$v[$this->col_pid]]) and $v[$this->col_pid] <> $k){
$this->arrData[$v[$this->col_pid]][$this->col_childs][] = &$this->arrData[$k];
}else{
$this->roots[$k] = &$this->arrData[$k];
}
}
}

发表评论