说明:

每个数据项都有自己的左值和右值。所有数据的左右值是连续的数字。

① 当右值比左值大1时,表示该数据无子集;

② 当某一数据项的左值大于另一数据项的左值,且该数据项的右值小于同另一数据项的右值时,该数据项属于另一数据项的子集;

例如:中国(1,8) 广东(2,5) 珠海(3,4) 江西(6,7)

数据库表结构:

CREATE TABLE `jd_category` (

`id_category` int(10) NOT NULL AUTO_INCREMENT,

`name` varchar(24) NOT NULL,

`lft` int(10) NOT NULL,

`rgt` int(10) NOT NULL,

`level` tinyint(1) NOT NULL,

`is_del` tinyint(1) NOT NULL,

PRIMARY KEY (`id_category`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

BTreeR只用于实现数据读取:

'level',

'lft' => 'lft',

'rgt' => 'rgt',

);

/**

* 获取虚拟的顶级目录

*/

protected function virtualTop(){

return array(

self::$fieldMap['level'] => -1,

self::$fieldMap['lft'] => -1,

self::$fieldMap['rgt'] => ((int)$this->where($this->condition)->max('rgt') + 1),

);

return $this->obj;

}

// 设置当前对象

public function setObj( $obj ){

if( $obj[ $this->getPk() ] && isset($obj[ self::$fieldMap['lft'] ]) && isset($obj[ self::$fieldMap['rgt'] ]) && isset($obj[ self::$fieldMap['level'] ]) ){

$this->obj = $obj;

}else{

$this->obj = false;

}

return $this;

}

// 设置条件参数

public function setCondition( $condition ){

$this->condition = $condition;

return $this;

}

/**

* 是否存在父节点

*/

public function hasParent(){

if( !$this->obj[ $this->getPk() ] || !$this->obj[ self::$fieldMap['level'] ] ){

return false;

}

return true;

}

/**

* 查询父级节点

*

* @param boolean $width_self 是否包含当前节点

*/

public function parents( $width_self = false ){

if( !$this->obj[ $this->getPk() ] ){

return false;

}

$map = $this->condition;

if( $width_self ){

$map[ self::$fieldMap['lft'] ] = array('elt', $this->obj[ self::$fieldMap['lft'] ]);

$map[ self::$fieldMap['rgt'] ] = array('egt', $this->obj[ self::$fieldMap['rgt'] ]);

}else{

$map[ self::$fieldMap['lft'] ] = array('lt', $this->obj[ self::$fieldMap['lft'] ]);

$map[ self::$fieldMap['rgt'] ] = array('gt', $this->obj[ self::$fieldMap['rgt'] ]);

}

$this->where($map)->order( self::$fieldMap['lft'].' asc' );

return $this;

}

/**

* 是否存在子节点

*/

public function hasSub(){

if( $this->obj[ $this->getPk() ] && ($this->obj[ self::$fieldMap['rgt'] ] - $this->obj[ self::$fieldMap['lft'] ] == 1) ){

return false;

}

return true;

}

/**

* 查询子节点

* @param boolean $width_self 是否包含当前节点

*/

public function subs( $width_self = false ){

$map = $this->condition;

if( $this->obj[ $this->getPk() ] ){

if( $width_self ){

$map[ self::$fieldMap['lft'] ] = array('egt', $this->obj[ self::$fieldMap['lft'] ]);

$map[ self::$fieldMap['rgt'] ] = array('elt', $this->obj[ self::$fieldMap['rgt'] ]);

}else{

$map[ self::$fieldMap['lft'] ] = array('gt', $this->obj[ self::$fieldMap['lft'] ]);

$map[ self::$fieldMap['rgt'] ] = array('lt', $this->obj[ self::$fieldMap['rgt'] ]);

}

}

$this->where($map)->order( self::$fieldMap['lft'].' asc' );

return $this;

}

/**

* 把返回的数据集转换成Tree

* @param array $list 数据集合

* @param string $child 存放子集的key

*/

public function toTree($list, $child = '_child' ){

// TODO

}

}

