//全局函数,用于删除节点后调整树形

//__z为待删除点,__root为根节点,__leftmost左极点,__rightmost为右极点

inline _Rb_tree_node_base*

_Rb_tree_rebalance_for_erase(_Rb_tree_node_base* __z,

_Rb_tree_node_base*& __root,

_Rb_tree_node_base*& __leftmost,

_Rb_tree_node_base*& __rightmost)

{

_Rb_tree_node_base* __y = __z;       //调整后实际被删除点的指针

_Rb_tree_node_base* __x = 0;         //__y的某个子节点

_Rb_tree_node_base* __x_parent = 0;       //__x的父节点

if (__y->_M_left == 0)     //__z最多有右子节点一个非空子节点,__y=__z

__x = __y->_M_right;     // __x可能为空

else

if (__y->_M_right == 0)  // __z确实有一个非空左子节点(因为上个if的限定). y == z.

__x = __y->_M_left;    // __x不为空

else {                   // __z 有两个非空子节点,设定__y为__z的后继,

__y = __y->_M_right;   // __x为__y的右节点,__x可能为空

while (__y->_M_left != 0)

__y = __y->_M_left;

__x = __y->_M_right;

}

if (__y != __z) {          // 重新设置__y的链接以取代__z,__y是__z的后继

__z->_M_left->_M_parent = __y;  //在__y!=__z是__z的左子节点

__y->_M_left = __z->_M_left;    //一定会设置为__y的左子节点

if (__y != __z->_M_right) {      //__y不为__z的右子节点是

__x_parent = __y->_M_parent;

if (__x) __x->_M_parent = __y->_M_parent;

__y->_M_parent->_M_left = __x;      // __y一定是其父节点的左孩子

__y->_M_right = __z->_M_right;

__z->_M_right->_M_parent = __y;

}

else

__x_parent = __y;

if (__root == __z)

__root = __y;

else if (__z->_M_parent->_M_left == __z)

__z->_M_parent->_M_left = __y;

else

__z->_M_parent->_M_right = __y;

__y->_M_parent = __z->_M_parent;

__STD::swap(__y->_M_color, __z->_M_color);

__y = __z;

// __y 现在指向实际被删除的节点

}

else {                        // __y == __z

__x_parent = __y->_M_parent;

if (__x) __x->_M_parent = __y->_M_parent;

if (__root == __z)

__root = __x;

else

if (__z->_M_parent->_M_left == __z)

__z->_M_parent->_M_left = __x;

else

__z->_M_parent->_M_right = __x;

if (__leftmost == __z)

if (__z->_M_right == 0)        // __z->_M_left也一定为0

__leftmost = __z->_M_parent;

// 设定__leftmost为__z的父节点,覆盖了__z为root,__leftmost指向_M_header的情况

else

__leftmost = _Rb_tree_node_base::_S_minimum(__x);

if (__rightmost == __z)

if (__z->_M_left == 0)         // __z->_M_right也一定为0

__rightmost = __z->_M_parent;

//设定__rightmost为__z的父节点,覆盖了__z为root,__rightmost指向_M_header的情况

else                      // __x == __z->_M_left

__rightmost = _Rb_tree_node_base::_S_maximum(__x);

}

//以下代码可把__x看成着双重黑色!

if (__y->_M_color != _S_rb_tree_red) {   //只有当__y为黑时才需调整树形

while (__x != __root && (__x == 0 || __x->_M_color == _S_rb_tree_black))

if (__x == __x_parent->_M_left) {  //__x为父亲的左儿子

_Rb_tree_node_base* __w = __x_parent->_M_right;   //令__w为其兄弟

if (__w->_M_color == _S_rb_tree_red) { //__w为红色时,令__w为黑,__x父亲为红

__w->_M_color = _S_rb_tree_black;    //并以__x父亲为旋转点左旋,并更新__w

__x_parent->_M_color = _S_rb_tree_red;  //转换为__w为黑的情况

_Rb_tree_rotate_left(__x_parent, __root);

__w = __x_parent->_M_right;

}//以下为__w为黑色的各种情况,

if ((__w->_M_left == 0 ||    //__w的左右孩子都为黑或者都为空的时候

__w->_M_left->_M_color == _S_rb_tree_black) &&

(__w->_M_right == 0 ||

__w->_M_right->_M_color == _S_rb_tree_black)) {

__w->_M_color = _S_rb_tree_red;  //改__w为红色并将__x上移

__x = __x_parent;

__x_parent = __x_parent->_M_parent;

} else {

if (__w->_M_right == 0 ||

__w->_M_right->_M_color == _S_rb_tree_black) {//__w右孩子为黑,左孩子红时

if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;

__w->_M_color = _S_rb_tree_red;       //将左孩子着为黑,原__w改为红

_Rb_tree_rotate_right(__w, __root);   //并以原__w为旋转点右旋

__w = __x_parent->_M_right;          //然后更新__w,进入__w右孩子为红色的情况

}

//下面为__w右孩子为红的情况

__w->_M_color = __x_parent->_M_color;    //着__w为红

__x_parent->_M_color = _S_rb_tree_black;   //__x父亲为黑

if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;   //__w右节点着黑色

_Rb_tree_rotate_left(__x_parent, __root);   //以__x父亲为旋转点左旋

break;   //结束循环

}

} else {                  // 当__x为右孩子时,与以上情况相同,只需对调左右即可.

_Rb_tree_node_base* __w = __x_parent->_M_left;

if (__w->_M_color == _S_rb_tree_red) {

__w->_M_color = _S_rb_tree_black;

__x_parent->_M_color = _S_rb_tree_red;

_Rb_tree_rotate_right(__x_parent, __root);

__w = __x_parent->_M_left;

}

if ((__w->_M_right == 0 ||

__w->_M_right->_M_color == _S_rb_tree_black) &&

(__w->_M_left == 0 ||

__w->_M_left->_M_color == _S_rb_tree_black)) {

__w->_M_color = _S_rb_tree_red;

__x = __x_parent;

__x_parent = __x_parent->_M_parent;

} else {

if (__w->_M_left == 0 ||

__w->_M_left->_M_color == _S_rb_tree_black) {

if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;

__w->_M_color = _S_rb_tree_red;

_Rb_tree_rotate_left(__w, __root);

__w = __x_parent->_M_left;

}

__w->_M_color = __x_parent->_M_color;

__x_parent->_M_color = _S_rb_tree_black;

if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;

_Rb_tree_rotate_right(__x_parent, __root);

break;

}

}

if (__x) __x->_M_color = _S_rb_tree_black;       //__x为红色时,着__x为黑色即可

}

return __y;     //返回__待删除节点地址

}

