上一篇文章是純粹地實現了紅黑樹,但是在STL中,紅黑樹容器是需要迭代器實現的。故將上一篇文章改進後實現紅黑樹容器。
本人實現的紅黑樹容器是底層紅黑樹結構是依據算法導論中設計的包含普通節點和空節點。不同於STL中的紅黑樹,其迭代器故也
有點不一樣
//my_rb_tree.h #ifndef MY_RB_TREE_H_INCLUDED #define MY_RB_TREE_H_INCLUDED #include"iterator_rb_tree.h" #include"simple_allocator.h" namespace juine { //紅黑樹 /* **紅黑樹容器中樹節點存放的對象是Value,但是比較的對象,用來決定樹的結構的則是Key, 函數對象KeyOfvalue這是Value對象向Key對象的轉化. 這樣紅黑樹容器與紅黑樹地區別就在於: 在insert和delete需找對象進行比較的時候,我們得到了Value對象,要將其轉化爲Key,然後在進行比較 例如以前是這樣寫的: if(temp->data<value) //節點所指值小於值value 要改成如下: if(key_compare(key(temp)),KeyOfValue()(value) ) key_compare:爲比較函數 key:將所指節點值轉化爲key類型 KeyOfValue;將Value值轉化爲Key類型 */ template<class Key,class Value,class KeyOfValue,class Compare,class Alloc=my_alloc> class RB_Tree { public: typedef Key key_type; typedef Value value_type; protected: RB_Node<Value>* root; //紅黑樹的根節點 RB_Node<Value>* nullNode; //空節點,黑色的 size_t node_num; Compare key_compare; //定義一個比較函數對象 typedef simple_allocator<RB_Node<Value>,Alloc> RB_Node_Container; //插入完成後要記得修復,使其滿足紅黑樹的性質 //插入時中的三種情況 void InsertFixUp(RB_Node<Value> *node) { while(node->parent->RB_COLOR==RED) { //插入節點爲父節點的左孩子 if(node->parent->left==node) { RB_Node<Value> *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<Value> *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<Value> *node) { RB_Node<Value> *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<Value> *node) { RB_Node<Value> *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<Value>* find_node(Value value) { RB_Node<Value> *temp=root; while(temp!=nullNode) { if(key_compare(KeyOfValue()(value),key(temp))) temp=temp->left; else if(key_compare(key(temp),KeyOfValue()(value))) temp=temp->right; else break; } return temp; } //該函數的功能是用來在刪除節點時,如果節點存在左右孩子節點則找到應該替換的節點 RB_Node<Value>* find_delete_node(RB_Node<Value> *node) { if(node->left==nullNode||node==nullNode) return nullNode; RB_Node<Value> *temp=node->left; while(temp->right!=nullNode) temp=temp->right; return temp; } void deleteFixUp(RB_Node<Value> *node) { RB_Node<Value> *temp=node; while(temp->RB_COLOR==BLACK&&temp!=root) { RB_Node<Value> *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; } RB_Node<Value>* alloc(COLOR color, Value value) { RB_Node<Value>* temp=RB_Node_Container::alloc(1); construct(temp,RB_Node<Value>(color,value)); return temp; } public: //定義迭代器 typedef Iterator_RB_Node<Value,Value&,Value*> iterator; typedef Iterator_RB_Node<Value,const Value&,const Value*> const_iterator; iterator begin() { RB_Node<Value>* temp=root; while(temp->left!=nullNode) temp=temp->left; return iterator(temp,nullNode); } iterator end(){ return iterator(nullNode,nullNode);} iterator minleft() {return begin();} iterator maxright() { RB_Node<Value>* temp=root; while(temp->right!=nullNode) temp=temp->right; return iterator(temp,nullNode); } //得到迭代器所指對象的key值 key_type key(RB_Node<Value> *iter) { return KeyOfValue()(iter->data); } //構造函數初始化 RB_Tree() { nullNode=alloc(BLACK,Value()); root=nullNode; node_num=0; nullNode->left=nullNode->right=nullNode; nullNode->parent=root; } //紅黑樹的插入操作 void insert_node(Value value) { node_num++; RB_Node<Value> *node=alloc(RED,value); node->left=node->right=node->parent=nullNode; if(root==nullNode) //先把空樹的情況處理掉 { root=node; root->RB_COLOR=BLACK; return ; } RB_Node<Value> *temp=root; RB_Node<Value> *insert_parent; while(temp!=nullNode) { insert_parent=temp; // if(value<temp->data) if(key_compare(KeyOfValue()(value),key(temp))) temp=temp->left; else temp=temp->right; } // if(value<insert_parent->data) if(key_compare(KeyOfValue()(value),key(insert_parent))) insert_parent->left=node; else insert_parent->right=node; node->parent=insert_parent; //完成插入後的修復工作 InsertFixUp(node); } //紅黑樹的刪除操作 void delete_node(Value value) { node_num--; RB_Node<Value> *node= find_node(value); RB_Node<Value> *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<Value> *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); } size_t size(){ return node_num;} }; } #endif // MY_RB_TREE_H_INCLUDED
#ifndef ITERATOR_RB_TREE_H_INCLUDED
#define ITERATOR_RB_TREE_H_INCLUDED
#include"my_iterator_base.h"
/*
**
iterator_rb_tree.h
紅黑樹地泛型容器地迭代器
與以往前面地容器構造方式不同,該容器採用雙層架構,使其獲得更加大的彈性
*/
namespace juine
{
enum COLOR{RED,BLACK};
template<class T> //紅黑樹的節點信息
struct RB_Node
{
typedef RB_Node* base_ptr;
base_ptr left;
base_ptr right;
base_ptr parent;
COLOR RB_COLOR;
T data;
RB_Node(COLOR _RB_COLOR=BLACK,T _data=0):RB_COLOR(_RB_COLOR),data(_data){}
};
//紅黑樹的正規迭代器(標準迭代器的寫法)
template<class Value,class Ref,class Ptr>
struct Iterator_RB_Node
{
typedef Value value_type;
typedef Ref reference;
typedef Ptr pointer;
typedef bidirectional_iterator_tag iterator_category;
typedef Iterator_RB_Node<Value,Value&,Value*> iterator;
typedef Iterator_RB_Node<Value,const Value&,const Value*> const_iterator;
typedef Iterator_RB_Node<Value,Ref,Ptr> self;
typedef RB_Node<Value>* link_type;
link_type node;
/*下面這個節點是我自己加的,因爲我設計的紅黑樹中節點分爲普通節點和空節點
**所有節點的指針域都不會是NULL,我們都用空節點來代替,其顏色都是黑色
因此,在迭代器執行++,--操作時,爲了符合終止條件,故在創建迭代器時候,
要講迭代器所指向的紅黑樹中表達的空節點指針傳過來,不然,迭代器中的循環終止
條件無法判斷。
*/
link_type nullNode;
//construct
Iterator_RB_Node(){}
Iterator_RB_Node(link_type x,link_type y){ node=x; nullNode=y;}
Iterator_RB_Node(const iterator& it){ node=it.node; nullNode=it.nullNode;}
self operator= (const iterator& it)
{
node=it.node;
return *this;
}
bool operator!=(const self& it)
{
return node!=it.node;
}
//重載
reference operator* () { return node->data;}
link_type operator-> () { return node;}
self& operator++()
{
increment();
return *this;
}
self operator++(int)
{
self iter=*this;
++*this;
return iter;
}
self& operator--()
{
decrement();
return *this;
}
self operator--(int)
{
self iter=*this;
--*this;
return iter;
}
void increment() //指針++操作
{
//當孩子有右節點時,++爲右子樹的最大左孩子節點
if(node->right!=nullNode)
{
node=node->right;
while(node->left!=nullNode)
node=node->left;
}
else //往父節點上尋找
{
link_type parents=node->parent;
while(node==parents->right) //爲父節點右孩子時,繼續往上找
{
node=parents;
parents=parents->parent;
}
if(parents!=nullNode)
node=parents;
else //找到根基點還沒找到,則++應該指向空節點
node=nullNode;
}
}
void decrement()
{
if(node->left!=nullNode)
{
node=node->left;
while(node->right!=nullNode)
node=node->right;
}
else
{
RB_Node<Value>* parents=node->parent;
while(parents->left==node)
{
node=parents;
parents=parents->parent;
}
if(parents!=nullNode)
node=parents;
else
node=nullNode;
}
}
};
}
#endif // ITERATOR_RB_TREE_H_INCLUDED
以下是測試代碼:
#include<iostream> #include"my_rb_tree.h" //#include<stack> using namespace std; using namespace juine; template<typename T> struct identity { const T& operator()(const T& x) { return x; } }; template<class T> struct comp { bool operator()(T v1,T v2) { return v1>v2; } }; int main() { RB_Tree<int,int,identity<int>,comp<int> > q; int i; for(i=1;i<10;i++) q.insert_node(i); RB_Tree<int,int,identity<int>,comp<int> >::iterator iter=q.maxright(); for(iter=q.maxright();iter!=q.end();iter--) cout<<*iter<<" 顏色爲: "<<iter->RB_COLOR<<endl; for(i=1;i<10;i++) { q.delete_node(i); cout<<"刪除"<<i<<"後:"<<endl; RB_Tree<int,int,identity<int>,comp<int> >::iterator iter=q.maxright(); for(iter=q.maxright();iter!=q.end();iter--) cout<<*iter<<" 顏色爲: "<<iter->RB_COLOR<<endl; } return 0; }