zoukankan      html  css  js  c++  java
  • 前序遍历树算法实现无限级分类

    分类的话一般用的都是无限极分类,无限极分类的有点是灵活,容易插入,但是在分类量特别大的情况下,使用前序遍历树算法代替无限极分类更好,因为当分类特别多的时候无限极分类的查询是每次都要查询所有,所以前序遍历树算法在此方面的能更好的。当然如果分类涉及经常变更,更改。无限极分类还是有他的有点。在此,分享一个自己的实现类。

    <?php
    /**
    * 前序遍历树算法实现无限极分类
    * @author zaizai
    * @link http://www.tuhuokeji.com
    */
    class Category
    {
    private $tablename = null;
    public function __construct($tablename)
    {
    if(is_null($this->$tablename)){
    $this->tablename = $tablename;
    }
    }
    /**
    * 设置表名
    * @Author   zaizai
    * @DateTime 2016-04-02T11:31:39+0800
    * @param    string                   $tablename [description]
    */
    public function setTbale(string $tablename)
    {
    return $this->tablename = $tablename;
    }
    public function getTable()
    {
    return $this->tablename;
    }
    /**
    * 显示树状结构
    * @Author   zaizai
    * @DateTime 2016-04-02T11:33:33+0800
    * @return   [type]                   [description]
    */
    public function view($pageindex,$pagesize,$where = '')
    {            
    $total = pdo_fetchcolumn('select count(id) from '.tablename($this->tablename).' where id!=1');
    $list = pdo_fetchAll('select * from '.tablename($this->tablename).$where.' order by lft asc  limit ' . ($pageindex - 1) * $pagesize . ',' . $pagesize);
    $pager = pagination($total, $pageindex, $pagesize);
    //两个循环而已,没有递归
    $parent = array();
    $arr_list = array();
    foreach($list as $item){
    if(count($parent)){
    while (count($parent) -1 > 0 && $parent[count($parent) -1]['rgt'] < $item['rgt']){
    array_pop($parent);
    }
    }
    $item['depath'] = count($parent);
    $parent[]  = $item;
    $arr_list[]= $item;
    }
    //显示树状结构
    foreach($arr_list as $k=> $a)
    {
    if($a['id'] != 1 ){
    if($a['depath'] !=1){
    $arr_list[$k]['view'] = str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;", $a['depath']).'|---';
    }
    }else{
    unset($arr_list[$k]);
    }
    }
    return array('list'=>$arr_list,'pager'=>$pager);
    }
    /**
    * 插入操作很简单找到其父节点,之后把左值和右值大于父节点左值的节点的左右值加上2,之后再插入本节点,左右值分别为父节点左值加一和加二
    * @Author   zaizai
    * @DateTime 2016-04-02T11:34:01+0800
    * @param    [type]                   $parent_id [description]
    * @param    [type]                   $data      [description]
    */
    public function add($parent_id,$data)
    {
    $parent_id = empty($parent_id)?1:$parent_id;
    //获取到父级分类的lft rgt
    $parent_category = pdo_get($this->tablename,array('id'=>$parent_id),array('lft','rgt','id'));
    // 1.左值和右值大于父节点左值的节点的左右值加上2
    if(!empty($parent_category)){
    pdo_query('update '.tablename($this->tablename).' set lft=lft+2 where lft >'.$parent_category['lft']);
    pdo_query('update '.tablename($this->tablename).' set rgt=rgt+2 where rgt >'.$parent_category['lft']);
    }
    $data = array_merge(array('lft'=>$parent_category['lft']+1,'rgt'=>$parent_category['lft']+2),$data);
    return pdo_insert($this->tablename,$data);
    }
    /**
    * 删除
    * 
    * #1.得到删除的节点,将右值减去左值然后加1,得到值$width = $rgt - $lft + 1;
    * #2.删除左右值之间的所有节点
    * #3.修改条件为大于本节点右值的所有节点,操作为把他们的左右值都减去$width
    * @Author   zaizai
    * @DateTime 2016-04-02T11:36:44+0800
    * @param    int                   $id 删除的节点id
    * @return   bool                       返回值
    */
    public function delete($id)
    {
    //通过分类id获取分类
    $category = pdo_get($this->tablename,array('id'=>$id),array('id','lft','rgt'));
    //计算$width
    $width = $category['rgt'] - $category['lft'] + 1;
    // 1.删除该条分类
    $res = pdo_delete($this->tablename,array('id'=>$id));
    // 2.删除左右值之间的所有分类
    pdo_query('delete from '.tablename($this->tablename).' where lft>:lft and lft<:rgt and id!=1',array(':lft'=>$category['lft'],':rgt'=>$category['rgt']));
    // 3.修改其它节点的值        
    $res1 = pdo_update($this->tablename,array('lft'=>"lft-{$width}"),array('lft'=>$category['rgt']));
    $res2 = pdo_update($this->tablename,array('rgt'=>"rgt-{$width}"),array('rgt'=>$category['rgt']));
    return $res;
    }
    /**
    * 编辑节点
    * @Author   zaizai
    * @DateTime 2016-04-02T11:34:58+0800
    * @param    int                   $id   节点名称
    * @param    array                   $data 入库的数据
    * @return   bool                         返回值
    */
    public function edit($id,$data)
    {
    //不用说了, 直接通过id编辑
    return pdo_update($this->tablename,$data,array('id'=>$id));
    }
    //获取子孙
    public function getSons($id)
    {
    $item = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$id));
    if($item){
    $sql = 'SELECT `id`,`title`,`lft`,`rgt` FROM '.tablename($this->tablename).' WHERE `lft`>='.$item['lft'].' AND `rgt`<='.$item['rgt'];
    return pdo_fetchAll($sql);
    }
    return false;
    }
    /**
    * 获取子类的直接父类
    * @Author   zaizai
    * @DateTime 2016-05-03T11:00:43+0800
    * @param    int                   $sonid    子类的id  
    * @return   array|false                          直接父类
    */
    public function getParent($sonid)
    {
    $item = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$sonid));
    if($item){
    $sql = 'SELECT `id`,`title`,`lft`,`rgt` FROM '.tablename($this->tablename).' WHERE `lft`<'.$item['lft'].' AND `rgt`>'.$item['rgt'].' order by rgt asc limit 1';
    return pdo_fetch($sql);
    }
    return false;
    }
    /**
    * 获取所有的子类
    * @Author   zaizai
    * @DateTime 2016-05-03T11:00:05+0800
    * @param    int                   $sonid 子类的id
    * @return   array                          所有的父类
    */
    public function getParents($sonid)
    {
    $item = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$sonid));
    if($item){
    $sql = 'SELECT `id`,`title`,`lft`,`rgt` FROM '.tablename($this->tablename).' WHERE `lft`<'.$item['lft'].' AND `rgt`>'.$item['rgt'];
    return pdo_fetchAll($sql);
    }
    return false;
    }
    /**
    * 取出第几级
    * @Author   zaizai
    * @DateTime 2016-05-13T18:07:09+0800
    * @param    [type]                   $depath 层级
    * @return   [type]                           [description]
    */
    public function get_Paret($depath = 1)
    {
    $list = pdo_fetchAll('select * from '.tablename($this->tablename) .' where status=:status  order by lft asc',array(':status'=>0));
    //两个循环而已,没有递归
    $parent = array();
    $arr_list = array();
    foreach($list as $k => $item){
    if(count($parent)){
    while (count($parent) -1 > 0 && $parent[count($parent) -1]['rgt'] < $item['rgt']){
    array_pop($parent);
    }
    }
    $item['depath'] = count($parent);
    $parent[]  = $item;
    $arr_list[]= $item;
    if($item['id'] != 1 ){
    if($item['depath'] == $depath){
    $aa[] = $item;
    //按照sort排序
    foreach ($aa as $key => $row)
    {
    $vals[$key] = $row['sort'];
    }
    array_multisort($vals, SORT_ASC, $aa);
    }
    }else{
    unset($list[$k]);
    }         
    }
    return $aa;
    }
    /**
    * 取出某父级的第几级子级
    * @Author   zaizai
    * @DateTime 2016-05-13T18:07:09+0800
    * @param    [type]                   $depath 层级
    * @return   [type]                           [description]
    */
    public function get_sons_level($id,$depath = 1)
    {
    $abc = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$id));
    if($abc){
    $list = pdo_fetchAll('select * from '.tablename($this->tablename).' WHERE `lft`>='.$abc['lft'].' AND `rgt`<='.$abc['rgt'] .' order by lft asc');
    }
    //两个循环而已,没有递归
    $parent = array();
    $arr_list = array();
    foreach($list as $k => $item){
    if(count($parent)){
    while (count($parent) -1 > 0 && $parent[count($parent) -1]['rgt'] < $item['rgt']){
    array_pop($parent);
    }
    }
    $item['depath'] = count($parent);
    $parent[]  = $item;
    $arr_list[]= $item;
    if($item['id'] != 1 ){
    if($item['depath'] == $depath){
    $aa[] = $item;
    //按照sort排序
    foreach ($aa as $key => $row)
    {
    $vals[$key] = $row['sort'];
    }
    array_multisort($vals, SORT_ASC, $aa);
    }
    }else{
    unset($list[$k]);
    }
    }
    return $aa;
    }
    //测试排序
    public function test_sort($where=''){
    foreach ($this->get_Paret(1) as $v){   //PHP<5.5   用这个
    $parentid[]=$v['id'];
    }
    for ($i=0;$i<count($parentid);$i++){
    $sons[$parentid[$i]]= ($this->get_sons_level($parentid[$i],1));
    }
    foreach ($sons as $k=>$v){
    $sons[$parentid[$k]]=$v[$k];
    }
    foreach ($this->get_Paret(1) as $k=>$v){   //PHP<5.5   用这个
    $parent[]=$v;
    }
    foreach ($this->get_Paret(2) as $v){   //PHP<5.5   用这个
    $sonsid[]=$v['id'];
    }
    for ($i=0;$i<count($sonsid);$i++){
    $sun[$sonsid[$i]]= ($this->get_sons_level($sonsid[$i],1));
    }
    foreach ($sun as $k=>$v){
    $sun[$sonsid[$k]]=$v[$k];
    }
    return  $this->name($parent,$sons,$sun);
    }
    public function name($a,$b,$c)
    {
    $list = array();
    $list[] = $a;
    $list[] = $b;
    $list[] = $c;
    return $list;
    }
    }
  • 相关阅读:
    Linux IO接口 监控 (iostat)
    linux 防火墙 命令
    _CommandPtr 添加参数 0xC0000005: Access violation writing location 0xcccccccc 错误
    Visual Studio自动关闭
    Linux vsftpd 安装 配置
    linux 挂载外部存储设备 (mount)
    myeclipse 9.0 激活 for win7 redhat mac 亲测
    英文操作系统 Myeclipse Console 乱码问题
    Linux 基本操作命令
    linux 查看系统相关 命令
  • 原文地址:https://www.cnblogs.com/gyrgyr/p/6806743.html
Copyright © 2011-2022 走看看