红黑树

当我们在使用二叉搜索树时,如果树的高度较高,对其的操作并不比对链表操作要快。原因是二叉搜索树在插入顺序基本有序时会退化为一个排序链表,所以说是不平衡的。

对二叉搜索树的改进有AVL树和红黑树。先来看红黑树,它广泛应用在STL的set和map,Java库和Linux内核等中 。

红黑树是一颗平衡的二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是RED或BLANK。通过对任何一条从根节点到叶子节点的简单路径上各个节点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似平衡的。 <!--more-->

红黑树的约束如下:

  • 每个节点要么是红色的,要么是黑色的;
  • 根节点是黑色的;
  • 如果一个节点是红色的,那么它的两个子节点都是黑色的;
  • 对每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含数目相同的黑色节点;
  • <del>每个叶子节点是黑色的(这里的叶子节点指的是NIL节点,即空节点)</del>。

红黑树的插入操作步骤如下:

  • 先按照搜索树的步骤将节点插入到相应位置,并置该节点颜色为红色。设该节点指针为cur;

  • 如果破坏了以上某些条件,则对该树进行相应的调整,步骤如下:

    *   情况1:若cur的父亲结点和叔叔节点都为红色,则进行红色提升;
    
    • 情况2:若父红叔黑或叔叔不存在,且cur为其父节点的右孩子,则令cur=parent并以父节点为根进行旋转;
    • 情况3:若父红叔黑或叔叔不存在,且cur为其父节点的左孩子,则将父节点变为黑色,祖父节点变为红色并以祖父节点为根进行旋转;

代码如下:

once
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include&lt;iostream&gt;
using namespace std;
enum Color
{
RED,
BLANK,
};
template&lt;typename K,typename V&gt;
struct RBTreeNode{
K _key;
V _value;
RBTreeNode&lt;K,V&gt;* _left;
RBTreeNode&lt;K,V&gt;* _right;
RBTreeNode&lt;K,V&gt;* _parent;
Color _color;
RBTreeNode(const K&amp; key=K(),const V&amp; value=V())
:_key(key),_value(value)
,_left(NULL),_right(NULL)
,_parent(NULL)
,_color(RED)
{}
};
template&lt;typename K,typename V&gt;
class RBTree{
typedef RBTreeNode&lt;K,V&gt; Node;
public:
RBTree()
:_root(nil)
{}
bool Insert(const K&amp; key,const V&amp; value)
{
Node* s=new Node(key,value);
Node* parent=nil;
Node* cur=_root;
while(cur!=nil)
{
parent=cur;
if(cur-&gt;_key&gt;cur-&gt;_key)
cur=cur-&gt;_left;
else
cur=cur-&gt;_right;
}
cur-&gt;_parent=parent;
if(parent==nil)
_root=s;
else if(s-&gt;_key&gt;parent-&gt;_key)
parent-&gt;_right=s;
else
parent-&gt;_left=s;
s-&gt;_left=s-&gt;_right=nil;
//s-&gt;_color=RED;
RB_INSERT_FIX(s);
}
bool Remove(const K&amp; key);
Node* Find(const K&amp; key);
bool IsBalance();
protected:
void RotateL(Node* root)
{
if(root==NULL)
return;
Node* parent=root;
Node* subR=parent-&gt;_right;
Node* subRL=subR-&gt;_left;
parent-&gt;_right=subRL;
if(subRL!=NULL)
subRL-&gt;_parent=parent;
Node* ppNode=parent-&gt;_parent;
subR-&gt;_left=parent;
parent-&gt;_parent=subR;
if(ppNode!=NULL)
{
if(ppNode-&gt;_left==parent)
ppNode-&gt;_left=subR;
else
ppNode-&gt;_right=subR;
}
else
{
_root=subR;
}
subR-&gt;_parent=ppNode;
parent-&gt;_bf = subR-&gt;_bf = 0;
}
void RotateR(Node* root)
{
if(root==NULL)
return;
Node* parent=root;
Node* subL=parent-&gt;_left;
Node* subLR=subL-&gt;_right;
parent-&gt;_left=subLR;
if(subLR!=NULL)
subLR-&gt;_parent=parent;
Node* ppNode=parent-&gt;_parent;
subL-&gt;_right=parent;
parent-&gt;_parent=subL;
if(ppNode!=NULL)
{
if(ppNode-&gt;_left==parent)
ppNode-&gt;_left=subL;
else
ppNode-&gt;_right=subL;
}
else
{
_root=subL;
}
subL-&gt;_parent=ppNode;
parent-&gt;_bf = subL-&gt;_bf = 0;
}
void RB_INSERT_FIX(Node* cur)
{
while(cur-&gt;_parent._color==RED)
{
Node* parent=cur-&gt;_parent;
Node* grandfather=parent-&gt;_parent;
Node* uncle;
if(parent=grandfather-&gt;_left)
{
uncle=grandfather-&gt;_right;
if(uncle-&gt;_color=RED)
{
parent-&gt;_color=BLANK;
uncle-&gt;_color=BLANK;
grandfather-&gt;_color=RED;
cur=grandfather;
}
else if(cur=parent-&gt;_right)
{
cur=parent;
rotateL(cur);
}
else
{
parent-&gt;_color=BLANK;
grandfather-&gt;_color=RED;
rotateR(grandfather);
}
}
else
{
uncle=grandfather-&gt;_left;
if(uncle-&gt;_color=RED)
{
parent-&gt;_color=BLANK;
uncle-&gt;_color=BLANK;
grandfather-&gt;_color=RED;
cur=grandfather;
}
else if(cur=parent-&gt;_left)
{
cur=parent;
rotateR(cur);
}
else
{
parent-&gt;_color=BLANK;
grandfather-&gt;_color=RED;
rotateL(grandfather);
}
}
}
_root-&gt;_color=BLANK;
}
private:
Node* _root;
static Node* nil;
};
template&lt;typename K,typename V&gt;
RBTreeNode&lt;K,V&gt;* RBTree&lt;K,V&gt;::nil=new RBTreeNode&lt;K,V&gt;();

以上

如果你有任何想法或是可以改进的地方,欢迎和我交流!

完整代码在github上:点我前往