第一种方案:
使用递归算法,也是使用频率最多的,大部分开源程序也是这么处理,不过一般都只用到四级分类。这种算法的数据库结构设计最为简单。category表中一个字段id,一个字段fid(父id)。这样可以根据WHERE id = fid来判断上一级内容,运用递归至最顶层。
分析:通过这种数据库设计出的无限级,可以说读取的时候相当费劲,所以大部分的程序最多3-4级分类,这就足以满足需求,从而一次性读出所有的数据,再对得到数组或者对象进行递归。本身负荷还是没太大问题。但是如果分类到更多级,那是不可取的办法。
这样看来这种分类有个好处,就是增删改的时候轻松了…然而就二级分类而言,采用这种算法就应该算最优先了。
第二种方案:
设置fid字段类型为varchar,将父类id都集中在这个字段里,用符号隔开,比如:1,3,6
这样可以比较容易得到各上级分类的ID,而且在查询分类下的信息的时候,
可以使用:
SELECT * FROM category WHERE pid LIKE “1,3%”
分析:相比于递归算法,在读取数据方面优势非常大,但是若查找该分类的所有 父分类 或者 子分类 查询的效率也不是很高,至少也要二次query,从某种意义看上,个人觉得不太符合数据库范式的设计。倘若递增到无限级,还需考虑字段是否达到要求,而且在修改分类和转移分类的时候操作将非常麻烦。
暂时,在自己项目中用的就是类似第二种方案的解决办法。就该方案在我的项目中存在这样的问题, 如果当所有数据记录达到上万甚至10W以上后,一次性将所以分类,有序分级的现实出来,效率很低。极有可能是项目处理数据代码效率低带来的。现在正在改良。
第三种方案:
无限级分类----改进前序遍历树
那么理想中的树型结构应具备哪些特点呢?数据存储冗余小、直观性强;方便返回整个树型结构数据;可以很轻松的返回某一子树(方便分层加载);快整获以某节点的祖谱路径;插入、删除、移动节点效率高等等。带着这些需求我查找了很多资料,发现了一种理想的树型结构数据存储及操作算法,改进的前序遍历树模型(The Nested Set Model)。
原 理:
我们先把树按照水平方式摆开。从根节点开始(“Food”),然后他的左边写上1。然后按照树的顺序(从上到下)给“Fruit”的左边写上2。这样,你沿着树的边界走啊走(这就是“遍历”),然后同时在每个节点的左边和右边写上数字。最后,我们回到了根节点“Food”在右边写上18。下面是标上了数字的树,同时把遍历的顺序用箭头标出来了。
MySQL技术:实现无限级分类实现思路
我们称这些数字为左值和右值(如,“Food”的左值是1,右值是18)。正如你所见,这些数字按时了每个节点之间的关系。因为“Red”有3和6两个值,所以,它是有拥有1-18值的“Food”节点的后续。同样的,我们可以推断所有左值大于2并且右值小于11的节点,都是有2-11的“Fruit” 节点的后续。这样,树的结构就通过左值和右值储存下来了。这种数遍整棵树算节点的方法叫做“改进前序遍历树”算法。
表结构设计:
MySQL技术:实现无限级分类实现思路
那么我们怎样才能通过一个SQL语句把所有的分类都查询出来呢,而且要求如果是子类的话前面要打几个空格以表现是子分类。要想查询出所有分类很好办:
SELECT * FROM category WHERE lft>1 AND lft<18 ORDER BY lft
这样的话所有的分类都出来了,但是谁是谁的子类却分不清,那么怎么办呢?我们仔细看图不难发现如果相邻的两条记录的右值第一条的右值比第二条的大那么就是他的父类,比如food的右值是18而fruit的右值是11 那么food是fruit的父类,但是又要考虑到多级目录。于是有了这样的设计,我们用一个数组来存储上一条记录的右值,再把它和本条记录的右值比较,如果前者比后者小,说明不是父子关系,就用array_pop弹出数组,否则就保留,之后根据数组的大小来打印空格。这样就解决了这个问题。代码如下
表结构:
--
-- 表的结构 `category`
--
CREATE TABLE IF NOT EXISTS `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` int(11) NOT NULL COMMENT '1为文章类型2为产品类型3为下载类型',
`title` varchar(50) NOT NULL,
`lft` int(11) NOT NULL,
`rgt` int(11) NOT NULL,
`lorder` int(11) NOT NULL COMMENT '排序',
`create_time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
--
-- 导出表中的数据 `category`
--
INSERT INTO `category` (`id`, `type`, `title`, `lft`, `rgt`, `lorder`, `create_time`) VALUES
(1, 1, '顶级栏目', 1, 18, 1, 1261964806),
(2, 1, '公司简介', 14, 17, 50, 1264586212),
(3, 1, '新闻', 12, 13, 50, 1264586226),
(4, 2, '公司产品', 10, 11, 50, 1264586249),
(5, 1, '荣誉资质', 8, 9, 50, 1264586270),
(6, 3, '资料下载', 6, 7, 50, 1264586295),
(7, 1, '人才招聘', 4, 5, 50, 1264586314),
(8, 1, '留言板', 2, 3, 50, 1264586884),
(9, 1, '总裁', 15, 16, 50, 1267771951);
/**
* 显示树,把所有的节点都显示出来。
* 1、先得到根结点的左右值(默认根节点的title为“顶级目录”)。
* 2、查询左右值在根节点的左右值范围内的记录,并且根据左值排序。
* 3、如果本次记录右值大于前次记录的右值则为子分类,输出时候加空格。
* @return array
**/
function display_tree(){
//获得root左边和右边的值
$arr_lr = $this->category->where("title = '顶级栏目'")->find();
//print_r($arr_lr);
if($arr_lr){
$right = array();
$arr_tree = $this->category->query("SELECT id, type, title, rgt FROM category WHERE lft >= ". $arr_lr['lft'] ." AND lft <=".$arr_lr['rgt']." ORDER BY lft");
foreach($arr_tree as $v){
if(count($right)){
while ($right[count($right) -1] < $v['rgt']){
array_pop($right);
}
}
$title = $v['title'];
if(count($right)){
$title = '|-'.$title;
}
$arr_list[] = array('id' => $v['id'], 'type' => $type, 'title' => str_repeat(' ', count($right)).$title, 'name' =>$v['title']);
$right[] = $v['rgt'];
}
return $arr_list;
}
}
好了 只要这样所有的分类都可以一次性查询出来了,而不用通过递归了。
下面的问题是怎样进行插入、删除和修改操作
插入:插入操作很简单找到其父节点,之后把左值和右值大于父节点左值的节点的左右值加上2,之后再插入本节点,左右值分别为父节点左值加一和加二,可以用一个存储过程来操作:
CREATE PROCEDURE `category_insert_by_parent`(IN pid INT,IN title VARCHAR(20), IN type INT, IN l_order INT, IN pubtime INT)
BEGIN
DECLARE myLeft INT;
SELECT lft into myLeft FROM category WHERE id= pid;
UPDATE qy_category SET rgt = rgt + 2 WHERE rgt > myLeft;
UPDATE qy_category SET lft = lft + 2 WHERE lft > myLeft;
INSERT INTO qy_category(type, title, lft, rgt, lorder, create_time) VALUES(type ,title, myLeft + 1, myLeft + 2, l_order, pubtime);
commit;
END
删除操作
删除的原理:
1.得到要删除节点的左右值,并得到他们的差再加一,@mywidth = @rgt - @lft + 1;
2.删除左右值在本节点之间的节点
3.修改条件为大于本节点右值的所有节点,操作为把他们的左右值都减去@mywidth
存储过程如下:
CREATE PROCEDURE `category_delete_by_key`(IN id INT)
BEGIN
SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
FROM category
WHERE id = id;
DELETE FROM category WHERE lft BETWEEN @myLeft AND @myRight;
UPDATE nested_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft - @myWidth WHERE lft > @myRight;
修改:
要命的修改操作,本人看了很久也没有看出什么规律出来,只要出此下策,先删除再插入,只要调用上面2个存储过程就可以了!
总结:查询方便,但是增删改操作有点繁琐,但是一般分类此类操作不是很多,还是查询用的多,再说弄个存储过程也方便!
第四种方案:
每级分类递增两位数字,这样,每级分类的数目限定在100个之间,分类方法主要为编码法;
示例:
一级分类:01,02,03
二级分类:0101,0102,0103,0201,0202........
三级分类:010101,010102,010103,010104..........
数据库查询时使用 like '01%'就可得到一级分类01下的所有子分类,非常方便!
如果要列出所有分类的树型结构,只需用一条语句select * from pro_class order by code,再稍微处理一下就可。(其中,pro_class为产品分类表,code为类别编码)。
设计的数据库结构如下:
id: 类别id,主键
classname: 类名
classcode: 类别编码
parent: 父id
left_child: 最左孩子id(或第一个孩子)
right_sibling: 右兄弟id
layer: 层级(第一级类别为1,第2级类别2,以此类推)
分享到:
相关推荐
总的来说,"tp树形无限极分类"实例为开发者提供了一个很好的起点,可以帮助他们深入理解无限级分类以及如何在ThinkPHP框架中实现这一功能。对于想要提升PHP Web开发技能,特别是对数据库设计和MVC模式应用的开发者来...
总的来说,ASP.NET无限极分类涉及数据库设计、查询优化、数据结构和算法、前端展示等多个方面,需要综合运用多种技术来实现。理解并掌握这些知识点,对于开发高效且易于维护的Web应用至关重要。
在PHP编程中,无限极分类是一项常见的需求,特别是在构建如菜单、组织结构或者商品分类等系统时。这个压缩包中的内容显然提供了一个高效的方法来处理这类问题,通过递归算法实现无限级分类,并且附带了示例代码...
以上就是"asp产品无限极分类"这一主题的主要知识点,涵盖了ASP编程、无限级分类的实现、数据库操作以及样式设计等方面的内容。在实际应用中,开发者需要根据具体需求调整和优化这些技术,以提供高效且用户友好的分类...
在ThinkPHP5中实现无限极分类,核心是通过递归算法处理数据,并生成树状结构。 ### 无限极分类实现步骤 1. **设计数据库结构**:通常需要两个字段,一个表示分类的主键(cid),另一个表示父分类的外键(pid)。...
在PHP中实现无限极分类,通常涉及到数据库设计和递归算法的应用。 首先,我们需要理解数据库设计。为了支持无限级分类,我们可以使用自引用的方式,即在分类表中有一个字段指向自身,表示父类与子类的关系。这样的...
总结,Java中的无限极树结构涉及节点类的设计、遍历、插入删除操作、数据结构的构建以及在实际应用中的实现。理解这些知识点并熟练运用,对于处理层次关系的数据问题至关重要。在实际项目中,要根据具体需求选择合适...
MySQL 实现无限级分类是一种常见的数据库设计挑战,特别是在需要构建层级结构的数据模型时,例如网站导航菜单、组织架构或商品分类。以下将详细介绍三种常见的无限级分类实现方法,并分析其优缺点。 ### 1. 递归...
在实际应用中,无限极分类的实现需要使用递归算法来构建这种层级结构。在catalog_show()方法中,递归体现在不断调用自身来显示更深层次的子分类。这个过程可以形象地看作是在树状结构中不断下潜,直到叶子节点(即...
实现无限极分类通常需要借助数据库查询和PHP的递归算法。在给定的`Category.class.php`文件中,我们可以预期它包含了一个用于处理分类操作的类。这个类可能提供了以下功能: 1. **读取分类数据**:首先,我们需要从...
- **递归算法**:构建无限级分类目录树的关键,需要理解如何通过递归遍历和构建树形结构。 - **会话管理**:如何在用户会话中保持状态,例如跟踪用户浏览的目录。 - **错误处理和日志记录**:学习如何优雅地处理异常...
在Android开发中,实现...综上所述,"android无限级分类"是一个涉及数据结构、数据库设计、UI组件、数据加载、用户交互等多个方面的复杂功能。在实际开发中,需要综合运用多种技术来实现高效且易用的无限级分类功能。
在IT领域,无限级分类是一种常见的数据组织方式,特别是在数据库设计、文件系统或者网站导航中。无限级分类允许我们创建一个可以无限扩展的层级结构,每个节点都可以有任意数量的子节点,这样的结构通常被称为树形...
面试的时候被问到无限极分类的设计和实现,比较常见的做法是在建表的时候,增加一个PID字段用来区别自己所属的分类 $array = array( array('id' => 1, 'pid' => 0, 'name' => '河北省'), array('id' => 2, 'pid' =>...
在IT行业中,数据库和数据结构的管理是至关...总的来说,PHP实现无限级分类并携带分类路径是一项涉及数据结构、算法和数据库设计的技术任务。理解并掌握这些概念和方法,将有助于我们构建高效、灵活的分类管理系统。
在IT行业中,数据库设计经常会遇到无限级分类的问题,特别是在电商、博客系统等需要层次结构的场景。例如,商品分类、文章目录等。...通过合理的设计和算法,可以有效地解决这些问题,提高系统的效率和用户体验。
描述中提到,这个程序最初是为资源共享而设计,被移植到了ACCESS数据库上。ACCESS是一款轻量级的关系型数据库管理系统,适合小型项目和个人使用。由于它与ASP的集成,使得开发者能够方便地存储、检索和处理数据。...
在ASP中实现无限极分类通常涉及递归算法和数据库设计。开发者需要在数据库中创建一个自关联的类别表,每个类别都有一个父类别ID字段,用于指向上一级类别。当查询时,通过递归遍历这些关系,可以构建出层次分明的...
在PHP中实现无限级分类通常会涉及递归算法,但是递归对性能有一定要求,并且可能受限于调用栈的深度。为了解决这些问题,我们可以采用非递归的方式来实现无限级分类。这种方法在数据库设计中通常采用的是父子结构,...