首页 | PHP资讯 | 技术专栏 | 资源共享 | PHP培训 | PHP职场 | 图书 | PHP ON WIN | PHP圈子
返回列表 回复 发帖

[总结] 父子ID法无限分类的简单实现算法

要不变态点,每个类型加一个字段, 该字段存储当前类型应属的所有前级字段,
按一楼的例子打个比方:
如果是父亲 那么就字段里的数据就是 祖父id,
如果是儿子,那么就字段里的数据就是 祖父id, 父亲id  
:如果是孙子,那么就字段里的数据就是 祖父id, 父亲id ,儿子id

搜索的时候只要字段中有当前类id的出类的出列出来,并查属于该类的数据
这样是不是要快一点,

[ 本帖最后由 zhaofei299 于 2008-9-25 11:00 编辑 ]
永远记住天外有天,人外有人的道理.
保持虚心的学习态度不仅能让你学到更多知识,而且会让你受人尊重.

TOP

回复 31# zhaofei299 的帖子

1、违背SQL设计原则。
2、其中一个分类被删除或移动的话,算法比较复杂。
2007算才入门,2008领会OOP,2009明白Service,2010会是什么呢? —— 十五工作室

TOP

原帖由 七月十五 于 2008-9-25 10:53 发表

还有一个问题,如何有效得取出直系祖先树。

现在把关键技术问题总结一下:
1、已知ID(多个ID?),如何求得后代分类树?及如何显示成树状?
2、已知ID(多个ID?),如何求得后代下所有产品?及如何排序、分 ...


嗯,你把问题抽象成这三大类就没错了。
显示 排序的这些倒不是什么大问题
广交天下程序员好友
我是Muddle
imuddle@hotmail.com

TOP

php默认支持100级的递归
绝大部分分类都够了
PHP对象OOD特设QQ群65050754
形上道也形下器也欲成器者能不学道哉
我常策谈(扯蛋) 详议加群

TOP

我说一下早前我采用的简单办法

1 后代分类ID的取得
    这种实现因为有许多分支,使用数组处理非常难,很难避免使用到递归。
    我的做法是使用递归生成缓存。比如 ID 1 的后代分类有 { 2, 5, 7 ,8, 30} 之类的
    这样的问题存在于对分类进行修改的时候,如何及什么时候更新缓存是关系。

2 取当前后代分类下的所有产品
   比如 ID 1
   从缓存中取得其后代分类  { 2, 5, 7 ,8, 30}
   那么如果是SQL查询产品的话,那就是 分类ID IN ( 1,2, 5, 7 ,8, 30 )。
   所以,这一个解决十分依赖于后代分类ID的取得,应从缓存取得入手。

3 取祖先树(导航)
    这个与问题1类似,这种根据父类ID回逆的查询,是单线路进行的,更容易解决。


这些办法是很初级的,在实际应用中,还会有比如 “各子分类下产品数”一类的问题等等。
多多实践,多多考虑。
1

评分人数

广交天下程序员好友
我是Muddle
imuddle@hotmail.com

TOP

原帖由 Muddle 于 2008-9-25 11:34 发表
我说一下早前我采用的简单办法

1 后代分类ID的取得
    这种实现因为有许多分支,使用数组处理非常难,很难避免使用到递归。
    我的做法是使用递归生成缓存。比如 ID 1 的后代分类有 { 2, 5, 7 ,8, 30} 之类的 ...


1 后代分类ID的取得用数组处理有啥难的?以楼主的数据为例,假设我想要的自己的全部子孙(包括自己)
[php]
    //将数据转化成数组,很容易做到
    $a_list = array(
            1=>array('ID'=>1, 'PARENT'=>0, 'NAME'=>'祖父'),
            2=>array('ID'=>2, 'PARENT'=>1, 'NAME'=>'父亲'),
            3=>array('ID'=>3, 'PARENT'=>1, 'NAME'=>'叔伯'),
            4=>array('ID'=>4, 'PARENT'=>2, 'NAME'=>'自己'),
            5=>array('ID'=>5, 'PARENT'=>4, 'NAME'=>'儿子'),
            6=>array('ID'=>6, 'PARENT'=>5, 'NAME'=>'孙子'),
            7=>array('ID'=>7, 'PARENT'=>2, 'NAME'=>'姐妹'),
            8=>array('ID'=>8, 'PARENT'=>3, 'NAME'=>'表亲'),
            9=>array('ID'=>9, 'PARENT'=>7, 'NAME'=>'甥儿'),
            10=>array('ID'=>10, 'PARENT'=>4, 'NAME'=>'女儿'),
            11=>array('ID'=>11, 'PARENT'=>10, 'NAME'=>'外孙'),
            12=>array('ID'=>12, 'PARENT'=>5, 'NAME'=>'孙女')
            );
        //将数组转变成树,因为使用了引用,所以不会占用太多的内存,一行代码搞定
        foreach ($a_list as $id => $item) if ($item['PARENT']) $a_list[$item['PARENT']][$item['ID']] = &$a_list[$id];
        //获得自己的全部子孙,自己的ID为4
        print_r($a_list[4]);
