在写完线性容器以后,再来看关联性容器。在关联性容器中,set,map容器都是基于红黑树而实现的,故花了几天时间写下来红黑树的代码。其原理可以参考算法导论。在写过程中也参照了网上别人写的代码。其代码实现如下:
#include<iostream>
using namespace std;
//红黑树
class RB_Tree
{
private:
enum COLOR{RED,BLACK};
class RB_Node
{
public:
RB_Node *left;
RB_Node *right;
RB_Node *parent;
COLOR RB_COLOR;
int data;
RB_Node(COLOR _COLOR=BLACK,int _data=0):left(NULL),right(NULL),parent(NULL),data(_data),RB_COLOR(_COLOR){}
};
private:
RB_Node *root; //红黑树的根节点
RB_Node *nullNode; //空节点,黑色的
//插入完成后要记得修复,使其满足红黑树的性质
//插入时中的三种情况
void InsertFixUp(RB_Node *node)
{
while(node->parent->RB_COLOR==RED)
{
//插入节点为父节点的左孩子
if(node->parent->left==node)
{
RB_Node *uncle=node->parent->parent->right;
if(uncle->RB_COLOR==RED) //case 1
{
node->parent->RB_COLOR=BLACK;
uncle->RB_COLOR=BLACK;
node=node->parent->parent;
node->RB_COLOR=RED;
}
else
{
if(node->parent==node->parent->parent->right) //case 2
{
node=node->parent;
right_rotate(node);
// goto double_left_rotate;
}
//case2结束以后直接进入case3,或者直接进入case3
// double_right_rotate:
else{
node->parent->RB_COLOR=BLACK;
node->parent->parent->RB_COLOR=RED;
right_rotate(node->parent->parent);
}
}
}
//当节点为为父节点的右孩子
else
{
RB_Node *uncle=node->parent->parent->left;
if(uncle->RB_COLOR==RED) //case 1
{
node->parent->RB_COLOR=BLACK;
uncle->RB_COLOR=BLACK;
node=node->parent->parent;
node->RB_COLOR=RED;
}
else
{
if(node->parent==node->parent->parent->left) //case 2
{
node=node->parent;
left_rotate(node);
// goto double_right_rotate;
}
//case2结束以后直接进入case3,或者直接进入case3
// double_left_rotate:
else{
node->parent->RB_COLOR=BLACK;
node->parent->parent->RB_COLOR=RED;
left_rotate(node->parent->parent);
}
}
}
}
if(node==root)
node->RB_COLOR=BLACK;
}
//左旋转
void left_rotate(RB_Node *node)
{
RB_Node *temp=node->right;
temp->parent=node->parent;
if(node->parent==nullNode)
root=temp;
else
{
if(node==node->parent->left)
node->parent->left=temp;
else
node->parent->right=temp;
}
node->right=temp->left;
if(temp->left!=nullNode)
temp->left->parent=node;
node->parent=temp;
temp->left=node;
}
//右旋转
void right_rotate(RB_Node *node)
{
RB_Node *temp=node->left;
temp->parent=node->parent;
if(node==root) //等价于node->parent==NULL
root=temp;
else
{
if(node==node->parent->left)
node->parent->left=temp;
else
node->parent->right=temp;
}
node->left=temp->right;
if(temp->right!=nullNode)
temp->right->parent=node;
node->parent=temp;
temp->right=node;
}
//找到值为value的节点
RB_Node* find_node(int value)
{
RB_Node *temp=root;
while(temp!=nullNode)
{
if(temp->data>value)
temp=temp->left;
else if(temp->data<value)
temp=temp->right;
else
break;
}
return temp;
}
//该函数的功能是用来在删除节点时,如果节点存在左右孩子节点则找到应该替换的节点
RB_Node* find_delete_node(RB_Node *node)
{
if(node->left==nullNode||node==nullNode)
return nullNode;
RB_Node *temp=node->left;
while(temp->right!=nullNode)
temp=temp->right;
return temp;
}
void deleteFixUp(RB_Node *node)
{
RB_Node *temp=node;
while(temp->RB_COLOR==BLACK&&temp!=root)
{
RB_Node *brother;
//该节点为父节点的左节点
if(temp==temp->parent->left)
{
brother=temp->parent->right;
if(brother->RB_COLOR==RED) //case 1
{
temp->parent->RB_COLOR=RED;
brother->RB_COLOR=BLACK;
//在旋转之后兄弟节点会发生变化,因此在旋转之前就将兄弟节点给换过来
brother=brother->left;
left_rotate(temp->parent);
}
//case 1结束后,会进入case2/case3/case4
if(brother->left->RB_COLOR==BLACK&&brother->right->RB_COLOR==BLACK) //case2
{
brother->RB_COLOR=RED;
temp=temp->parent;
}
else
{
if(brother->right->RB_COLOR==BLACK) //case 3
{
brother->RB_COLOR=RED;
brother->left->RB_COLOR=BLACK;
brother=brother->left;
right_rotate(brother->parent);
}
//进入case4情况
brother->RB_COLOR=temp->parent->RB_COLOR;
brother->right->RB_COLOR=temp->parent->RB_COLOR=BLACK;
left_rotate(temp->parent);
temp=root;
}
}
else //该节点为父节点的右孩子
{
brother=temp->parent->left;
if(brother->RB_COLOR==RED) //case 1
{
temp->parent->RB_COLOR=RED;
brother->RB_COLOR=BLACK;
//在旋转之后兄弟节点会发生变化,因此在旋转之前就将兄弟节点给换过来
brother=brother->right;
right_rotate(temp->parent);
}
//case 1结束后,会进入case2/case3/case4
if(brother->left->RB_COLOR==BLACK&&brother->right->RB_COLOR==BLACK) //case2
{
brother->RB_COLOR=RED;
temp=temp->parent;
}
else
{
if(brother->right->RB_COLOR==BLACK) //case 3
{
brother->RB_COLOR=RED;
brother->left->RB_COLOR=BLACK;
brother=brother->left;
left_rotate(brother->parent);
}
//进入case4情况
brother->RB_COLOR=temp->parent->RB_COLOR;
brother->right->RB_COLOR=temp->parent->RB_COLOR=BLACK;
right_rotate(temp->parent);
temp=root;
}
}
}
//最后退出来的时候记得将节点颜色变成黑色
temp->RB_COLOR=BLACK;
}
public:
//构造函数初始化
RB_Tree()
{
nullNode=new RB_Node();
root=nullNode;
nullNode->left=nullNode->right=nullNode->parent=nullNode;
}
//红黑树的插入操作
void insert_node(int value)
{
RB_Node *node=new RB_Node(RED,value);
node->left=node->right=node->parent=nullNode;
if(root==nullNode) //先把空树的情况处理掉
{
root=node;
root->RB_COLOR=BLACK;
return ;
}
RB_Node *temp=root;
RB_Node *insert_parent;
while(temp!=nullNode)
{
insert_parent=temp;
if(temp->data>value)
temp=temp->left;
else
temp=temp->right;
}
if(insert_parent->data>value)
insert_parent->left=node;
else
insert_parent->right=node;
node->parent=insert_parent;
//完成插入后的修复工作
InsertFixUp(node);
}
//红黑树的删除操作
void delete_node(int value)
{
RB_Node *node=find_node(value);
RB_Node *delete_node,*delete_node_child;
if(node->left==nullNode||node->right==nullNode)
delete_node=node;
else
delete_node=find_delete_node(node);
//如果删除点不是node,则应该将delete_node值复制过来
if(delete_node!=node)
node->data=delete_node->data;
if(delete_node->left!=nullNode)
delete_node_child=delete_node->left;
else if(delete_node->right!=nullNode)
delete_node_child=delete_node->right;
else
delete_node_child=nullNode;
delete_node_child->parent=delete_node->parent;
if(delete_node==root)
root=delete_node_child;
else
{
if(delete_node==delete_node->parent->left)
delete_node->parent->left=delete_node_child;
else
delete_node->parent->right=delete_node_child;
}
if(delete_node->RB_COLOR==BLACK)
deleteFixUp(delete_node_child);
delete delete_node;
}
//打印节点
void display()
{
display(root);
}
void display(RB_Node *node)
{
if(node->left!=nullNode)
display(node->left);
if(node!=nullNode)
cout<<node->data<<" 颜色为:"<<node->RB_COLOR<<endl;
if(node->right!=nullNode)
display(node->right);
}
};
int main()
{
RB_Tree q;
int i;
for(i=1;i<10;i++)
q.insert_node(i);
q.display();
for(i=1;i<10;i++)
{
q.delete_node(i);
cout<<"删除"<<i<<"后:"<<endl;
q.display();
}
return 0;
}
其运行结果图如下: