上一篇介绍了红黑树的插入操作,这篇来给大家介绍下红黑树的删除操作。

红黑树删除节点

  红黑树的节点的删除其实也分为两步:

  1. 先删除节点(这步和普通的二叉树删除是一样的)
  2. 然后再调整

1.删除节点

  要删除这个节点先需要找到这个节点,找到节点就是普通的二分查找,具体代码如下

    private RBNode getNode(K key){RBNode node = this.root;while (node != null ){int cmp = key.compareTo((K) node.key);if(cmp < 0){// 在左子树node = node.left;}else if(cmp >0){// 右子树node = node.right;}else{return node;}}return null;}

  在整理红黑树节点的删除操作时我们需要先理解清楚红黑树删除和2-3-4树删除的等价关系,这样理解起来才会比较容易
  核心理论:红黑树删除操作的本质其实就是删除2-3-4树的叶子节点

情况一

情况2:删除的是非情况1的节点,根据我们前面介绍的删除的规则,会找到对应的前驱和后继节点,那么最终删除的还是叶子节点

首先删除节点的代码为:

/*** 删除节点* @param key* @return*/public V remove(K key){// 先找到这个节点RBNode node = getNode(key);if(node == null){return null;}// 把值存起来 删除后 返回V oldValue = (V) node.value;deleteNode(node);return oldValue;}/*** 删除节点*   3种情况* 1.删除叶子节点,直接删除* 2.删除的节点有一个子节点,那么用子节点来替代* 3.如果删除的节点右两个子节点,此时需要找到前驱节点或者后继节点来替代*    可以转换为 1、2的情况* @param node*/private void deleteNode(RBNode node){// 3.node节点有两个子节点if(node.left !=null && node.right != null){// 找到要删除节点的后继节点RBNode successor = successor(node);// 然后用后继节点的信息覆盖掉 要删除节点的信息node.key = successor.key;node.value = successor.value;// 然后我们要删除的节点就变为了 后继节点node = successor;}// 2.删除有一个子节点的情况RBNode replacement = node.left != null ? node.left : node.right;if(replacement != null){// 替代者的父指针指向原来 node 的父节点replacement.parent = node.parent;if(node.parent == null){// 说明 node 是root节点root = replacement;}else if(node == node.parent.left){// 双向绑定node.parent.left = replacement;}else{node.parent.right = replacement;}// 将node的左右孩子指针和父指针都指向null node等待GCnode.left = node.right = node.parent = null;// 替换完成后需要调整平衡if(node.color == BLACK){// fixAfterRemove(replacement)}}else if(node.parent == null){// 说明要删除的是root节点root = null;}else{// 1. node节点是叶子节点 replacement为null// 先调整if(node.color == BLACK){// fixAfterRemove(node)}// 再删除if(node.parent != null){if(node == node.parent.left){node.parent.left = null;}else{node.parent.right = null;}node = null;}}}

然后就是需要调整红黑树的平衡了。

2.删除后的平衡调整

删除节点的调整操作:

1.情况一:自己能搞定的,对应叶子节点是3节点和4节点

2.情况二:自己搞不定,需要兄弟借,但是兄弟不借,找父亲借,父亲下来,然后兄弟找一个人去代替父亲当家

这种情况就是兄弟节点是3节点或者4节点

找兄弟节点
如果找到的兄弟节点是红色其实还要调整

执行如下调整先,先变色,然后左旋

找兄弟节点借

然后沿着7节点左旋

3.情况三:跟兄弟借,兄弟也没有(情同手足,同时自损)

兄弟节点是2节点,同时当前节点的父节点是红色节点的情况


删除后直接变色就可以了

兄弟节点是2节点,同时当前节点的父节点是黑色节点

变更操作为如下,如果继续有父节点那么还要递归处理

分析清楚了删除的3中情况,我们就可以撸处删除的调整的代码了

    /*** 2-3-4树删除操作:* 1.情况一:自己能搞定的,对应叶子节点是3节点和4节点* 2.情况二:自己搞不定,需要兄弟借,但是兄弟不借,找父亲借,父亲下来,然后兄弟找一个人去代替父亲当家* 3.情况三:跟兄弟借,兄弟也没有* @param x*/private void fixAfterRemove(RBNode x){// 情况2、3while(x != root && colorOf(x) == BLACK){// 这种情况才需要调整// x 是左孩子的情况if(x == leftOf(parentOf(x))){// 找兄弟节点RBNode rNode = rightOf(parentOf(x));// 判断此时的兄弟节点是否是真正的兄弟节点 兄弟是红色的情况要调整if(colorOf(rNode) == RED){ // 2-3-4树的 3节点 交换颜色,然后左旋一次就可以了setColor(rNode,BLACK);setColor(parentOf(x),RED);leftRotate(parentOf(x)); // 左旋一次rNode = rightOf(parentOf(x)); // 找到真正的兄弟节点}// 情况3 找兄弟借 没得借if(colorOf(leftOf(rNode)) == BLACK && colorOf(rightOf(rNode)) == BLACK){// 情况复杂setColor(rNode,RED);x=parentOf(x); // 向上递归}else{// 情况2 找兄弟借 有借// 兄弟节点是 3节点或者4节点if(colorOf(rightOf(rNode)) == BLACK){// 右孩子为空,则左孩子肯定不为空// 兄弟节点 先要左一次右旋setColor(rNode,RED);setColor(leftOf(rNode),BLACK);rightRotate(rNode);// 重新调整叔叔节点的位置rNode = rightOf(parentOf(x));}// 变色  兄弟节点是 3节点还是4节点 都旋转一次setColor(rNode, colorOf(parentOf(x)));setColor(parentOf(x),BLACK);setColor(rightOf(rNode),BLACK);// 左旋leftRotate(parentOf(x));x = root; // 结束循环  递归 针对的是 情况3}}else{// 找兄弟节点RBNode rNode = leftOf(parentOf(x));// 判断此时的兄弟节点是否是真正的兄弟节点 兄弟是红色的情况要调整if(colorOf(rNode) == RED){ // 2-3-4树的 3节点 交换颜色,然后左旋一次就可以了setColor(rNode,BLACK);setColor(parentOf(x),RED);rightRotate(parentOf(x)); // 左旋一次rNode = leftOf(parentOf(x)); // 找到真正的兄弟节点}// 情况3 找兄弟借 没得借if(colorOf(rightOf(rNode)) == BLACK && colorOf(leftOf(rNode)) == BLACK){// 情况复杂setColor(rNode,RED);x=parentOf(x); // 向上递归}else{// 情况2 找兄弟借 有借// 兄弟节点是 3节点或者4节点if(colorOf(leftOf(rNode)) == BLACK){// 右孩子为空,则左孩子肯定不为空// 兄弟节点 先要左一次右旋setColor(rNode,RED);setColor(leftOf(rNode),BLACK);leftRotate(rNode);// 重新调整叔叔节点的位置rNode = leftOf(parentOf(x));}// 变色  兄弟节点是 3节点还是4节点 都旋转一次setColor(rNode, colorOf(parentOf(x)));setColor(parentOf(x),BLACK);setColor(leftOf(rNode),BLACK);// 左旋rightRotate(parentOf(x));x = root; // 结束循环  递归 针对的是 情况3}}}// 情况1:替代节点是红色,直接染黑  在情况3的情况下  补偿删除的黑色节点,这样红黑树依然保存平衡setColor(x,BLACK);}

~好了,到这儿,相信大家应该对红黑树的各种操作都比较清楚了,如果对你有帮助,欢迎点赞关注加收藏哦!!! V_V

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

  1. ZBrush建模很难么?那是没找到技巧!盘点八十个3DMAX常见的问题,小白珍藏系列

    01.使用图像平面 02.利用Scale Master 03.使用Sculptris Pro 04.背面遮蔽 05.硬表面建模 06.动态细分 07.使用颜色选择器 08.子工具大师 Remesh B ...

  2. 【转载】哈希表的原理,真的很难弄懂么?

    [转载]哈希表的原理,真的很难弄懂么? 刘小爱v 发布时间:05-0909:06科技达人 转载路径: https://baijiahao.baidu.com/s?id=1666172942887109 ...

  3. 红黑树的删除_从红黑树的本质出发,彻底理解红黑树!

    前言 早上好,我是彤哥. 上一节,我们一起从二叉树.二叉查找树.平衡树.AVL树.2-3树.2-3-4树.B树,一路讲到红黑树,最后得出红黑树的本质:红黑树就是2-3-4树,请看下图: 我们知道2-3 ...

  4. 数据结构真的很难学?

    如果你关注计算机专业招聘试题,会发现越是大型公司,问的问题越基础,有的甚至问你什么是栈和队列,反而一些小公司会关心你做过什么系统.从关注点的不同可以看出,大公司更注重基础扎实和发展潜力,而小公司希望你 ...

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

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

  6. 红黑树的删除_红黑树

    红黑树是许多"平衡的"查找树中的一种,它能保证在最坏的情况下,基本的动态集合操作(插入和删除)的时间为O(lgh).我们先简单叙述二叉查找树的性质. 1.1 二叉查找树 二叉查找树 ...

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

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

  8. 红黑树操作详解——很形象的过程

    红黑树是一种很好的自平衡二叉排序树,在此,给出一个网友给出的红黑树操作详解: https://segmentfault.com/a/1190000012728513 里面给出了红黑树的详细操作,过程很 ...

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

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

最新文章

  1. Xshell+技巧+快捷键
  2. c+和python的区别-python和c先学哪个
  3. 日本推出罩杯测量APP,罩杯大小一夹便知!
  4. nutch开发(二)
  5. java 泛型调用方法调用_java – 如何使用泛型调用最具体的方法?
  6. 视图插入数据_用EXCEL作数据分析--招聘信息
  7. linux shell express,Linux下使Shell 命令脱离终端在后台运行
  8. 多径传输系统MATLAB代码,求助大佬帮忙写毕设代码啊。。用matlab做MIMO-FrFT-OFDM系统...
  9. 单链表的插入和遍历 包括头插入和尾插入
  10. 面向公交营运管理的车路协同应用场景研究
  11. win7系统如何添加显示桌面?显示桌面图标设置方法
  12. Python进阶实战 1.0 :爬取豆瓣TOP250电影排行榜
  13. 力科(Lecroy)示波器专用波形文件(轨迹文件/trace文件/.trc文件)在MATLAB上的解析与回写
  14. 阳离子铱配合物(Ir1+)|(Ir2-)|Ir(dmecf3ppz)2bpy+(PF6)-齐岳合成
  15. 自动创建文件夹 pictureBox 显示图片 并调用系统窗体打开文件夹
  16. 轻松打造开源安全信息管理平台
  17. docsify安装,docsify搭建,docsify使用教程
  18. *grep -F/f的作用*
  19. 谷歌浏览器自带的翻译插件为什么不能用
  20. 用matlab证明向量组等价,线性代数常见面试题

热门文章

  1. java读书心得_java夜未眠的读书心得
  2. MySQL高可用之InnoDB Cluster
  3. java 中 Scanner 输入
  4. 在java中给数组赋值,java中给数组赋值的方法
  5. SQL Server跟踪(Trace)--慢查询跟踪跟踪日志
  6. mysql裸石ID用什么数据类型_澳宝裸石.网址的whois查询信息-西部数码,方便快捷的whois查询平台...
  7. C 语言 GET请求 超小纯净下载工具 (支持http、https)第四季
  8. 不作为的领导,锁住了劳动者的创新,以及手脚
  9. 几个免费的在线项目管理
  10. Vue项目中的接口调用