?>

BTreeW继承子 BtreeR,用于实现数据操作:

condition;

if( !$this->obj[ $this->getPk() ] ){

$this->obj = $this->virtualTop();

}

$lft = $this->obj[ self::$fieldMap['rgt'] ];

$data[ self::$fieldMap['level'] ] = $this->obj[ self::$fieldMap['level'] ] + 1;

$data[ self::$fieldMap['lft'] ] = $lft;

$data[ self::$fieldMap['rgt'] ] = $lft + 1;

$this->startTrans();

$insert_id = $this->add($data);

if( !$insert_id ){

$this->rollback();

return false;

}

$map = $this->condition;

$map[ self::$fieldMap['lft'] ] = array('gt', $lft);

$res = $this->where( $map )->setInc( self::$fieldMap['lft'], 2 );

if( false === $res ){

$this->rollback();

return false;

}

$map = $this->condition;

$map[ $this->getPk() ] = array('neq', $insert_id);

$map[ self::$fieldMap['rgt'] ] = array('egt', $lft);

$res = $this->where( $map )->setInc( self::$fieldMap['rgt'], 2 );

if( false === $res ){

$this->rollback();

return false;

}

$this->commit();

return true;

}

/**

* 删除节点及所有子节点

* ① 删除当前节点及其所有子节点

* ② 更改父级右值-$move_count,更改父级右边记录左右值-$move_count

*

* @param string $field 标识删除的字段名

* @param int $value 标识删除的字段值

* @return array 所有删除的节点ID集

*/

public function delInBTree( $field = false, $value = 1 ) {

if( !$this->obj[ $this->getPk() ] ){

return false;

}

$map = $this->condition;

if( $this->obj[ self::$fieldMap['rgt'] ] - $this->obj[ self::$fieldMap['lft'] ] == 1 ){

$del_ids = $this->obj[ $this->getPk() ];

}else{

$map[ self::$fieldMap['lft'] ] = array('egt', $this->obj[ self::$fieldMap['lft'] ]);

$map[ self::$fieldMap['rgt'] ] = array('elt', $this->obj[ self::$fieldMap['rgt'] ]);

$del_ids = $this->where($map)->getField( $this->getPk(), true );

}

if( !$del_ids ){

return false;

}

$this->startTrans();

$this->where(array( $this->getPk() => array('in', $del_ids) ));

if($field){

$res = $this->setField( $field, $value );

}else{

$res = $this->delete();

}

if( !$res ){

$this->rollback();

return false;

}

$move_count = $this->obj[ self::$fieldMap['rgt'] ] - $this->obj[ self::$fieldMap['lft'] ] + 1;

$map = $this->condition;

$map[ self::$fieldMap['lft'] ] = array('gt', $this->obj[ self::$fieldMap['rgt'] ]);

$res = $this->where( $map )->setDec( self::$fieldMap['lft'], $move_count );

if( false === $res ){

$this->rollback();

return false;

}

$map = $this->condition;

$map[ self::$fieldMap['rgt'] ] = array('gt', $this->obj[ self::$fieldMap['rgt'] ]);

$res = $this->where( $map )->setDec( self::$fieldMap['rgt'], $move_count );

if( false === $res ){

$this->rollback();

return false;

}

$this->commit();

return $del_ids;

}

/**

* 节点左右移动

* ① 确定右左移动的节点

* ② 左节点集向右移动$r_move_count

* ③ 右节点集向左移动$l_move_count

*

* @param boolean $move_lft 是否是左移

*/

