左倾红黑树(LLRBT)删除操作及相关性质总结答疑
Left-leaning Red Black Tree
看算法4(算法 第4版 Algorithms 4th Edition)3.4节时,后面的习题有实现左倾红黑树删除操作的代码,刚开始看得云里雾里的,后来查了不少资料慢慢理解了,发现还是对LLRBT的性质认识得不够深刻,如果认识深刻的话还是可以理解代码的。今天做一个总结,希望能帮到遇到类似问题的朋友,如有错误,还望大家指出。
- 总是完美黑色平衡,且所有右链接都是黑链接,只有左链接有可能是红链接。
- 旋转操作(rotate)不会影响平衡。
- 转换颜色操作(flipColors)不会影响平衡(前提是左右子节点同色,而根节点与子节点们异色)。
转换颜色: - moveRedLeft往左添红,删除最小节点或当前节点大于需删除节点时使用。
- moveRedRight往右添红,删除最大节点或当前节点小于需删除节点时使用。
- moveRedLeft和moveRedRight的代码实现中,也只是在不同条件下,使用了不同的旋转操作或者转换颜色操作,所以也不影响平衡。
- 当需要删除一个节点时,如果这个节点刚好是红节点(指向它的是红链接),那就直接删除1即可(红节点不影响平衡),但是这是理想状况,现实不可能是理想的,再但是!我们可以追求理想!
- 为了追求7中的理想,也就是当前节点永远是红节点,LLRBT的删除操作中有个隐藏约束,那就是确保当前节点或者当前节点的左子节点是红节点,为什么当前节点的左子节点是红节点也行呢,因为这时候我们不是能通过右旋操作把当前节点变成红节点嘛,再为什么是左子节点而不是右子节点呢,因为LLRBT只有左子节点可能是红啊。
- 做到8,基本就能达到7中我们所追求的理想状态了。但是又有,如果从root出我们开始时当前节点(此时就是root节点)和它的左子节点都不是红的怎么办(此时的隐藏信息是右子节点也不为红,因为LLRBT所有右链接都为黑),那我们就直接把根节点改为红!(不影响平衡,只是黑高减了1)
- 至此,我们就把现实变成了理想的样子。遇到待删除节点,就可以直接(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);}
关于二叉树的通用删除操作:如果待删除节点是叶子节点:直接删除;如果待删除节点有一个自己点:删除,并用它的子节点代替它,此时待删除元素的这唯一一个子节点其实就是它的前驱(左)或者后继(右)节点;如果待删除节点有两个子节点:删除,并用它的后继节点(以待删除节点的右子树为根的子树的最小节点)代替它。 ↩︎
收尾工作:要把root,再平衡(blance)一下,平衡完后root有可能为红,得把root改为黑。 ↩︎
左倾红黑树(LLRBT)删除操作及相关性质总结答疑相关推荐
- 红黑树的删除_Python实现红黑树的删除操作
上一篇文章使用Python实现了红黑树的插入操作.参考:Python实现红黑树的插入操作本篇文章使用Python实现红黑树的删除操作.先将红黑树的5条特性列出来:1. 节点是红色或黑色.2. 根节点是 ...
- Python实现红黑树的删除操作
Python实现红黑树的删除操作 本专栏的上一篇文章使用Python实现了红黑树的插入操作.参考:https://blog.csdn.net/weixin_43790276/article/detai ...
- 红黑树的删除操作详解
红黑树的删除操作 无子节点时,删除节点可能为红色或者黑色: 1.1 如果为红色,直接删除即可,不会影响黑色节点的数量: 1.2 如果为黑色,则需要进行删除平衡的操作了: 只有一个子节点时,删除节点只能 ...
- 从二叉查找树到平衡树:avl, 2-3树,左倾红黑树(含实现代码),传统红黑树...
参考:自平衡二叉查找树 ,红黑树, 算法:理解红黑树 (英文pdf:红黑树) 目录 自平衡二叉树介绍 avl树 2-3树 LLRBT(Left-leaning red-black tree左倾红黑树 ...
- 左倾红黑树的go语言实现
简介 红黑树经常能在计算机底层代码中见到,比如 C++的map,multimap, set, multiset Linux中rdtree用以管理内存和进程 Java中的HashMap 左倾红黑树是对红 ...
- 红黑树+java+删除_红黑树深入剖析及Java实现
红黑树是平衡二叉查找树的一种.为了深入理解红黑树,我们需要从二叉查找树开始讲起. BST 二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小, ...
- 红黑树的删除真的很难吗?其实是你没找到好的解题思路,不信你点击进来看看,建议收藏哦!!!
上一篇介绍了红黑树的插入操作,这篇来给大家介绍下红黑树的删除操作. 红黑树删除节点 红黑树的节点的删除其实也分为两步: 先删除节点(这步和普通的二叉树删除是一样的) 然后再调整 1.删除节点 ...
- 左倾红黑树Go语言实现
文章目录 左倾红黑树的定义 红黑树性质 Node数据结构 旋转 插入 颜色转换 删除 实现 Keys Contains DeleteMin.DeleteMax Rank.Get Ceil Floor ...
- 数据结构——左倾红黑树
左倾红黑树 前提了解 红黑树和平衡多叉树的对应关系 左倾红黑树 基于自顶向下2-3-4树的左倾红黑树 基于2-3树的左倾红黑树 重要代码 左右旋转变色 翻转变色 向2-3左倾红黑树插入 向2-3-4左 ...
最新文章
- iview实现国际化
- arm linux gcc fpic,【待整理】Gcc中编译和链接选项 -fpic -fPIC -fpie -fPIE -pie的含义
- where is url parameter evaluated in UI5 core q.sap.getUriParameters
- 使用命令行编译Less源文件
- 2016 年 7 个最佳的 Java 框架
- c语言回文字符串判断函数的奇偶性,C语言拓展训练编程题.doc
- 学习码 滚动码 固定码 有什么区别重码数,编码容量滚动码的原理
- c 语言读取字符串长度,C++获取字符串长度的几个函数方式
- 云端服务器怎么修改密码,云端服务器怎么设置登录密码
- PgSQl 结合 Mybatis 插入 json,及查询,数据库使用 jsonb
- 2018年「编码美丽」公众号精华帖总结,建议收藏(文末赠书)!
- 如何获取dll或exe的模块名
- 微软 Teams 等服务大规模宕机
- 51单片机c语言学习感想,51单片机实训心得体会
- 64位系统下同时使用64位和32位的eclipse
- 何为固定IP和动态IP?快解析搞定固定IP端口映射!
- 整理全菜30篇学习vue和脚手架的笔记
- Mysql性能优化教程
- s12xep100 bootloader设计要点总结
- 有创业团队想打造不一样的大数据平台
热门文章
- Code Festival 2017 qualA E-Modern Painting
- 谷歌浏览器无法打开localhost:3000,打开localhost就跳转测试地址问题
- SpringMVC_初级总结
- 和风天气开发者使用总结
- ssh提示IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY解决
- jquery-210812-05---jquery函数02
- 【蓝桥杯每日一练:木头加工】
- 深度估计(Depth Estimation)
- html5博客在线写文章,HTML5响应式清新博客文章类织梦模板(移动端自适应)
- 内网工具viper的介绍与配置简介