本篇文章并没有详细的讲解红黑树各方面的知识,只是以图形的方式对红黑树插入节点需要进行调整的过程进行的解释。
最近在看stl源码剖析,看到map底层红黑树的实现。为了加深对于红黑树的理解就自己动手写了红黑树插入的实现。关于红黑树插入节点后破坏红黑树性质的几种情况,可以在网上搜到很多相关的信息。下面用图说明插入新节点时红黑树所做的调整。插入的序列分别是30,40,50,20,35,10,11。
首先是插入30,由于现在红黑树是一棵空,所以直接将30作为根节点,并将根节点颜色染成黑色即可。
一、插入40,如下图所示。由于此时并没有破坏红黑树的性质,所以此时插入成功。
图1:插入40
二、插入50,插入节点50后,50及其父节点都为红色,由于此时40没有兄弟节点。此时将父节点变黑,祖父节点变红,以祖父节点为根进行左旋。调整后如图2-2所示
图2-1:插入节点50 图2-2:插入节点50调整后
三、插入20,插入节点20后,其父节点30及叔节点50都是红色节点。解决方法是将父节点及叔节点变黑,祖父节点变红。祖父节点变成新的当前节点重新进行算法。由于40是根节点,所以将根节点变黑。调整后如图3-2所示,此时满足红黑树的全部性质。
图3-1:插入节点20 图3-2:插入节点20调整后
四、插入节点35,如图4所示,由于此时并未破坏红黑树的任何性质。不需要进行调整算法。
图4:插入节点35
五、插入节点10,此时10的父节点20及其叔节点35都是红色。将20及35节点变黑,祖父节点30变红。30作为新的当前节点。由于30的父节点40是黑色。所以调整算法结束。调整后如图5-2所示
图5-1:插入节点10
图5-2:插入节点10调整后
六、插入节点11,如图6-1所示,由于11的父节点10是红色节点,并且11是10的右子节点。所以首先以10节点为根节点进行左旋,旋转后其的红黑树如图6-2所示。此时节点10的父节点11为红色,并且10是11节点的左子节点;此时将父节点11变黑,祖父节点20变红,以祖父节点20为根节点进行右旋。旋转后如图6-3所示。
图6-1:插入节点11
图6-2:10为根节点进行左旋后
图6-3:插入节点调整后的红黑树
下面附上只实现了插入功能的红黑树源码
rbtree.h
- #include <iostream>
- #include <queue>
- using namespace std;
- static int _rb_black_node = 0;
- static int _rb_red_node = 1;
- template<typename T>
- struct RBNode
- {
- RBNode():left(NULL),right(NULL),parent(NULL),val(T()),color(_rb_red_node){}
- RBNode(const T &v1):left(NULL),right(NULL),parent(NULL),val(v1),color(_rb_red_node){}
- RBNode *left;
- RBNode *right;
- RBNode *parent;
- int color;
- T val;
- };
-
- template<typename T>
- class RBTree
- {
- public:
- RBTree():root(NULL){}
- ~RBTree()
- {
- if(root)
- {
- Destroy(root);
- }
- }
- void print();
- void Search(const T &v1, RBNode<T> *&node);
- bool InsertUnique(const T &v1);
- void DeleteValue(const T &v1);
- void Destroy(RBNode<T> *p);
- void InsertReBalance(RBNode<T> *node);
- RBNode<T>* _rbtree_rotate_left(RBNode<T> *node);
- RBNode<T>* _rbtree_rotate_right(RBNode<T> *node);
- private:
- RBNode<T> *root;
- };
-
-
-
-
-
-
- template<typename T>
- void RBTree<T>::print()
- {
- RBNode<T> *p;
- queue<RBNode<T> *> Q;
- Q.push(root);
- while(!Q.empty())
- {
- p = Q.front();
- Q.pop();
- cout<<"节点: "<<p->val<<" ";
- if(p->left)
- {
- cout<<"left:"<<p->left->val<<"->color:"<<p->left->color<<" ";
- Q.push(p->left);
- }
- if(p->right)
- {
- cout<<"right:"<<p->right->val<<"->color:"<<p->right->color<<" ";
- Q.push(p->right);
- }
- cout<<endl<<endl;
- }
- }
-
-
-
-
-
-
-
-
- template<typename T>
- void RBTree<T>::Search(const T &v1,RBNode<T> *&node)
- {
- RBNode<T> *p = root;
- node = NULL;
- while(p)
- {
- if(p->val == v1)
- {
- node = p;
- break;
- }
- else if(p->val < v1)
- {
- node = p;
- p = p->right;
- }
- else
- {
- node = p;
- p = p->left;
- }
- }
- }
-
- template<typename T>
- bool RBTree<T>::InsertUnique(const T &v1)
- {
- RBNode<T> *parent = NULL;
- RBNode<T> *newNode = new RBNode<T>(v1);
- Search(v1, parent);
- if(parent == NULL)
- {
- root = newNode;
- root->color = _rb_black_node;
- return true;
- }
- if(parent->val == v1)
- return false;
-
- if(v1 < parent->val)
- {
- parent->left = newNode;
- }
- else
- {
- parent->right = newNode;
- }
- newNode->parent = parent;
- InsertReBalance(newNode);
- return true;
- }
-
-
-
-
-
-
-
- template<typename T>
- void RBTree<T>::InsertReBalance(RBNode<T> *node)
- {
- RBNode<T> *parent = node->parent;
- RBNode<T> *grandParent = NULL;
- while(parent && parent->color==_rb_red_node)
- {
- grandParent = parent->parent;
- if(parent == grandParent->left)
- {
- RBNode<T> *uncle = grandParent->right;
- if(uncle && uncle->color == _rb_red_node)
- {
-
- parent->color = _rb_black_node;
- uncle->color = _rb_black_node;
- grandParent->color = _rb_red_node;
- node = grandParent;
- parent = grandParent->parent;
- }
- else
- {
- if(node == parent->right)
- {
-
-
- node = _rbtree_rotate_left(parent);
- parent = node->parent;
- grandParent = parent->parent;
- }
-
-
-
- parent->color = _rb_black_node;
- grandParent->color = _rb_red_node;
- _rbtree_rotate_right(grandParent);
- }
- }
- else
- {
- RBNode<T> *uncle = grandParent->left;
- if(uncle && uncle->color == _rb_red_node)
- {
- uncle->color = _rb_black_node;
- parent->color = _rb_black_node;
- grandParent->color = _rb_red_node;
- node = grandParent;
- parent = node->parent;
- }
- else
- {
- if(node == parent->left)
- {
- node = _rbtree_rotate_right(parent);
- parent = node->parent;
- grandParent = parent->parent;
- }
- parent->color = _rb_black_node;
- grandParent->color = _rb_red_node;
- _rbtree_rotate_left(grandParent);
- }
- }
- }
- root->color = _rb_black_node;
- }
-
-
-
-
-
-
- template<typename T>
- RBNode<T> *RBTree<T>::_rbtree_rotate_left(RBNode<T> *x)
- {
- RBNode<T> *y = x->right;
- if(y == NULL)
- {
- return x;
- }
-
- x->right = y->left;
- if(y->left)
- y->left->parent = x;
- if(root == x)
- {
- root = y;
- }
- else
- {
- if(x == x->parent->left)
- {
-
- x->parent->left = y;
- }
- else
- {
- x->parent->right = y;
- }
-
- y->parent = x->parent;
- }
-
- y->left = x;
-
- x->parent = y;
- return x;
- }
-
-
-
-
-
-
-
- template<typename T>
- RBNode<T>* RBTree<T>::_rbtree_rotate_right(RBNode<T> *x)
- {
- RBNode<T> *y = x->left;
- if(y == NULL)
- {
- return x;
- }
- x->left = y->right;
- if(y->right)
- y->right->parent = x;
- if(root == x)
- {
- root = y;
- }
- else
- {
- if(x == x->parent->left)
- {
- x->parent->left = y;
- }
- else
- {
- x->parent->right = y;
- }
- y->parent = x->parent;
- }
- y->right = x;
- x->parent = y;
- return x;
- }
-
-
-
-
-
-
- template<typename T>
- void RBTree<T>::Destroy(RBNode<T> *p)
- {
- if(p->left)
- {
- Destroy(p->left);
- }
- if(p->right)
- {
- Destroy(p->right);
- }
- delete p;
- }
插入节点的程序:
- #include "rbtree.h"
- #include <iostream>
- using namespace std;
-
- int main()
- {
- RBTree<int> obj;
- obj.InsertUnique(30);
- obj.InsertUnique(40);
- obj.InsertUnique(50);
- obj.InsertUnique(20);
- obj.InsertUnique(35);
- obj.InsertUnique(10);
- obj.InsertUnique(11);
- obj.print();
- return 0;
- }