zoukankan      html  css  js  c++  java
  • 采用左右值编码实现无限分级树形结构(转)

    无限分级树形结构是在系统开发中很常见的,如下图

    在之前实现这样的菜单一直是使用传统的方法,看数据表结构就一目了然

    parent_id记录其直接父节点,组合树形结构的关键字段;parent_list记录其所有父节点,便于查询某个节点下所有子节点(一般使用MySQL的FIND_IN_SET函数),相对冗余。
    对于这种结构生成树形的关键算法:根据parent_id组合一个父子(直接关系)节点映射表,即 2 => array(3, 4), 3 => array(5),然后递归优先遍历每个节点的子节点。
    如果还需要按顺序排列,比如移动某个节点,则需要再添加一个字段来记录顺序。
    优点:简单清晰,通俗易懂,添删改节点都很容易实现
    缺点:查询效率不高(但一般树形结构都比较小)

    再看另一种实现方式-左右值编码
    其数据结构比较简单,但左右值需要经过遍历计算得到,很难看出直接父子关系的节点

    通过图了解左右值如何定义,类似前序遍历,父节点先访问,再访问子节点,递增标记,每个节点访问两次,分左右值。

    所有子节点的左右值一定在父节点的左右值范围,所以通过语句left > $parent_left AND right < $parent_right就可以查询某个节点下所有的子节点,比FIND_IN_SET优雅。而查找直属的子节点只需要加上layer = $parent_layer + 1限制。

    生成树操作
    只需要按left字段从小到大顺序输出就行,缩进层次的就根据layer值,简单。

    新增操作
    比如在服务端类别添加一个子节点Python,一个节点占用2个值,新增的节点就是左右值就是父节点的右值和右值+1,而影响到的节点值(蓝色)都是大于等于父节点的右值(即>=10),都是原先的值加2。
    新增前

    新增后

    删除操作
    删除可参考新增操作,只是将>=父节点右值的所有节点值减去2

    移动操作
    主要是改变父节点和同层节点调换操作
    移动操作基本基于一个公式:任何树所占的数字数目 = 根的右值 – 根的左值 + 1。

    1.改变父节点
    先看下移动PHP到客户端,即PHP的父节点换成客户端,这种情况下树节点上的变化
    改变前

    改变后

    以PHP为根的树(虽然只有一个节点)的节点值变化是以新父节点的原右值为依据,如上图,新父节点的原右值为6,那PHP新的左值就是6,这样重新遍历PHP为根的树,就相当于这棵子树上的每个节点更新为:原值 – (根的原左值 – 根的新左值),所以PHP的右值就等于7 = 9 – (8 – 6)。
    而除了PHP为根的树,其他节点更新的有一定范围,范围就是新父节点的右值和PHP原先的左值(或旧父节点的左值),因为PHP是向前移,范围内的节点值是往后移,需要加上PHP树的所占的数字数目,见上面公式,这里可以总结一个定律:
    新父节点_right <= ([left, right] + (移动_right – 移动_left + 1)) < 移动_left

    再看下PHP向后移的情况,与前移类似,也是更新一定范围的节点,变成减定律:
    移动_right < ([left, right] – (移动_right – 移动_left + 1)) < 新父节点_left

    2.同层节点调换
    这里同层节点调换是指兄弟节点顺序调换,为了简化,一般是移到某个兄弟节点(参考点)后面,特殊情况是移到最前,这种情况参考点就是父节点。

    如图,把语言一类移到兄弟节点-数据库后面。参考点是数据库,影响范围是语言的right与数据库的right之间的值,这类移动属于后移,根据上面提到的后移减定律,可得到公式:
    移动_right < ([left, right] – (移动_right – 移动_left + 1)) <= 参考点_right
    而前移公式:参考点_right < ([left, right] + (移动_right – 移动_left + 1)) < 移动_left
    如果是移到最前,只是前移公式的范围的左边界换为父节点_left,即公式为:父节点_left < ([left, right] + (移动_right – 移动_left + 1)) < 移动_left。
    对于是前移还是后移,可以根据移动节点的left值与参考点的right值的大小关系判断。

    至此,关于左右值编码实现树形结构的关键操作都已说明,主要也是公式,范围是哪些,是加还是减,我也是纠结了几天,所以上面显得有点啰嗦,如果有兴趣的还是亲手推断,也许会发现比上面更简单的更新操作。

  • 相关阅读:
    93. Restore IP Addresses
    92. Reverse Linked List II
    阿里巴巴 内推 面试
    hulu
    287. Find the Duplicate Number *HARD*
    89. Gray Code
    87. Scramble String *HARD* 动态规划
    84. Largest Rectangle in Histogram *HARD* -- 柱状图求最大面积 85. Maximal Rectangle *HARD* -- 求01矩阵中的最大矩形
    BZOJ2693jzptab
    最大公约数和
  • 原文地址:https://www.cnblogs.com/stubborn412/p/3937266.html
Copyright © 2011-2022 走看看