public function moveLOrRInBTree($move_lft = true){

if( !$this->obj[ $this->getPk() ] ){

return false;

}

$map = $this->condition;

$fields = $this->getPk().','.implode(',', self::$fieldMap);

if( $move_lft ){

$map[ self::$fieldMap['rgt'] ] = $this->obj[ self::$fieldMap['lft'] ] - 1;

$lft = $this->field($fields)->where($map)->find();

$rgt = $this->obj;

}else{

$lft = $this->obj;

$map[ self::$fieldMap['lft'] ] = $this->obj[ self::$fieldMap['rgt'] ] + 1;

$rgt = $this->field($fields)->where($map)->find();

}

if( !$lft || !$rgt ){

return false;

}

$l_move_count = $lft[ self::$fieldMap['rgt'] ] - $lft[ self::$fieldMap['lft'] ] + 1;

$r_move_count = $rgt[ self::$fieldMap['rgt'] ] - $rgt[ self::$fieldMap['lft'] ] + 1;

// 查询需要需要移动的ID集

$map = $this->condition;

if( $lft[ self::$fieldMap['rgt'] ] - $lft[ self::$fieldMap['lft'] ] == 1 ){

$lft_ids = $lft[ $this->getPk() ];

}else{

$map[ self::$fieldMap['lft'] ] = array('egt', $lft[ self::$fieldMap['lft'] ]);

$map[ self::$fieldMap['rgt'] ] = array('elt', $lft[ self::$fieldMap['rgt'] ]);

$lft_ids = $this->where($map)->getField( $this->getPk(), true );

}

if( $rgt[ self::$fieldMap['rgt'] ] - $rgt[ self::$fieldMap['lft'] ] == 1 ){

$rgt_ids = $rgt[ $this->getPk() ];

}else{

$map[ self::$fieldMap['lft'] ] = array('egt', $rgt[ self::$fieldMap['lft'] ]);

$map[ self::$fieldMap['rgt'] ] = array('elt', $rgt[ self::$fieldMap['rgt'] ]);

$rgt_ids = $this->where($map)->getField( $this->getPk(), true );

}

// 执行移动

$this->startTrans();

$res = $this->where( array($this->getPk() => array('in', $lft_ids)) )->save( array(

self::$fieldMap['lft'] => array('exp', self::$fieldMap['lft'].'+'.$r_move_count),

self::$fieldMap['rgt'] => array('exp', self::$fieldMap['rgt'].'+'.$r_move_count),

) );

if( false === $res ){

$this->rollback();

return false;

}

$res = $this->where( array($this->getPk() => array('in', $rgt_ids)) )->save( array(

self::$fieldMap['lft'] => array('exp', self::$fieldMap['lft'].'-'.$l_move_count),

self::$fieldMap['rgt'] => array('exp', self::$fieldMap['rgt'].'-'.$l_move_count),

) );

if( false === $res ){

$this->rollback();

return false;

}

$this->commit();

return true;

}

// TODO

public function moveLevelInBTree(){

}

}

?>

