Rb-tree中删除元素后树形调整函数_Rb_tree_rebalance_for_erase
//全局函数,用于删除节点后调整树形
//__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相关推荐
- vector中删除元素后,如何有效的释放无效元素的内存
.erase()只是删除了元素内容,并不能改变容量大小: 举例: 35 void testvector() 36 { 38 vector v; 39 v.push_back(1); 4 ...
- linux数组删除数据,JavaScript在数组的循环中删除元素
在开发JavaScript应用的过程中,经常会遇到在循环中移除指定元素的需求. 按照常规的思路,就是对数组进行一个for循环,然后在循环里面进行if判断,在判断中删除掉指定元素即可. 但是实际情况往往 ...
- 从PHP中的数组中删除元素
有没有一种简单的方法可以使用PHP从数组中删除元素,以便foreach ($array)不再包含该元素? 我认为将其设置为null可以做到,但是显然不起作用. #1楼 如果您有一个数字索引的数组,其中 ...
- javascript在数组的循环中删除元素
在开发JavaScript应用的过程中,经常会遇到在循环中移除指定元素的需求. 按照常规的思路,就是对数组进行一个for循环,然后在循环里面进行if判断,在判断中删除掉指定元素即可. 但是实际情况往往 ...
- 容器删除元素后迭代器失效_STL 4: STL之容器:选择时机,删除元素,迭代器失效...
一. 种类: 标准STL序列容器:vector.string.deque和list. 标准STL关联容器:set.multiset.map和multimap. 非标准序列容器slist和rope.sl ...
- List与Map的遍历过程中删除元素
在日常的开发过程中,经常需要对List或Map里面的符合某种业务的数据进行删除,但是如果不了解里面的机制就容易掉入"陷阱"导致遗漏或者程序异常. List遍历过程中删除元素 使用索 ...
- 如何在Java中处理ConcurrentModificationException? 在循环中从ArrayList中删除元素时要当心...
从Java中从ArrayList中删除元素时常见的问题之一是ConcurrentModificationException. 如果您对索引使用经典的for循环或增强的for循环,并尝试使用remove ...
- php unset函数_PHP | 使用unset()函数从数组中删除元素
php unset函数 Given an array and we have to remove an element from the array. 给定一个数组,我们必须从数组中删除一个元素. u ...
- mysql for 循环删除_Java增强for循环中删除元素抛异常问题
前言 最近突然想起刚毕业那会找工作时面试被问了个这样的问题.就是"使用增强for循环遍历ArrayList(List集合)时删除其中的元素是否会出现异常?".说实话当时真把我愣住了 ...
最新文章
- easyUI的combobox是否可用
- 自反ACL访问控制列表的应用
- 不可不知的C#基础 1. -- Extension 扩展方法
- push_back和emplace_back的区别
- plantuml语法_PlantUML实践 | 思维导图
- 代码android点击效果,GitHub - likaiyuan559/TouchEffects: Android View点击特效TouchEffects,几行代码为所有控件添加点击效果...
- Java消息服务~开发者分配的消息头
- 几大 Git 平台仓库被劫,黑客欲勒索比特币
- VMware vSphere常见问题汇总(十九)
- python运维自动化开发12期_Python自动化运维之12、面向对象进阶
- python主要数据变量_python的数据类型和变量
- 将ubuntu引导项加入windowsXP启动菜单中
- 局域网桌面监控软件_如何促进局域网监控软件在企业中的普及
- 最全“勒索病毒”的应对方案
- FPGA实现BT.1120编码
- mysql健康档案管理系统_益康居民健康档案管理系统(网络版)
- iOS开发工程师(SDK),U3D主程,制作人 招聘
- 贴片天线的HFSS和CST仿真对比
- 【AE软件】视频添加字幕
- powermock跳过某方法_PowerMock使用详解