创建树上每级节点与叶子节点的映射[PHP]

    建立这种映射关系在一些情况下是非常有用的; 在数据库中存层级结构数据 一种最简单的方式就是 id,pid,attributes... id是主键,pid是上级节点id,结构简单但使用起来就会比较麻烦;

    首先,某级节点的子节点或者说后代节点不好查找,查找深度为2以上的父节点 为了效率就需要将所有的数据取出来迭代;虽然有这诸多麻烦,但这种结构维护起来确实非常方便;

    好了,进入正题,问题并不是很麻烦,设想一种情况,多层级分类只有叶子节点关联数据,而需要用户点击一个节点(无论是父级还是叶子)都能取出相关的关联数据,那么建立这种关系放在redis等kv nosql数据库中使用起来就会非常方便,先上代码

private function _createMap(){
    $connection = Yii::app()->db;
    $sql = "SELECT id,pid FROM {{nodes}}";
    $command = $connection->createCommand($sql);
    $dataReader = $command->query();      
    $rows = array();
    //struct 子节点 => 父节点
    foreach($dataReader as $row){
        $rows[$row['id']] = $row['pid'];
    }
    $map = array();
    while(!empty($rows)){
        foreach($rows as $key=>$value){
            if(!in_array($key,$rows)){
                if(!isset($map[$value])) $map[$value] = array();
                if(!empty($map[$key])){
                    $map[$value] = array_merge($map[$value],$map[$key]);
                }else{
                    $map[$value][] = $key;
                }
                unset($rows[$key]);
            }
        }
    }
    foreach($map[0] as $v){
        $map[$v]=array($v);
    }
    unset($map[0]);          
    return $map;
}

这里为了简单直接使用了Yii 的DAO 操作数据库;由于PHP数组的强大秒杀一切LinkedHashMap之类的东东;要充分使用这个优势,

代码中的$rows 是 '子节点'=>'父节点'的数组;$map是最后的结果 '节点'=>array(后代节点中的叶子节点);

下面来一个假设的$rows


$rows =array(
    array('id'=>1,'pid'=>0),
    array('id'=>2,'pid'=>1),
    array('id'=>3,'pid'=>2),
    array('id'=>4,'pid'=>3),
    array('id'=>5,'pid'=>4),
    array('id'=>9,'pid'=>4)
);

每次foreach将会取出$row里id不再pid里面的节点(当前的叶子节点) 存到$map中,然后unset;这样一次while循环之后就会把id为5,9的元素unset在$map中就会增加array(4=>array(5,9));下一次就会是id为4的依次类推,

到这里,你可能就会发现一个问题,就是如果照这样下去$map 只会存在每层节点的子节点而不是后代节点的叶子节点,所以在存到$map之前要先去判断一下这个id在$map中是否存在了,如果有就需要array_merge让其转换为叶子节点,这样问题就解决了;

下面贴出$map的最后结果;


array
(
    4 => array(5,9),
    3 => array(5,9),
    2 => array(5,9),
    1 => array(5,9),
    5 => array(5),
    9 => array(9)
)

$map[0](pid=0)的为根节点 会存整棵树的叶子节点,将这些叶子节点转换为同样的结构便于使用;查询的时候可以根据ID取出ids OR查询(据说会比IN快一些,没有测试过);


问题并不是很复杂,只适用单父节点的树结构上,我觉得以上是创建这种映射比较快的一种方式,希望不会在 玩算法的高手面前贻笑大方;


转载于:https://my.oschina.net/empty125/blog/206116

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值