PHP实现无限极分类的两种方式示例【递归和引用方式】
本文实例讲述了PHP实现无限极分类的两种方式。分享给大家供大家参考,具体如下:
面试的时候被问到无限极分类的设计和实现,比较常见的做法是在建表的时候,增加一个PID字段用来区别自己所属的分类
$array=array(
array('id'=>1,'pid'=>0,'name'=>'河北省'),
array('id'=>2,'pid'=>0,'name'=>'北京市'),
array('id'=>3,'pid'=>1,'name'=>'邯郸市'),
array('id'=>4,'pid'=>2,'name'=>'朝阳区'),
array('id'=>5,'pid'=>2,'name'=>'通州区'),
array('id'=>6,'pid'=>4,'name'=>'望京'),
array('id'=>7,'pid'=>4,'name'=>'酒仙桥'),
array('id'=>8,'pid'=>3,'name'=>'永年区'),
array('id'=>9,'pid'=>1,'name'=>'武安市'),
);
数据在数据库中存储大概是这个样子,怎么实现无限极递归呢,有两种常用的做法,递归和引用算法
递归算法
/**
*递归实现无限极分类
*@param$array分类数据
*@param$pid父ID
*@param$level分类级别
*@return$list分好类的数组直接遍历即可$level可以用来遍历缩进
*/
functiongetTree($array,$pid=0,$level=0){
//声明静态数组,避免递归调用时,多次声明导致数组覆盖
static$list=[];
foreach($arrayas$key=>$value){
//第一次遍历,找到父节点为根节点的节点也就是pid=0的节点
if($value['pid']==$pid){
//父节点为根节点的节点,级别为0,也就是第一级
$value['level']=$level;
//把数组放到list中
$list[]=$value;
//把这个节点从数组中移除,减少后续递归消耗
unset($array[$key]);
//开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
getTree($array,$value['id'],$level+1);
}
}
return$list;
}
/*
*获得递归完的数据,遍历生成分类
*/
$array=getTree($array);
foreach($array)as$value{
echostr_repeat('--',$value['level']),$value['name'].'
';
}
输出结果无限极分类实现ok
河北省
--邯郸市
----永年区
--武安市
北京市
--朝阳区
----望京
----酒仙桥
--通州区
引用算法
functiongenerateTree($array){
//第一步构造数据
$items=array();
foreach($arrayas$value){
$items[$value['id']]=$value;
}
//第二部遍历数据生成树状结构
$tree=array();
foreach($itemsas$key=>$value){
if(isset($items[$item['pid']])){
$items[$item['pid']]['son'][]=&$items[$key];
}else{
$tree[]=&$items[$key];
}
}
return$tree;
}
//经过第一步数据变成了这样
Array
(
[1]=>Array
(
[id]=>1
[pid]=>0
[name]=>河北省
[children]=>Array
(
)
)
[2]=>Array
(
[id]=>2
[pid]=>0
[name]=>北京市
[children]=>Array
(
)
)
[3]=>Array
(
[id]=>3
[pid]=>1
[name]=>邯郸市
[children]=>Array
(
)
)
[4]=>Array
(
[id]=>4
[pid]=>2
[name]=>朝阳区
[children]=>Array
(
)
)
[5]=>Array
(
[id]=>5
[pid]=>2
[name]=>通州区
[children]=>Array
(
)
)
[6]=>Array
(
[id]=>6
[pid]=>4
[name]=>望京
[children]=>Array
(
)
)
[7]=>Array
(
[id]=>7
[pid]=>4
[name]=>酒仙桥
[children]=>Array
(
)
)
[8]=>Array
(
[id]=>8
[pid]=>3
[name]=>永年区
[children]=>Array
(
)
)
[9]=>Array
(
[id]=>9
[pid]=>1
[name]=>武安市
[children]=>Array
(
)
)
)
//第一步很容易就能看懂,就是构造数据,现在咱们仔细说一下第二步
$tree=array();
//遍历构造的数据
foreach($itemsas$key=>$value){
//如果pid这个节点存在
if(isset($items[$value['pid']])){
//把当前的$value放到pid节点的son中注意这里传递的是引用为什么呢?
$items[$value['pid']]['son'][]=&$items[$key];
}else{
$tree[]=&$items[$key];
}
}
//这个方法的核心在于引用,php变量默认的传值方式是按指传递
//也就是说假如说遍历顺序是河北省邯郸市当遍历到河北省时会把河北省放到tree中遍历到邯郸市时会把邯郸市放到河北省的子节点数组中但是!!!这会儿的tree数组中河北省已经放进去了根据php变量按值传递的规则你并没有更改tree数组中的河北省的数据所以这里用到了引用传递
//当你对河北省做更改时,tree数组中的河北省也一并做了更改下面我们做个实验我们把引用传递去掉,看一下结果
//使用普通传值输出结果
Array
(
[0]=>Array
(
[id]=>1
[pid]=>0
[name]=>河北省
)
[1]=>Array
(
[id]=>2
[pid]=>0
[name]=>北京市
)
)
//可以看到只有河北省和北京市输出出来了因为他们俩是第一级节点而且排行1和2,放到$tree数组中之后,没有使用引用传递,那么后续对他俩的子节点的操作都没有在$tree中生效,现在我们更改一下顺序把邯郸市放到河北省的前面那么根据咱们的推断那么邯郸市就应该出现在tree数组里
//邯郸市放到河北省前面的输出结果
Array
(
[0]=>Array
(
[id]=>1
[pid]=>0
[name]=>河北省
[son]=>Array
(
[0]=>Array
(
[id]=>3
[pid]=>1
[name]=>邯郸市
)
)
)
[1]=>Array
(
[id]=>2
[pid]=>0
[name]=>北京市
)
)
//果然是这样那么证明我们的推断是正确的现在我们把引用传值改回去再看一下
//使用引用传值输出结果
Array
(
[1]=>Array
(
[id]=>1
[pid]=>0
[name]=>河北省
[children]=>Array
(
[0]=>Array
(
[id]=>3
[pid]=>1
[name]=>邯郸市
[children]=>Array
(
[0]=>Array
(
[id]=>8
[pid]=>3
[name]=>永年区
)
)
)
[1]=>Array
(
[id]=>9
[pid]=>1
[name]=>武安市
)
)
)
[2]=>Array
(
[id]=>2
[pid]=>0
[name]=>北京市
[children]=>Array
(
[0]=>Array
(
[id]=>4
[pid]=>2
[name]=>朝阳区
[children]=>Array
(
[0]=>Array
(
[id]=>6
[pid]=>4
[name]=>望京
)
[1]=>Array
(
[id]=>7
[pid]=>4
[name]=>酒仙桥
)
)
)
[1]=>Array
(
[id]=>5
[pid]=>2
[name]=>通州区
)
)
)
)
//树状结构完美的输出出来了这个方法的核心就是引用传值
更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP数据结构与算法教程》、《php程序设计算法总结》、《php字符串(string)用法总结》、《PHP数组(Array)操作技巧大全》、《PHP常用遍历算法与技巧总结》及《PHP数学运算技巧总结》
希望本文所述对大家PHP程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。