在写完线性容器以后,再来看关联性容器。在关联性容器中,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; }