预排序遍历树算法小结

       前几天在项目开发中遇到了前辈们所设计的结构(用来实现商品分类),所设计的结构便是利用了预排序遍历树算法。故特此去查询资料以便掌握该知识点!下面是我这些天的心得体会。

一,商品分类表--建表语句和数据库结构

CREATE  TABLE IF NOT EXISTS `test`.`product_type` (
    `pt_id` INT(11) unsigned NOT NULL AUTO_INCREMENT ,
    `pt_name` varchar(50) NOT NULL COMMENT '分类名称' ,
    `pt_fid` INT(11) unsigned NOT NULL DEFAULT 0 COMMENT '父分类id' ,
    `pt_depth` tinyint(5) NOT NULL DEFAULT 0 COMMENT '分类深度' ,
    `pt_left` INT(11) unsigned NOT NULL DEFAULT 0 COMMENT '节点左侧编号' ,
    `pt_right` INT(11) unsigned NOT NULL DEFAULT 0 COMMENT '节点右侧编号' ,
    PRIMARY KEY (`pt_id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci
COMMENT = '商品分类表';

商品分类表数据结构 .jpg

建表成功后的数据结构

二,预排序遍历树的结构

1.jpg

      当我第一眼看到这个图的时候,我的最大的疑问就是图1.jpg上的那些节点的左右数字编号是如何确定的?为什么B节点的左右编号是2和11?E,F这些节点的左右编号相差1?
      首先我们用手指按照图中红线箭头所示的方向自行描一遍,分别从1赋值到20,明白了没有?(还不明白,那就再描一遍)。从根节点的左侧向下(平行结构时从左到右)数字加1,如:B C D 节点所组成的树。到此,我们可以看出来每个终端节点的左右编号相差为1;一个节点的左编号必定是以该节点为根节点所组成树的编号里面的最小值,而它的右编号必定是最大值,这样才能涵盖它子孙节点的编号变化。

三,所对应的相关算法

      插入数据,将图1.jpg所显示的结构存入数据库中(我们一条条的添加),这样有助于我们更加清晰直观的了解整个树结构的变化。在见到整个结构之前你是不知道1.jpg所示结构的,那么我们按照业务逻辑来的话,商品分类逐级建立,则sql语句应如下:
      //添加一级分类 A
      insert into product_type(pt_name,pt_fid,pt_depth,pt_left,pt_right) values('A',0,1,1,2);
      //A下添加二级分类B  (A的主键已知)
      select * from product_type where pt_id=1;              //得到A的左右编号 1 2 
      select max(pt_right) from product_type where pt_fid = 1;    //得 null ,故A没有子节点
      update product_type set pt_right = pt_right+2 where  pt_right>=2;  //A右编号+2 为B腾出空间
      insert into product_type(pt_name,pt_fid,pt_depth,pt_left,pt_right) values('B',1,2,2,3);
      //B下添加三级分类C (B的主键已知)
      select * from product_type where pt_id=2;              //得到B的左右编号  2 3
      select max(pt_right) from product_type where pt_fid = 2;    //得 null ,故B没有子节点
      update product_type set pt_right = pt_right+2 where  pt_right>=3;  //A,B右编号+2 为C腾出空间 
      insert into product_type(pt_name,pt_fid,pt_depth,pt_left,pt_right) values('C',2,3,3,4);
      //B下添加三级分类D(B的主键已知)
     select * from product_type where pt_id=2;              //得到B的左右编号  2 3
     select max(pt_right) from product_type where pt_fid = 2;    //得 4 ,故D左右为 5 6
     update product_type set pt_right = pt_right+2 where  pt_right > 4;  //A,B右编号+2 为D腾出空间
     insert into product_type(pt_name,pt_fid,pt_depth,pt_left,pt_right) values('D',2,3,5,6);
     ......(好烦,为了页面好看在此省略下面的代码)

     建立好结构后,我们可以很清楚的发现一些规律:

    1. 那我们在查询数据库时where条件为 pt_right - pt_left = 1 的所查询出来的结构必定为终端节点。sql语句如下 :
        select * from product_type where pt_right - pt_left = 1;
    2. 得到某个节点下面的所有子孙节点,只需要where条件 pt_left 大于该节点的左值 and pt_right小于该节点的右值,以b节点举例,则sql语句如下:
        select * from product_type where pt_left>2 and pt_right<11 order by pt_left asc;
        得到的结果是 C,D,E,F四个节点的数据。
    3. 查找两个节点之间的路径,以A到E为例,sql语句如下:
        select * from product_type where pt_left between 1 and 6 and pt_right between 7 and 20 order by pt_left ;
        得到的结果是A,B,D,E 这4个节点的数据。
    4.通过我们刚才新增数据得到这个结构的操作,我们发现新增分两种情况。第一种如下图所示:

新增节点X

变更所有的受影响的节点,给新节点腾出空位子,所有左节点比G节点大的,都增加2,所有右节点比G节点大的,也都增加2,则sql语句如下:
      update product_type set pt_left=pt_left+2 where pt_left>12;
      update product_type set pt_right=pt_right+2 where pt_right>13;
另一种为新增子节点,但该新增的节点左侧并有节点。举例:在E下新增Y节点,Y节点左右值为7,8,这时我们在修改后续节点时也应该考虑到E节点的存在。所以sql语句如下:
      update product_type set pt_left=pt_left+2 where pt_left>6;      

      update product_type set pt_right=pt_right+2 where pt_right>=7;

算法说明:

1.所有分类 左边和右边的值 > 插入节点的左边节点记录的右值 的全部 + 2
2.插入节点 左值 = 插入位置左边节点记录的右值 + 1, 右值 = 插入位置左边节点记录的右值 + 2

总结:

      经过这几天的相关操作和查询资料,整理后我写出了这些东西,但我的收获远不止这些,奈何语言水平有限就讲这么多吧!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容