说明:以下为程序中举出的四种情形

Rb-tree中删除元素后树形调整函数_Rb_tree_rebalance_for_erase相关推荐

  1. vector中删除元素后,如何有效的释放无效元素的内存

    .erase()只是删除了元素内容,并不能改变容量大小: 举例: 35 void testvector() 36 { 38     vector v; 39     v.push_back(1); 4 ...

  2. linux数组删除数据,JavaScript在数组的循环中删除元素

    在开发JavaScript应用的过程中,经常会遇到在循环中移除指定元素的需求. 按照常规的思路,就是对数组进行一个for循环,然后在循环里面进行if判断,在判断中删除掉指定元素即可. 但是实际情况往往 ...

  3. 从PHP中的数组中删除元素

    有没有一种简单的方法可以使用PHP从数组中删除元素,以便foreach ($array)不再包含该元素? 我认为将其设置为null可以做到,但是显然不起作用. #1楼 如果您有一个数字索引的数组,其中 ...

  4. javascript在数组的循环中删除元素

    在开发JavaScript应用的过程中,经常会遇到在循环中移除指定元素的需求. 按照常规的思路,就是对数组进行一个for循环,然后在循环里面进行if判断,在判断中删除掉指定元素即可. 但是实际情况往往 ...

  5. 容器删除元素后迭代器失效_STL 4: STL之容器:选择时机,删除元素,迭代器失效...

    一. 种类: 标准STL序列容器:vector.string.deque和list. 标准STL关联容器:set.multiset.map和multimap. 非标准序列容器slist和rope.sl ...

  6. List与Map的遍历过程中删除元素

    在日常的开发过程中,经常需要对List或Map里面的符合某种业务的数据进行删除,但是如果不了解里面的机制就容易掉入"陷阱"导致遗漏或者程序异常. List遍历过程中删除元素 使用索 ...

  7. 如何在Java中处理ConcurrentModificationException? 在循环中从ArrayList中删除元素时要当心...

    从Java中从ArrayList中删除元素时常见的问题之一是ConcurrentModificationException. 如果您对索引使用经典的for循环或增强的for循环,并尝试使用remove ...

  8. php unset函数_PHP | 使用unset()函数从数组中删除元素

    php unset函数 Given an array and we have to remove an element from the array. 给定一个数组,我们必须从数组中删除一个元素. u ...

  9. mysql for 循环删除_Java增强for循环中删除元素抛异常问题

    前言 最近突然想起刚毕业那会找工作时面试被问了个这样的问题.就是"使用增强for循环遍历ArrayList(List集合)时删除其中的元素是否会出现异常?".说实话当时真把我愣住了 ...

最新文章

  1. easyUI的combobox是否可用
  2. 自反ACL访问控制列表的应用
  3. 不可不知的C#基础 1. -- Extension 扩展方法
  4. push_back和emplace_back的区别
  5. plantuml语法_PlantUML实践 | 思维导图
  6. 代码android点击效果,GitHub - likaiyuan559/TouchEffects: Android View点击特效TouchEffects,几行代码为所有控件添加点击效果...
  7. Java消息服务~开发者分配的消息头
  8. 几大 Git 平台仓库被劫,黑客欲勒索比特币
  9. VMware vSphere常见问题汇总(十九)
  10. python运维自动化开发12期_Python自动化运维之12、面向对象进阶
  11. python主要数据变量_python的数据类型和变量
  12. 将ubuntu引导项加入windowsXP启动菜单中
  13. 局域网桌面监控软件_如何促进局域网监控软件在企业中的普及
  14. 最全“勒索病毒”的应对方案
  15. FPGA实现BT.1120编码
  16. mysql健康档案管理系统_益康居民健康档案管理系统(网络版)
  17. iOS开发工程师(SDK),U3D主程,制作人 招聘
  18. 贴片天线的HFSS和CST仿真对比
  19. 【AE软件】视频添加字幕
  20. powermock跳过某方法_PowerMock使用详解

热门文章

  1. 《终结拖延症》读书笔记
  2. 离职通知邮件主题写什么好_离职祝福邮件怎么写
  3. 沙箱支付宝支付 前后端分离项目 实战
  4. 【微信小程序调用百度API实现图像识别功能】----项目实战
  5. C语言struct用法详解
  6. 【八】【vlc-android】vlc-vout视频流输出端源码分析
  7. ssh海思3531a开发板的交叉编译
  8. 国开本科计算机应用基础操作题,新版国家开放大学中央电大本科计算机应用基础操作题题库...
  9. [篇二章七]_安装卸载 VMware Tools
  10. 面试题和问题总结-面试题2