Left-leaning Red Black Tree
看算法4(算法 第4版 Algorithms 4th Edition)3.4节时,后面的习题有实现左倾红黑树删除操作的代码,刚开始看得云里雾里的,后来查了不少资料慢慢理解了,发现还是对LLRBT的性质认识得不够深刻,如果认识深刻的话还是可以理解代码的。今天做一个总结,希望能帮到遇到类似问题的朋友,如有错误,还望大家指出。

  1. 总是完美黑色平衡,且所有右链接都是黑链接,只有左链接有可能是红链接。
  2. 旋转操作(rotate)不会影响平衡。
  3. 转换颜色操作(flipColors)不会影响平衡(前提是左右子节点同色,而根节点与子节点们异色)。
    转换颜色:
  4. moveRedLeft往左添红,删除最小节点或当前节点大于需删除节点时使用。
  5. moveRedRight往右添红,删除最大节点或当前节点小于需删除节点时使用。
  6. moveRedLeft和moveRedRight的代码实现中,也只是在不同条件下,使用了不同的旋转操作或者转换颜色操作,所以也不影响平衡。
  7. 当需要删除一个节点时,如果这个节点刚好是红节点(指向它的是红链接),那就直接删除1即可(红节点不影响平衡),但是这是理想状况,现实不可能是理想的,再但是!我们可以追求理想!
  8. 为了追求7中的理想,也就是当前节点永远是红节点,LLRBT的删除操作中有个隐藏约束,那就是确保当前节点或者当前节点的左子节点是红节点,为什么当前节点的左子节点是红节点也行呢,因为这时候我们不是能通过右旋操作把当前节点变成红节点嘛,再为什么是左子节点而不是右子节点呢,因为LLRBT只有左子节点可能是红啊。
  9. 做到8,基本就能达到7中我们所追求的理想状态了。但是又有,如果从root出我们开始时当前节点(此时就是root节点)和它的左子节点都不是红的怎么办(此时的隐藏信息是右子节点也不为红,因为LLRBT所有右链接都为黑),那我们就直接把根节点改为红!(不影响平衡,只是黑高减了1)
  10. 至此,我们就把现实变成了理想的样子。遇到待删除节点,就可以直接(zhanzhe)把它(qian)删除(zhengle)。 2

