【学习笔记】红黑树的实现(二):删除算法
来源:互联网 发布:淘宝的营销中心在哪找 编辑:程序博客网 时间:2024/05/17 08:51
该文主要解释红黑树的删除和删除后的再平衡
所有代码已经过编译,编译环境ubuntu12.04LTS GCC 4.6.3
完整的红黑树代码已上传GitHub:https://github.com/xusongqi/Data_Structures
————————————————————————————————————————————
5月6日上午总算把删除算法弄得差不多了......
————————————————————————————————————————————
昨天整理了自己红黑树中插入操作的学习,今天把删除操作给整理了~
红黑树里插入的一般情况有三种,删除的一般情况却有四种,所以基本上来讲,插入操作比删除操作简单一点。
再写一遍红黑树的五个基本性质:
1)每个结点要么是红的,要么是黑的。
2)根结点是黑的。
3)每个叶结点,即空结点(NIL)是黑的。
4)如果一个结点是红的,那么它的俩个儿子都是黑的。
5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
删除操作和AVL树里面的删除原理基本差不多,不过也存在几个比较蛋疼的地方,下面会写到。
删除函数
删除函数里面,除了删除叶子节点之外,有三种情况:
1)待删结点有两个孩子
2)待删结点只有左孩子(其实可以把叶节点的情况放在这里)
3)待删结点只有右孩子
其中主要注意一点:删除之后,如果删掉的节点是黑的,那么传入删除再平衡函数(Delete_Rebalance(child, parent, root))的第一个参数是【实际删掉节点】的孩子节点。
举个例子:如果待删结点有两个孩子,那么会将该节点右枝中的最小节点(递归寻找左孩子before该节点为NULL)替换掉该待删结点,那么child就是该最小节点的右孩子(因为左孩子为空了)。
发一个流程图
第二个和第三个情况比较简单,因为待删结点的最多只有一个非空的孩子,只需要将这个孩子与待删结点的父节点连起来就OK了。
说下情况一:
1.将待删结点的old右枝中的最小值设为node(具体是:找到待删结点的右孩子,在右孩子中不断递归寻找当前节点的非空左孩子),
然后将child等于node的右孩子,将parent等于node的父节点。
然后断开node与parent以及child的连接,将child与parent建立连接。
最后如果node是黑色的,将child和parent传入函数Delete_Rebalance(child, parent, index);
删除再平衡函数
/*删除再平衡函数*/static RB_Tree RB_Delete_Rebalance(RB_Tree node, RB_Tree parent, RB_Tree index){RB_Tree brother;//节点的兄弟/*开始循环调整,以下四种情况,当前节点(node)均为黑色*/while((!node || node->color == BLACK) && node != index){/*当前节点为父节点的左子*/if(parent->leftChild == node){brother = parent->rightChild;/*情况一:兄弟节点为红色 *解决办法:父节点变红,兄弟节点变黑,左旋父节点 * */if(brother->color == RED){parent->color = RED;brother->color = BLACK;index = RB_Rotate_Left(parent, index);}else//以下是brother颜色为黑的三种情况{/*情况二:兄弟节点为黑,兄弟节点的两个子节点也为黑*解决办法:先将兄弟节点变红,然后根据父节点:1.若父节点为黑,父节点成为当前节点,继续算法2.若父节点为红,将父节点变黑。树平衡,结束算法 * */if( (!brother->leftChild || brother->leftChild->color == BLACK) &&(!brother->rightChild || brother->rightChild->color == BLACK) ){brother->color = RED;//若父节点为红,变为黑,结束算法if(parent->color == RED){parent->color = BLACK;break;}node = parent;//父节点成为新的当前节点(父节点原即为黑)parent = node->parent;continue;//重新进入算法循环}/*情况三:兄弟节点为黑,兄弟节点的左孩子为红,右孩子为黑 *解决办法:将兄弟节点染红,兄弟节点的左孩子染黑,右旋兄弟节点 * */if( (brother->leftChild && brother->leftChild->color == RED) && (!brother->rightChild || brother->rightChild->color == BLACK)){brother->color = RED;brother->leftChild->color = BLACK;index = RB_Rotate_Right(brother, index);}/*情况四:兄弟节点为黑,兄弟节点的右孩子为红,左孩子颜色任意 *解决办法:兄弟节点染成父节点的颜色,父节点染黑,兄弟节点的右孩子染黑,左旋父节点。树平衡,算法结束 * */brother->color = parent->color;parent->color = BLACK;brother->rightChild->color = BLACK;//此时该节点原本颜色一定为红色index = RB_Rotate_Left(parent, index);node = index;}//[else:bro为黑]结束}//[if:node为父节点左孩子]结束/*当前节点为父节点右孩子*/else{brother = parent->leftChild;/*情况一:兄弟节点为红 *解决办法:父节点染红,兄弟节点染黑,右旋父节点 * */if(brother->color == RED){parent->color = RED;brother->color = BLACK;index = RB_Rotate_Right(parent, index);}/*以下三种情况,兄弟节点均为黑色*/else{/*情况二:兄弟节点为黑,兄弟节点的两个字节点也为黑*解决办法:先将兄弟节点变红,然后根据父节点:1.若父节点为黑,父节点成为当前节点,继续算法2.若父节点为红,将父节点变黑。树平衡,结束算法 * */if( (!brother->leftChild ||brother->leftChild->color == BLACK) && (!brother->rightChild || brother->rightChild->color == BLACK)){brother->color = RED;//若父节点为红,染黑,树即平衡。if(parent->color == RED){parent->color = BLACK;break;}node = parent;//父节点成为新的当前节点(父节点原来即黑色)parent = node->parent;continue;//重新进入算法循环}/*情况三:兄弟节点为黑,兄弟节点的右孩子为红,左孩子为黑 *解决办法:兄弟节点变红,兄弟节点的右孩子变黑,左旋兄弟节点 * */if( (brother->rightChild && brother->rightChild->color == RED) &&(!brother->leftChild || brother->leftChild->color == BLACK)){brother->color = RED;brother->rightChild->color = BLACK;index = RB_Rotate_Left(brother, index);}/*情况四:兄弟节点为黑,兄弟节点的左孩子为红,右孩子颜色任意 *解决办法:兄弟节点染成父节点颜色,父节点染黑,兄弟节点的左孩子染黑,右旋父节点 * */brother->color = parent->color;parent->color = BLACK;brother->color = BLACK;index = RB_Rotate_Right(parent, index);}//[else:兄弟节点为黑]结束}//[else:node为父节点右孩子]结束}//[while:删除再平衡算法]结束/*将root点的颜色置为黑色*/if(node){node->color = BLACK;}return index;//返回root节点}
参考资料
你透彻了解红黑树—结构之法,算法之道
红黑树的C实现完整源码—结构之法,算法之道
红黑树删除—spch2008
还有一片资料对我理解(一般情况二)的帮助很大,但是找不到了.....
- 【学习笔记】红黑树的实现(二):删除算法
- 数据结构学习笔记<二> 算法2.3的具体实现
- 红黑树插入与删除 算法实现+代码(二)
- 【学习笔记】红黑树的实现(一):插入算法
- 算法(第4版) 学习笔记二——二分查找的普通实现与递归实现
- Andrew Ng机器学习笔记+Weka相关算法实现(二)生成学习/朴素贝叶斯
- 数据结构与算法分析学习笔记二-栈的C语言实现
- 数据结构学习笔记<二> 算法2.1的具体实现,合并集合A,B
- TLD算法学习笔记(二)
- 算法学习笔记(二) 面试
- KMP算法学习笔记(二)
- 算法导论学习笔记(二) 初稿
- Hadoop学习笔记二 - kNN算法实现用户风险分类
- 学习笔记二、调用聚类算法包实现层次
- 《Orange'S:一个操作系统的实现》学习笔记(二)
- 实现接口的枚举类 学习笔记(二)
- C#学习笔记(二) 标准Dispose模式的实现
- JFinal学习笔记(二) 实现简单的用户登录
- No mapping found for HTTP request with URI
- iOS UITextField垂直居中对齐
- 中国软件业真的到了该反思的时候了
- 发布应用到AppStore
- C++ 使用ACTIVE控件
- 【学习笔记】红黑树的实现(二):删除算法
- 装SQL Server 2005中报错,错误说明:事务管理器不可用。
- 用什么方法可以恢复视频mp4格式文件呢
- Linux下批量杀掉 包含某个关键字的 程序进程
- golang字符、字符串的那些事儿
- Android修炼之道—ListView的HeaderView的问题
- c++中关于数组作为函数参数并传递数组元素个数的几种有效方法的讨论
- 自定义java 线程池
- Zstack之HAL层增加新的按键key的分析笔记3