PHP+mysql 无限级分类算法

来源:互联网 发布:node.js开发指南 mobi 编辑:程序博客网 时间:2024/06/06 01:28

   关于这个无限级分类的算法一直很纠结,看了很多方法,各有个的优缺点。很难的兼顾到各个方面,我主要考虑了2个方法,一种就是非常常用的通过递归方法得到的无限级分类。还有一种就是树形结构的算法。

一。递归算法

    这种算法一般用得比较多,主要通过两个字段,本身ID和父类ID值PID两个字段来关联。

贴一段自己写的代码:

function getAllChildNav($id){
        $sql = "SELECT a.nav_title a_title, a.id a_id,b.id b_id, b.nav_title b_titleFROM (SELECT nav_title, url, id FROM nav WHERE pid='{$id}' AND deleted = 0 ORDER BY ord ASC) a LEFT JOIN
                (SELECT * FROM nav WHERE deleted = 0 ORDER BY ord ASC) b
                ON a.id = b.pid ";
        $result = $this->getAll($sql);

      
        foreach($result as $value){
            if ($id != $value['a_id']){
                $id = $value['a_id'];
                $child = array();
                foreach($result as $v){
                    if ($value['a_id'] == $v['a_id'] && $v['b_title']){
                        $c['nav_title'] = $v['b_title'];
                        $c['id'] = $v['b_id'];

                        $c['child'] = getChild($c['id']);

                        $child[] = $c;
                    }
                }
                $p['nav_title'] = $value['a_title'];
                $p['id'] = $value['a_id'];
                $p['child'] = $child;
                $nav[] = $p;
            }
        }
        return $nav;
    }

function getChild($id){
        $sql = "SELECT * FROM duke_nav WHERE pid = '{$id}' AND deleted = 0";
        $result = $this->db->getAll($sql);
        if (!empty($result)){
            foreach ($result as $value){
                $c = $value;
                $c['child'] = $this->getChild($value['id']);
                $re[] = $c;
            }
            return $re;
        }else{
            return $result;
        }
    }

这样写每执行一次getAllChildNav()方法就会执行一次SQL语句操作,每执行一次能够查询出两层结构的数据。这种方法的特点就是查询的时候很不方便,但是对数据的修改插入等相对较容易。

二。采用树形结构前序遍历算法。

首先COPY一下网上找的介绍。

原 理:

  我们先把树按照水平方式摆开。从根节点开始(“Food”),然后他的左边写上1。然后按照树的顺序(从上到下)给“Fruit”的左边写上2。这样,你沿着树的边界走啊走(这就是“遍历”),然后同时在每个节点的左边和右边写上数字。最后,我们回到了根节点“Food”在右边写上18。下面是标上了数字的树,同时把遍历的顺序用箭头标出来了。

  我们称这些数字为左值和右值(如,“Food”的左值是1,右值是18)。正如你所见,这些数字按时了每个节点之间的关系。因为“Red”有3和6两个值,所以,它是有拥有1-18值的“Food”节点的后续。同样的,我们可以推断所有左值大于2并且右值小于11的节点,都是有2-11的“Fruit” 节点的后续。这样,树的结构就通过左值和右值储存下来了。这种数遍整棵树算节点的方法叫做“改进前序遍历树”算法。

数据查询:

        当我们需要查询某个节点下的所有子节点时,只需要先查询出他的左右值,然后找到左值比父节点左值大,右值比父节点小的所有节点就是其子孙节点。

        这样的话所有的分类都出来了,但是谁是谁的子类却分不清,那么怎么办呢?我们仔细看图不难发现如果相邻的两条记录的右值第一条的右值比第二条的大那么就是他的父类,比如food的右值是18而fruit的右值是11 那么food是fruit的父类,但是又要考虑到多级目录。于是有了这样的设计,我们用一个数组来存储上一条记录的右值,再把它和本条记录的右值比较,如果前者比后者小,说明不是父子关系,就用array_pop弹出数组,否则就保留,之后根据数组的大小来打印空格。这样就解决了这个问题。


插入新节点:

     当我们插入新节点的时候,需要把左右值比其父节点的左右值都大的节点的左右值加2,然后再找到左节点比插入数据小,右值比插入数据大的节点的节点值右值+2,左值比插入节点左值大,右值比插入节点值小的节点 右值小的 +1;


删除节点:

       需要把左右值比其父节点的左右值都大的节点的左右值-2,然后再找到左节点比插入数据小,右值比插入数据大的节点的节点值右值-2,左值比插入节点左值大,右值比插入节点值小的节点 右值小的 -1;

     


原创粉丝点击