- 作者:邹祁峰
- 邮箱:Qifeng.zou.job@hotmail.com
- 博客:http://blog.csdn.net/qifengzou
- 日期:2014.01.18 01:21
- 转载请注明来自"祁峰"的CSDN博客
1 引言
在《算法导论 之 红黑树 - 插入》中已经对红黑树的5个性质做了较详细的分析,同时也给出了insert操作的C语言实现。首先我们再回顾一下红黑树的5个性质:
①、每个节点要么是红色的,要么是黑色的;
②、根结点是黑色的;
③、所有叶子结点(NIL)都是黑色的;
④、如果一个结点是红色,则它的两个儿子都是黑色的;
⑤、对任何一个结点,从该结点通过其子孙结点到达叶子结点(NIL)的所有路径上包含相同数目的黑结点。
和插入操作一样,结点的删除操作的时间复杂度也是O(log2@N)[注:以2为底数,N为对数],但删除操作的处理更复杂一些。
2 删除处理
2.1 外部接口
调用接口删除指定key结点时,其内部首先会查找红黑树中是否存在key结点。如果key结点不存在,则无需进行任何的处理;如果key结点存在,则调用_rbt_delete()删除结点。
红黑树是查找树的一种,其查找key结点的过程与查找树的查找过程极其相似。故,外部接口的实现代码如下:[注:代码中出现的数据类型、宏、枚举或函数定义可以参考《算法导论 之 红黑树 - 插入》]
/******************************************************************************
**函数名称: rbt_delete
**功 能: 删除结点(外部接口)
**输入参数:
** tree: 红黑树
** key: 关键字
**输出参数: NONE
**返 回: RBT_SUCCESS:成功 RBT_FAILED:失败
**实现描述:
** 1. 如果key的结点不存在,则无需进行任何的处理;
** 2. 如果key的结点存在,则调用_rbt_delete()删除结点。
**注意事项:
**作 者: # Qifeng.zou # 2013.12.27 #
******************************************************************************/
int rbt_delete(rbt_tree_t *tree, int key)
{
rbt_node_t *node = tree->root;
while(tree->sentinel != node) {
if(key == node->key) {
return _rb_delete(tree, node); /* 找到:执行删除处理 */
} else if(key < node->key) {
node = node->lchild;
} else {
node = node->rchild;
}
}
return RBT_SUCCESS; /* 未找到 */
}
代码1 删除操作
2.2 删除过程
假如需要删除结点D,则删除操作的过程有如下几种情况:[注:在以下所有绘制的红黑树中,均未绘制叶子结点]
情况1:被删结点D的左孩子为叶子结点,右孩子无限制(可为叶子结点,也可为非叶子结点)
处理过程:
①、删除结点D,并用右孩子结点替代结点D的位置;
②、如果被删结点D为红色,则红黑树性质未被破坏,因此无需做其他调整;
③、如果被删结点D为黑色,则需进一步做调整处理。
图1 情况1-1:左右孩子均为叶子结点
[叶子结点取代了结点D的位置]
图2 情况1-2:左孩子为叶子结点 右孩子不为叶子结点
[结点DR取代了叶子结点的位置]
情况2: 被删结点D的右孩子为叶子结点,左孩子不为叶子结点
处理过程:
①、删除结点D,并用左孩子节点替代结点D的位置;
②、如果被删结点D为红色,则红黑树性质未被破坏,因此不需做其他调整;
③、如果被删结点D为黑色,则需进