算法练习五 红黑树下 节点删除(转)
2013-06-07 23:12
483 查看
接着算法联系五,实现了红黑树的节点删除功能。
补充了五个函数,这里主要将 删除 和 删除修正两个函数给出,其它的就十分简单了。
//删除
RBNode* RBDelete(RBNode** proot, RBNode* pnode, RBNode* pguardNode);
//删除修正
void RBDeleteFixup(RBNode** proot, RBNode* pnode, RBNode* pguardNode);
//返回以节点为根的最小元素
RBNode* TreeMinimum(RBNode* pnode, RBNode* pguardNode);
//返回以节点为根的最大元素
RBNode* TreeMaxmum(RBNode* pnode, RBNode* pguardNode);
//返回节点的后继
RBNode* TreeSuccessor(RBNode* pnode, RBNode* pguardNode);
[cpp]
view plaincopyprint?
//删除
RBNode* RBDelete(RBNode** proot, RBNode* pnode, RBNode* pguardNode)
{
RBNode* y; //y为实际要被删除的节点
RBNode* x; //x为y的孩子,y最多只有一个孩子
if ( pnode->pLeft == pguardNode || pnode->pRight == pguardNode ) //左右孩子至少有一个为空
{
y = pnode;
}
else //左右孩子都不为空
{
y = TreeSuccessor(pnode,pguardNode); //y为pnode的后继节点
}
if ( y->pLeft != pguardNode ) //pnode的只有左孩子的情况
{
x = y->pLeft;
}
else
{
x = y->pRight;
}
//删除y开始
x->pParent = y->pParent; //用x来替换y
if ( y->pParent == pguardNode )
{
*proot = x;
}
else
{
if ( y == y->pParent->pLeft )
{
y->pParent->pLeft = x; //用x替换y
}
else
{
y->pParent->pRight = x;
}
}
//删除y结束
//将pnode的key用y的key替换
if ( y != pnode )
{
pnode->key = y->key; //*这里没有将y的颜色赋值给pnode,这一点十分重要*//
}
if ( y->color == BLACK )
{
RBDeleteFixup( proot,x,pguardNode ); //修正性质5
}
return y;
}
//删除修正
void RBDeleteFixup(RBNode** proot, RBNode* px, RBNode* pguardNode)
{
RBNode* w;
while( px != *proot && px->color == BLACK && px != pguardNode )
{
if ( px == px->pParent->pLeft )
{
w = px->pParent->pRight;
if ( w->color == RED ) //case1 px的兄弟是红色的
{
w->color = BLACK;
px->pParent->color = RED;
LeftRotate( proot, px->pParent, pguardNode );
w = px->pParent->pRight;
}
if ( w->pLeft->color == BLACK && w->pRight->color == BLACK )
{ // case2 px的兄弟w是黑色的,并且w的两个孩子都是黑色的
w->color = RED;
px = px->pParent;
}
else
{
if ( w->pRight->color == BLACK )
{
//case3 px的兄弟w是黑色的,w的左孩子是红色的,右孩子是黑色的
w->pLeft->color = BLACK;
w->color = RED;
RightRotate(proot,w,pguardNode);
w = px->pParent->pRight;
}
//case4 px的兄弟w是黑色的,w的左孩子任意色,右孩子是红色的
w->color = px->pParent->color;
px->pParent->color = BLACK;
w->pRight->color = BLACK;
LeftRotate(proot,px->pParent,pguardNode);
px = *proot;
}
}
else // px == px->pParent->pRight
{
w = px->pParent->pLeft;
if ( w->color == RED )
{
w->color = BLACK;
px->pParent->color = RED;
RightRotate( proot, px->pParent, pguardNode );
w = px->pParent->pLeft;
}
if ( w->pLeft->color == BLACK && w->pRight->color == BLACK )
{
w->color = RED;
px = px->pParent;
}
else
{
if ( w->pLeft->color == BLACK )
{
w->pRight->color = BLACK;
w->color = RED;
LeftRotate( proot, w, pguardNode );
w = px->pParent->pLeft;
}
w->color = px->pParent->color;
px->pParent->color = BLACK;
w->pLeft->color = BLACK;
RightRotate(proot, px->pParent, pguardNode );
px = *proot;
}
}
}//end while loop
px->color = BLACK;
}
补充了五个函数,这里主要将 删除 和 删除修正两个函数给出,其它的就十分简单了。
//删除
RBNode* RBDelete(RBNode** proot, RBNode* pnode, RBNode* pguardNode);
//删除修正
void RBDeleteFixup(RBNode** proot, RBNode* pnode, RBNode* pguardNode);
//返回以节点为根的最小元素
RBNode* TreeMinimum(RBNode* pnode, RBNode* pguardNode);
//返回以节点为根的最大元素
RBNode* TreeMaxmum(RBNode* pnode, RBNode* pguardNode);
//返回节点的后继
RBNode* TreeSuccessor(RBNode* pnode, RBNode* pguardNode);
[cpp]
view plaincopyprint?
//删除
RBNode* RBDelete(RBNode** proot, RBNode* pnode, RBNode* pguardNode)
{
RBNode* y; //y为实际要被删除的节点
RBNode* x; //x为y的孩子,y最多只有一个孩子
if ( pnode->pLeft == pguardNode || pnode->pRight == pguardNode ) //左右孩子至少有一个为空
{
y = pnode;
}
else //左右孩子都不为空
{
y = TreeSuccessor(pnode,pguardNode); //y为pnode的后继节点
}
if ( y->pLeft != pguardNode ) //pnode的只有左孩子的情况
{
x = y->pLeft;
}
else
{
x = y->pRight;
}
//删除y开始
x->pParent = y->pParent; //用x来替换y
if ( y->pParent == pguardNode )
{
*proot = x;
}
else
{
if ( y == y->pParent->pLeft )
{
y->pParent->pLeft = x; //用x替换y
}
else
{
y->pParent->pRight = x;
}
}
//删除y结束
//将pnode的key用y的key替换
if ( y != pnode )
{
pnode->key = y->key; //*这里没有将y的颜色赋值给pnode,这一点十分重要*//
}
if ( y->color == BLACK )
{
RBDeleteFixup( proot,x,pguardNode ); //修正性质5
}
return y;
}
//删除修正
void RBDeleteFixup(RBNode** proot, RBNode* px, RBNode* pguardNode)
{
RBNode* w;
while( px != *proot && px->color == BLACK && px != pguardNode )
{
if ( px == px->pParent->pLeft )
{
w = px->pParent->pRight;
if ( w->color == RED ) //case1 px的兄弟是红色的
{
w->color = BLACK;
px->pParent->color = RED;
LeftRotate( proot, px->pParent, pguardNode );
w = px->pParent->pRight;
}
if ( w->pLeft->color == BLACK && w->pRight->color == BLACK )
{ // case2 px的兄弟w是黑色的,并且w的两个孩子都是黑色的
w->color = RED;
px = px->pParent;
}
else
{
if ( w->pRight->color == BLACK )
{
//case3 px的兄弟w是黑色的,w的左孩子是红色的,右孩子是黑色的
w->pLeft->color = BLACK;
w->color = RED;
RightRotate(proot,w,pguardNode);
w = px->pParent->pRight;
}
//case4 px的兄弟w是黑色的,w的左孩子任意色,右孩子是红色的
w->color = px->pParent->color;
px->pParent->color = BLACK;
w->pRight->color = BLACK;
LeftRotate(proot,px->pParent,pguardNode);
px = *proot;
}
}
else // px == px->pParent->pRight
{
w = px->pParent->pLeft;
if ( w->color == RED )
{
w->color = BLACK;
px->pParent->color = RED;
RightRotate( proot, px->pParent, pguardNode );
w = px->pParent->pLeft;
}
if ( w->pLeft->color == BLACK && w->pRight->color == BLACK )
{
w->color = RED;
px = px->pParent;
}
else
{
if ( w->pLeft->color == BLACK )
{
w->pRight->color = BLACK;
w->color = RED;
LeftRotate( proot, w, pguardNode );
w = px->pParent->pLeft;
}
w->color = px->pParent->color;
px->pParent->color = BLACK;
w->pLeft->color = BLACK;
RightRotate(proot, px->pParent, pguardNode );
px = *proot;
}
}
}//end while loop
px->color = BLACK;
}
相关文章推荐
- 算法练习五 红黑树下 节点删除
- 一种新的删除红黑树节点的算法
- [算法练习]逆置链表,链表排序,删除节点
- 一种新的删除红黑树节点的算法
- 红黑树插入与删除 算法实现+代码(一)
- 红黑树插入与删除 算法实现+代码(二)
- [算法练习]找到单向链表的中间节点
- 算法导论 红黑树 节点删除
- 删除链表的倒数第K个节点(每日一道算法题)
- leetcode:Remove Nth Node From End of List(删除链表倒数第n个节点)【面试算法题】
- 红黑树的删除(算法导论)
- 数据结构和算法设计专题之---单链表中在指定的节点前面插入以及删除一个节点
- 剑指offer之O(1)算法删除指针所指向的节点
- [算法练习]将字符串中*提前&&删除指定字符
- Java数据结构与算法《十三》删除二叉树节点
- LeetCode算法练习(删除链表的倒数第N个节点)
- 链表删除节点--算法复杂度o(1)
- 算法与数据结构基础11:C++实现——二拆搜索树节点删除
- 【简单算法】22.删除链表的倒数第N个节点
- 【算法之链表(三)】单链表中,在仅允许使用一个指针的情况下,在指定的节点前面插入以及删除一个节点