下面附上涉及到的代码

 // make a left-leaning link lean to the rightprivate Node rotateRight(Node h) {assert (h != null) && isRed(h.left);// assert (h != null) && isRed(h.left) &&  !isRed(h.right);  // for insertion onlyNode x = h.left;h.left = x.right;x.right = h;x.color = x.right.color;x.right.color = RED;x.size = h.size;h.size = size(h.left) + size(h.right) + 1;return x;}// make a right-leaning link lean to the leftprivate Node rotateLeft(Node h) {assert (h != null) && isRed(h.right);// assert (h != null) && isRed(h.right) && !isRed(h.left);  // for insertion onlyNode x = h.right;h.right = x.left;x.left = h;x.color = x.left.color;x.left.color = RED;x.size = h.size;h.size = size(h.left) + size(h.right) + 1;return x;}// flip the colors of a node and its two childrenprivate void flipColors(Node h) {// h must have opposite color of its two children// assert (h != null) && (h.left != null) && (h.right != null);// assert (!isRed(h) &&  isRed(h.left) &&  isRed(h.right))//    || (isRed(h)  && !isRed(h.left) && !isRed(h.right));h.color = !h.color;h.left.color = !h.left.color;h.right.color = !h.right.color;}/*** Removes the smallest key and associated value from the symbol table.** @throws NoSuchElementException if the symbol table is empty*/public void deleteMin() {if (isEmpty()) throw new NoSuchElementException("BST underflow");// if both children of root are black, set root to redif (!isRed(root.left) && !isRed(root.right))root.color = RED;root = deleteMin(root);if (!isEmpty()) root.color = BLACK;// assert check();}// delete the key-value pair with the minimum key rooted at hprivate Node deleteMin(Node h) {if (h.left == null)return null;if (!isRed(h.left) && !isRed(h.left.left))h = moveRedLeft(h);h.left = deleteMin(h.left);return balance(h);}// Assuming that h is red and both h.left and h.left.left// are black, make h.left or one of its children red.private Node moveRedLeft(Node h) {// assert (h != null);// assert isRed(h) && !isRed(h.left) && !isRed(h.left.left);flipColors(h);if (isRed(h.right.left)) {h.right = rotateRight(h.right);h = rotateLeft(h);flipColors(h);}return h;}/*** Removes the largest key and associated value from the symbol table.** @throws NoSuchElementException if the symbol table is empty*/public void deleteMax() {if (isEmpty()) throw new NoSuchElementException("BST underflow");// if both children of root are black, set root to redif (!isRed(root.left) && !isRed(root.right))root.color = RED;root = deleteMax(root);if (!isEmpty()) root.color = BLACK;// assert check();}// delete the key-value pair with the maximum key rooted at hprivate Node deleteMax(Node h) {if (isRed(h.left))h = rotateRight(h);if (h.right == null)return null;if (!isRed(h.right) && !isRed(h.right.left))h = moveRedRight(h);h.right = deleteMax(h.right);return balance(h);}// Assuming that h is red and both h.right and h.right.left// are black, make h.right or one of its children red.private Node moveRedRight(Node h) {// assert (h != null);// assert isRed(h) && !isRed(h.right) && !isRed(h.right.left);flipColors(h);if (isRed(h.left.left)) {h = rotateRight(h);flipColors(h);}return h;}/*** Removes the specified key and its associated value from this symbol table* (if the key is in this symbol table).** @param key the key* @throws IllegalArgumentException if {@code key} is {@code null}*/public void delete(Key key) {if (key == null) throw new IllegalArgumentException("argument to delete() is null");if (!contains(key)) return;// if both children of root are black, set root to redif (!isRed(root.left) && !isRed(root.right))root.color = RED;root = delete(root, key);if (!isEmpty()) root.color = BLACK;// assert check();}// delete the key-value pair with the given key rooted at hprivate Node delete(Node h, Key key) {// assert get(h, key) != null;if (key.compareTo(h.key) < 0) {if (!isRed(h.left) && !isRed(h.left.left))h = moveRedLeft(h);h.left = delete(h.left, key);} else {if (isRed(h.left))h = rotateRight(h);if (key.compareTo(h.key) == 0 && (h.right == null))return null;if (!isRed(h.right) && !isRed(h.right.left))h = moveRedRight(h);if (key.compareTo(h.key) == 0) {Node x = min(h.right);h.key = x.key;h.val = x.val;// h.val = get(h.right, min(h.right).key);// h.key = min(h.right).key;h.right = deleteMin(h.right);} else h.right = delete(h.right, key);}return balance(h);}

  1. 关于二叉树的通用删除操作:如果待删除节点是叶子节点:直接删除;如果待删除节点有一个自己点:删除,并用它的子节点代替它,此时待删除元素的这唯一一个子节点其实就是它的前驱(左)或者后继(右)节点;如果待删除节点有两个子节点:删除,并用它的后继节点(以待删除节点的右子树为根的子树的最小节点)代替它。 ↩︎

  2. 收尾工作:要把root,再平衡(blance)一下,平衡完后root有可能为红,得把root改为黑。 ↩︎