php左右值实现无限极分类,基于ThinkPHP的二叉树左右值无限极分类实现相关推荐

  1. php 自减函数,Thinkphp中某个字段值从增或自减函数

    Thinkphp中某个字段值自增或自减函数 Thinkphp中某个字段值自增或自减函数,可以用于文章的浏览量 /** +---------------------- * 某个字段值自增或自减 +--- ...

  2. KNN分类器、最近邻分类、KD树、KNN分类的最佳K值、基于半径的最近邻分类器、KNN多分类、KNN多标签分类、KNN多输出分类、KNN分类的优缺点

    KNN分类器.最近邻分类.KD树.KNN分类的最佳K值.基于半径的最近邻分类器.KNN多分类.KNN多标签分类.KNN多输出分类.KNN分类的优缺点 目录

  3. 【图像去噪】基于matlab GUI butterworth+中值+维纳+小波图像去噪【含Matlab源码 520期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[图像去噪]基于matlab GUI butterworth+中值+维纳+小波图像去噪[含Matlab源码 520期] 获取代码方式2: ...

  4. 阅读笔记3:基于深度学习的运动想象脑电信号分类算法研究

    1.论文信息 题目:基于深度学习的运动想象脑电信号分类算法研究 作者佟歌 单位:哈尔滨工程大学控制科学与工程 发表时间:201803 2.笔记 2.1 脑电信号采集及预处理 2.1.1脑电信号分析方法 ...

  5. 基于哈里斯鹰算法的极限学习机(ELM)分类算法-附代码

    基于哈里斯鹰算法的极限学习机(ELM)分类算法 文章目录 基于哈里斯鹰算法的极限学习机(ELM)分类算法 1.极限学习机原理概述 2.ELM学习算法 3.分类问题 4.基于哈里斯鹰算法优化的ELM 5 ...

  6. 基于k近邻算法的干豆品种分类

    摘 要 近年来,干豆由于其较高的营养价值和良好的口感越来越受到人们的欢迎.其种类繁多且易于种植,是世界食用作物中产量最高的一种.干豆品种分类对干豆培育方向.产量需求和品质改良具有重要意义.本文以k近邻 ...

  7. 基于粒子群算法的极限学习机(ELM)分类算法-附代码

    基于粒子群算法的极限学习机(ELM)分类算法 文章目录 基于粒子群算法的极限学习机(ELM)分类算法 1.极限学习机原理概述 2.ELM学习算法 3.分类问题 4.基于粒子群算法优化的ELM 5.测试 ...

  8. input自适应_【正点原子FPGA连载】第十一章基于OV5640的自适应二值化实验-领航者ZYNQ之HLS 开发指南...

    1)摘自[正点原子]领航者ZYNQ之HLS 开发指南 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手 ...

  9. 【图像去噪】基于matlab GUI均值+中值滤波图像去噪(含PNSR)【含Matlab源码 372期】

    ⛄一.图像去噪及滤波简介 1 图像去噪 1.1 图像噪声定义 噪声是干扰图像视觉效果的重要因素,图像去噪是指减少图像中噪声的过程.噪声分类有三种:加性噪声,乘性噪声和量化噪声.我们用f(x,y)表示图 ...

最新文章

  1. UVa 10701 - Pre, in and post
  2. linux大爱版本Vinux 盲人也能用的OS
  3. spring boot 启动 nested exception is java.lang.IllegalStateException
  4. iOS--动画demo--Launch Image淡出效果
  5. 寻找数组中只出现一次的数
  6. 关于负载均衡的三种传输模式(反向代理,透传,三角)
  7. 成功解决‘pip‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
  8. 【数据结构与算法】之深入解析“扁平化多级双向链表”的求解思路与算法示例
  9. JS与APP原生控件交互
  10. 遥感水文前景_遥感水文
  11. GMP文件分类与编码管理规程
  12. 您没有权限访问网络计算机,Win7提示“无法访问您可能没有权限使用网络资源”如何解决?...
  13. 什么是数字式射频信号发生器
  14. International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (ECPC 2018)
  15. 镜像站(整理各个镜像站资源)
  16. 大学生PHP个人博客网站源码 简单个人动态网站设计模板 PHP毕业设计成品 学生PHP MYSQL日志管理系统网页
  17. 安全设计:加速传输软件镭速传输安全技术解读
  18. 关于打印机打印网页出现字迹显示不全的问题心得
  19. 师徒结对活动记录表计算机,师徒结对活动记录表一.doc
  20. FireFox必备插件(七)

热门文章

  1. linux驱动之i2c学习
  2. py2exe——.py文件转换成exe
  3. Linux下MySQL的几种安装方式
  4. hashtable、hashmap、ConcurrentHashMap、treemap的区别
  5. EchoesWorks —— 打造下一代技术Blog/Presentation 框架(招兵买马)
  6. Samba服务器配置(1)--源码安装
  7. python获取数据库查询的元数据_Python数据库、MySQL存储引擎、使用分区表、更改表结构、获取数据库元数据...
  8. python网络开发框架_greenev首页、文档和下载 - Python网络服务框架 - OSCHINA - 中文开源技术交流社区...
  9. 壁纸引擎java运行库_Microsoft Windows Desktop Runtime v5.0.0 桌面程序运行库(含常规运行库)...
  10. 2003系统服务器,雨林木风 windows server 2003企业版服务器系统