底层实现红黑树_stl map底层之红黑树插入步骤详解与代码实现 | 学步园
本篇文章并沒有詳細的講解紅黑樹各方面的知識,只是以圖形的方式對紅黑樹插入節點需要進行調整的過程進行的解釋。
最近在看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都是紅色節點。解決方法是將父節點及叔節點變黑,祖父節點變紅。祖父節點變成新的當前節點重新進行
圖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
#include
using namespace std;
static int _rb_black_node = 0;
static int _rb_red_node = 1;
template
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;
intcolor;
Tval;
};
template
class RBTree
{
public:
RBTree():root(NULL){}
~RBTree()
{
if(root)
{
Destroy(root);
}
}
voidprint();
voidSearch(const T &v1, RBNode *&node);
boolInsertUnique(const T &v1);
voidDeleteValue(const T &v1);
voidDestroy(RBNode *p);
voidInsertReBalance(RBNode *node);
RBNode*_rbtree_rotate_left(RBNode *node);
RBNode* _rbtree_rotate_right(RBNode *node);
private:
RBNode*root;
};
/*
*
* 打印紅黑樹的節點信息
*
*/
template
void RBTree::print()
{
RBNode *p;
queue *> Q;
Q.push(root);
while(!Q.empty())
{
p = Q.front();
Q.pop();
cout<val<
if(p->left)
{
cout<left->val<color:"<left->color<
Q.push(p->left);
}
if(p->right)
{
cout<right->val<color:"<right->color<
Q.push(p->right);
}
cout<
}
}
/*
*
* 搜索v1在紅黑樹中出現的位置,如果v1在紅黑樹中則node節點為
* 值為v1所在紅黑樹中的節點。
* 否則node節點為如果將v1插入到紅黑樹中的父節點
*
*/
template
void RBTree::Search(const T &v1,RBNode *&node)
{
RBNode *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
bool RBTree::InsertUnique(const T &v1)
{
RBNode *parent = NULL;
RBNode *newNode = new RBNode(v1);
Search(v1, parent);
if(parent == NULL)
{//紅黑樹為空,當前插入的節點為根節點。插入后將根顏色變為黑
root = newNode;
root->color = _rb_black_node;
return true;
}
if(parent->val == v1)//v1已經存在紅黑樹中。不再插入
return false;
if(v1 < parent->val)
{
parent->left = newNode;
}
else
{
parent->right = newNode;
}
newNode->parent = parent;
InsertReBalance(newNode);
return true;
}
/*
*
* 插入節點后進行調整,
* 使所有節點滿足紅黑樹的性質
*
*/
template
void RBTree::InsertReBalance(RBNode *node)
{
RBNode *parent = node->parent;
RBNode *grandParent = NULL;
while(parent && parent->color==_rb_red_node)
{
grandParent = parent->parent;
if(parent == grandParent->left)
{//父節點為祖父節點的左兒子
RBNode *uncle = grandParent->right;
if(uncle && uncle->color == _rb_red_node)
{//情形1 父節點與叔節點都為紅
//解決方法父與叔變黑,祖父變黑。祖父變為新的當前節點重新進入算法
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)
{//情形2,叔為黑,當前節點為其父節點的右子節點
//解決方法:以父節點為根進行左旋
//操作后將轉換為情形3
node = _rbtree_rotate_left(parent);
parent = node->parent;
grandParent = parent->parent;
}
//情形3父為紅,當前節點為父節點的左子節點
//解決方法:父節點變黑,祖父節點變紅,以
//祖父節點為根節點進行右旋
parent->color = _rb_black_node;
grandParent->color = _rb_red_node;
_rbtree_rotate_right(grandParent);
}
}
else
{//父節點為祖父節點的右子節點,情況與上面相同
RBNode *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
RBNode *RBTree::_rbtree_rotate_left(RBNode *x)
{
RBNode *y = x->right;
if(y == NULL)
{
return x;
}
//x的右節點為y的左節點
x->right = y->left;
if(y->left)//如果y的左節點存在,其父節點為y
y->left->parent = x;
if(root == x)
{//x為root,旋轉后y為新的root根節點
root = y;
}
else
{
if(x == x->parent->left)
{//如果x為其父節點的左子節點。
//x的父節點的新左子節點為y
x->parent->left = y;
}
else
{
x->parent->right = y;
}
//y的父節點為x的父節點
y->parent = x->parent;
}
//y的左子節點為x
y->left = x;
//x的父節點為y
x->parent = y;
return x;
}
/*
*
* 右旋
* 分析其邏輯與左旋代碼類似
*
*/
template
RBNode* RBTree::_rbtree_rotate_right(RBNode *x)
{
RBNode *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
void RBTree::Destroy(RBNode *p)
{
if(p->left)
{
Destroy(p->left);
}
if(p->right)
{
Destroy(p->right);
}
delete p;
}
插入節點的程序:
#include "rbtree.h"
#include
using namespace std;
int main()
{
RBTree 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;
}
總結
以上是生活随笔為你收集整理的底层实现红黑树_stl map底层之红黑树插入步骤详解与代码实现 | 学步园的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python排序的方法_python中排
- 下一篇: java 词频_java程序:统计单词词