//结果如下:
/*
Array
(
    [ID] => 4
    [PARENT] => 2
    [NAME] => 自己
    [5] => Array
        (
            [ID] => 5
            [PARENT] => 4
            [NAME] => 儿子
            [6] => Array
                (
                    [ID] => 6
                    [PARENT] => 5
                    [NAME] => 孙子
                )

            [12] => Array
                (
                    [ID] => 12
                    [PARENT] => 5
                    [NAME] => 孙女
                )

        )

    [10] => Array
        (
            [ID] => 10
            [PARENT] => 4
            [NAME] => 女儿
            [11] => Array
                (
                    [ID] => 11
                    [PARENT] => 10
                    [NAME] => 外孙
                )

        )

)

*/
[/php]
1

评分人数

TOP

以下对话可以参考

fleaphp:
这个无限分类在数量多的时候就恼火了,呵呵。  

fleaphp:
【左右值也是无限分类的一种算法。
但是恰好相反,在分类数据量大的时候不推荐。
算法也比较麻烦,添加和编辑一个分类时会涉及到很多分类的改动。
适合数据量小且不经常改动的无限分类。】
正好相反,分类层数和数量都非常多的时候,改进型先序遍历算法具有巨大的优势。
  
七月十五:
哦,这个要研究一下

神仙:
层数会很多吗?通常来说
  
fleaphp:
一般也就3-4层
  
神仙:
所以通常用前缀编码挺好的  

fleaphp:
前缀编码可以搞成 64bit* 2 的,还是能容纳不少数据。
  
七月十五:
左右值、前缀编码、父子ID

fleaphp:
递归其实不是问题。但在递归中查询数据库就是问题了。

七月十五:
明白了

神仙:
分类总量不大的时候,父子id也很好。可以一次性组装好缓存起来 。

七月十五:
先把数据给读出来交给数组,然后对数组操作

fleaphp:
如果分类总量不大,不如全部读出来保存为.php,用的时候include  

七月十五:
关键在于比较多的分类,而且会有动态更新。

fleaphp:
一般都是“读”多于“写” ,分类数据频繁更新的情况比较少见。

[ 本帖最后由 七月十五 于 2008-9-25 12:42 编辑 ]
2007算才入门,2008领会OOP,2009明白Service,2010会是什么呢? —— 十五工作室

TOP

原帖由 七月十五 于 2008-9-25 12:41 发表
fleaphp:
这个无限分类在数量多的时候就恼火了,呵呵。  

fleaphp:
【左右值也是无限分类的一种算法。
但是恰好相反,在分类数据量大的时候不推荐。
算法也比较麻烦,添加和编辑一个分类时会涉及到很多分类 ...

红色标出的话正是我认为楼主的算法中不良的部分。

TOP

没错,一次查询,然后把运算交给PHP去做,PHP的数组很强大
楼上sentrychen对数组的处理就很有经验。
广交天下程序员好友
我是Muddle
imuddle@hotmail.com

TOP

原帖由 sentrychen 于 2008-9-25 12:19 发表


1 后代分类ID的取得用数组处理有啥难的?以楼主的数据为例,假设我想要的自己的全部子孙(包括自己)

    //将数据转化成数组,很容易做到
    $a_list = array(
            1=>array('ID'=>1, 'PARENT'=> ...

这种办法有一个缺点
就是在数组内部会复制许多数据导致重复,最后数组可能会很大

在数据量不大的时候,考虑将分类取出,使用sentrychen的这种办法生成缓存
广交天下程序员好友
我是Muddle
imuddle@hotmail.com

TOP

返回列表