mysql 使用嵌套集实现无限分类
2014-04-22 15:48
295 查看
参考文章:
1.http://www.2cto.com/database/201303/194971.html
2.http://www.jb51.net/article/28020.htm
实现无线分类的方法还有邻接表,路径枚举,闭包表
创建表:
插入测试数据:
结构图:
思路:树的前序遍历改进算法
1.通过树id查找 一个完成的树
(1)先根据id查找到当前结点的左右值lft,rgt
(2)在查找结点左值(右值)在lft 和rgt之间,并按照lft升序排序
(3)两条相邻的记录的右值如果前一条大于当前条的右值那么前一条为该条记录的父记录
2.给一个结点插入一个字节点
(1).获取该结点的左值lft
(2)更新所有结点的左值,条件是被更新的结点左值大于lft,
(3)跟新所有结点的右值,条件是被更新的结点的右值大于lft
(4)插入当前结点,当前结点的左值为lft+1,右值为lft+2
3.删除一个树
(1).获取结点的左值lft 和右值 rgt 记该树占用的数字个数len = rgt-lft +1;
(2).删除所有左值(右值)在lft和rgt之间的结点
(3).更新其他结点,把其他结点左右值都减去 len(这些左右值大于rgt)
简单的一个实现类:
调用文件:
1.http://www.2cto.com/database/201303/194971.html
2.http://www.jb51.net/article/28020.htm
实现无线分类的方法还有邻接表,路径枚举,闭包表
创建表:
CREATE TABLE nestedCategory( id INT NOT NULL PRIMARY KEY, title VARCHAR(20) NOT NULL, lft INT NOT NULL, rgt INT NOT NULL );
插入测试数据:
insert into `nestedcategory`(`id`,`title`,`lft`,`rgt`) values (1,'Food',1,18),(2,'Fruit',2,11),(3,'Red',3,6),(4,'Cherry',4,5),(5,'Yellow',7,10),(6,'Banana',8,9),(7,'Meat',12,17),(8,'Beef',13,14),(9,'Pork',15,16);
结构图:
思路:树的前序遍历改进算法
1.通过树id查找 一个完成的树
(1)先根据id查找到当前结点的左右值lft,rgt
(2)在查找结点左值(右值)在lft 和rgt之间,并按照lft升序排序
(3)两条相邻的记录的右值如果前一条大于当前条的右值那么前一条为该条记录的父记录
2.给一个结点插入一个字节点
(1).获取该结点的左值lft
(2)更新所有结点的左值,条件是被更新的结点左值大于lft,
(3)跟新所有结点的右值,条件是被更新的结点的右值大于lft
(4)插入当前结点,当前结点的左值为lft+1,右值为lft+2
3.删除一个树
(1).获取结点的左值lft 和右值 rgt 记该树占用的数字个数len = rgt-lft +1;
(2).删除所有左值(右值)在lft和rgt之间的结点
(3).更新其他结点,把其他结点左右值都减去 len(这些左右值大于rgt)
简单的一个实现类:
<?php /** * mysql数据库类别无限分类,嵌套集实现\ * 实现功能不检查错误 * @author prg * @copyright 2014/4/21 */ class nestedCategory { private $db; private $tree; //保存结果树 /** * 连接数据库什么的 */ function __construct() { $this->db = new mysqli('localhost', 'root', '245030109', 'test'); } /** * 根据id获取整棵树 * @param int $id * @return array|flase */ function getTreeByRootID($id) { $query = "select lft,rgt from nestedCategory where id = $id"; $res = $this->db->query($query); if($res->num_rows<=0){ //查找的根节点树不在 return false; } $row = $res->fetch_assoc(); $lft = $row['lft']; //获取左值 $rgt = $row['rgt']; //获取右值 $arrayRight = array(); //记录每个节点的又值便于分出父子关系 $query = "select * from nestedCategory where lft>=$lft and rgt <= $rgt order by lft "; $res = $this->db->query($query); for($i=0;$i<$res->num_rows;$i++){ $row = $res->fetch_assoc(); while(!empty($arrayRight)&&end($arrayRight)<$row['rgt']){ //相邻的两条记录的右值第一条的右值比第二条的大那么就是他的父类 //不是父类出栈 array_pop($arrayRight); } $tiltle = $row['title']; if(!empty($arrayRight)){ //$tiltle = '|-'.$tiltle; } //这里设置节点在树中的层数没有- 表示 根节点 $this->tree[] = array('title'=>str_repeat('-', count($arrayRight)).$tiltle); $arrayRight[] = $row['rgt']; } return $this->tree; } /** * 为某个父节点添加一个子节点 * //这里一般创建存储过程 * @param int $parentId * @param int $selfId * @param string $title */ function addNodeByPid($parentId,$selfId,$title='default') { $query = "select lft from nestedCategory where id = $parentId"; $res = $this->db->query($query); if($res->num_rows<=0){ return false; } $row = $res->fetch_assoc(); $lft = $row['lft']; //更新左值大于该父节点左值的值 $query = "update nestedCategory set lft = lft+ 2 where lft>$lft"; $res = $this->db->query($query); if(!$res){ return false; } //更新右值大于该父节点左值的值 $query = "update nestedCategory set rgt = rgt+ 2 where rgt>$lft"; $res = $this->db->query($query); if(!$res){ return false; } //插入节点 $query = "insert into nestedCategory values($selfId,'".$title."',".($lft+1).','.($lft+2).')'; $res = $this->db->query($query); if(!$res){ return FALSE; } return true; } /** * 删除一棵树 * @param int $id */ function deleteNodeById($id) { // $query = "select lft,rgt from nestedCategory where id = $id "; $res = $this->db->query($query); if($res->num_rows<=0){ return false; } $row = $res->fetch_assoc(); $dis = $row['rgt']-$row['lft']+1; //删除树 $query = "delete from nestedCategory where lft>=".$row['lft']." and lft<=".$row['rgt']; //删除左值在lft和rgt之间的结点,包括自己 $res = $this->db->query($query); if(!$res){ return false; } //更新其他结点 $query = "update nestedCategory set lft=lft-$dis where lft>".$row['rgt'];//更新左值 $res = $this->db->query($query); if(!$res){ return false; } $query = "update nestedCategory set rgt=rgt-$dis where rgt>".$row['rgt'];//更新右值 $res = $this->db->query($query); if(!$res){ return false; } return true; } /** * 输出树形结构 * @param array $arrayList */ function displayTree(array $arrayList) { foreach ($arrayList as $list){ if(is_array($list)){ foreach ($list as $val){ echo $val,'<br/>'; } }else{ echo $list,'<br/>'; } } } } ?>
调用文件:
<?php require_once 'nestedCategory.php'; $nest = new nestedCategory(); $arrList = $nest->getTreeByRootID(1); $nest->displayTree($arrList); $nest->addNodeByPid(1, 10,'addnode1'); $nest->addNodeByPid(1, 11,'addnode2'); $arrList = $nest->getTreeByRootID(1); $nest->displayTree($arrList); $nest->deleteNodeById(2); ?>
相关文章推荐
- PHP + MySQL 无限分类实现的2种方法
- 使用PHP数组实现无限分类,不使用数据库,不使用递归.
- PHP+MYSQL实现无限级分类管理
- PHP MySQL实现无限级分类|树型显示分类关系
- 使用PHP引用实现无限分类思路(非递归迭代)
- PHP + MySQL 实现无限分类的2种方法
- php+mysql不用递归实现的无限级分类实例(非递归)
- node.js+Mysql实现无限菜单分类
- PHP递归写入MySQL实现无限级分类数据操作示例
- PHP + MYSQL 实现无限分类
- laravel 使用递归实现无限分类(转自oschina姚棉伟原创)
- thinkphp实现无限分类(使用递归)
- php mysql实现无限级分类 | 树型显示分类关系
- 使用TREEVIEW实现无限级分类
- php+mysql不用递归实现的无限级分类实例(非递归)
- 使用ThinkPHP的自动完成实现无限级分类实例详解
- 使用PHP数组实现无限分类,不使用数据库,不使用递归.
- php+mysql实现无限级分类 | 树型显示分类关系
- PHP实现无限级分类(不使用递归)