了解无限极分类,首先要确定其数据结构,然后从易到难,分别理解找子结点,找祖先结点,找子孙结点。

数据结构如下:

$arr=array(
array('id'=>1,'name'=>'湖北','parent_id'=>0),
array('id'=>2,'name'=>'武汉','parent_id'=>1),
array('id'=>3,'name'=>'黄冈','parent_id'=>1),
array('id'=>4,'name'=>'江西','parent_id'=>0),
array('id'=>5,'name'=>'黄陂','parent_id'=>2),
array('id'=>6,'name'=>'九江','parent_id'=>4),
array('id'=>7,'name'=>'南昌','parent_id'=>4),
array('id'=>8,'name'=>'研子','parent_id'=>5),
array('id'=>9,'name'=>'罗田','parent_id'=>3));

最终的要效果如下:

湖北
 武汉
  黄陂
   研子
 黄冈
  罗田
江西
 九江
 南昌

现在我们从易到难,首先实现找子结点(直接子结点,不包含孙子结点)。某个结点与其子结点的联系在该结点的id等于子结点的parent_id。

例如给定 array('id'=>1,'name'=>'湖北','parent_id'=>0),其子结点为:

array('id'=>2,'name'=>'武汉','parent_id'=>1)array('id'=>3,'name'=>'黄冈','parent_id'=>1)

按此逻辑,代码如下:

function sontree($arr,$cat_id){
	$son=array();
	foreach ($arr as $k => $v) {
		if($v['parent_id']==$cat_id){
			$son[]=$v;
		}
	}
	return $son;
}

接着来实现找祖先结点,A结点的parent_id等于B结点的id,则B结点是A结点的祖先,依次类推,直到某个祖先结点的parent_id=0时结束。例:A->B->C->D(D的parent_id=0),则A结点的祖先是B->C->D.依此逻辑,代码如下:

function fathertree34($arr,$id){
	$father=array();
	while($id>0){
		foreach ($arr as $k => $v) {
			if($v['cat_id']==$id){
				$father[]=$v;
				$id=$v['parent_id'];
			}
		}
	}
	return $father;
}

最后来实现找子孙结点。前面已经实现了找子结点,子孙结点即在子结点的基础上再找子结点,依次类推,直到没有子结点为止。依此逻辑,我们可以利用递归来实现,代码如下:

function sub_tree($arr,$id,$lev=0){
	static $sub=array();
	foreach ($arr as $k => $v) {
		if($v['parent_id']==$id){
			$v['lev']=$lev;
			$sub[]=$v;
			sub_tree($arr,$v['cat_id'],$lev+1);
		}
	}
	return $sub;
}

$v['lev']=$lev;是用来记录结点在子孙树中的深度。

找子孙结点也可以使用栈来实现,代码如下:

function sub_tree($arr,$id){
	$stack=array();
	$sub=array();

	foreach ($arr as $k => $v) {
		if($v['cat_id']==$id){
			$stack[]=$v;
		}	
	}

	while($stack){
		$row=array_pop($stack);
		$sub[]=$row;
		foreach ($arr as $k => $v) {
		if($v['parent_id']==$row['cat_id']){
			$stack[]=$v;
		}	
	}
	}
	return $sub;
}