左倾红黑树(LLRBT)删除操作及相关性质总结答疑相关推荐

  1. 红黑树的删除_Python实现红黑树的删除操作

    上一篇文章使用Python实现了红黑树的插入操作.参考:Python实现红黑树的插入操作本篇文章使用Python实现红黑树的删除操作.先将红黑树的5条特性列出来:1. 节点是红色或黑色.2. 根节点是 ...

  2. Python实现红黑树的删除操作

    Python实现红黑树的删除操作 本专栏的上一篇文章使用Python实现了红黑树的插入操作.参考:https://blog.csdn.net/weixin_43790276/article/detai ...

  3. 红黑树的删除操作详解

    红黑树的删除操作 无子节点时,删除节点可能为红色或者黑色: 1.1 如果为红色,直接删除即可,不会影响黑色节点的数量: 1.2 如果为黑色,则需要进行删除平衡的操作了: 只有一个子节点时,删除节点只能 ...

  4. 从二叉查找树到平衡树:avl, 2-3树,左倾红黑树(含实现代码),传统红黑树...

    参考:自平衡二叉查找树 ,红黑树, 算法:理解红黑树 (英文pdf:红黑树) 目录 自平衡二叉树介绍 avl树 2-3树 LLRBT(Left-leaning red-black tree左倾红黑树 ...

  5. 左倾红黑树的go语言实现

    简介 红黑树经常能在计算机底层代码中见到,比如 C++的map,multimap, set, multiset Linux中rdtree用以管理内存和进程 Java中的HashMap 左倾红黑树是对红 ...

  6. 红黑树+java+删除_红黑树深入剖析及Java实现

    红黑树是平衡二叉查找树的一种.为了深入理解红黑树,我们需要从二叉查找树开始讲起. BST 二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小, ...

  7. 红黑树的删除真的很难吗?其实是你没找到好的解题思路,不信你点击进来看看,建议收藏哦!!!

      上一篇介绍了红黑树的插入操作,这篇来给大家介绍下红黑树的删除操作. 红黑树删除节点   红黑树的节点的删除其实也分为两步: 先删除节点(这步和普通的二叉树删除是一样的) 然后再调整 1.删除节点 ...

  8. 左倾红黑树Go语言实现

    文章目录 左倾红黑树的定义 红黑树性质 Node数据结构 旋转 插入 颜色转换 删除 实现 Keys Contains DeleteMin.DeleteMax Rank.Get Ceil Floor ...

  9. 数据结构——左倾红黑树

    左倾红黑树 前提了解 红黑树和平衡多叉树的对应关系 左倾红黑树 基于自顶向下2-3-4树的左倾红黑树 基于2-3树的左倾红黑树 重要代码 左右旋转变色 翻转变色 向2-3左倾红黑树插入 向2-3-4左 ...

最新文章

  1. iview实现国际化
  2. arm linux gcc fpic,【待整理】Gcc中编译和链接选项 -fpic -fPIC -fpie -fPIE -pie的含义
  3. where is url parameter evaluated in UI5 core q.sap.getUriParameters
  4. 使用命令行编译Less源文件
  5. 2016 年 7 个最佳的 Java 框架
  6. c语言回文字符串判断函数的奇偶性,C语言拓展训练编程题.doc
  7. 学习码 滚动码 固定码 有什么区别重码数,编码容量滚动码的原理
  8. c 语言读取字符串长度,C++获取字符串长度的几个函数方式
  9. 云端服务器怎么修改密码,云端服务器怎么设置登录密码
  10. PgSQl 结合 Mybatis 插入 json,及查询,数据库使用 jsonb
  11. 2018年「编码美丽」公众号精华帖总结,建议收藏(文末赠书)!
  12. 如何获取dll或exe的模块名
  13. 微软 Teams 等服务大规模宕机
  14. 51单片机c语言学习感想,51单片机实训心得体会
  15. 64位系统下同时使用64位和32位的eclipse
  16. 何为固定IP和动态IP?快解析搞定固定IP端口映射!
  17. 整理全菜30篇学习vue和脚手架的笔记
  18. Mysql性能优化教程
  19. s12xep100 bootloader设计要点总结
  20. 有创业团队想打造不一样的大数据平台

热门文章

  1. Code Festival 2017 qualA E-Modern Painting
  2. 谷歌浏览器无法打开localhost:3000,打开localhost就跳转测试地址问题
  3. SpringMVC_初级总结
  4. 和风天气开发者使用总结
  5. ssh提示IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY解决
  6. jquery-210812-05---jquery函数02
  7. 【蓝桥杯每日一练:木头加工】
  8. 深度估计(Depth Estimation)
  9. html5博客在线写文章,HTML5响应式清新博客文章类织梦模板(移动端自适应)
  10. 内网工具viper的介绍与配置简介