最近一直忙于校招的笔试,STL的深入理解系列也耽搁了好几天,再加上!红黑树真的是超级超级难理解,超级超级复杂,参考了好多博客上的大神的理解才稍微明白一点,勉强入个门,下面请以一个菜鸟的角度跟着我一起学习STL的红黑树吧。
概述
红黑树是平衡二叉搜索树的一种,其通过特定的操作来保持二叉查找树的平衡。首先,我们来复习一下二叉查找树的知识,建议如果对二叉查找树不理解的先去搜一下相关博客来了解一下。
二叉搜索树是指一个空树或者具有以下性质的二叉树:
- 任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 任意节点的左、右子树也分别为二叉查找树;
- 没有键值相等的节点
我们知道,一颗由n个节点随机构造的二叉搜索树的高度为logn,但是,由于输入值往往不够随机,导致二叉搜索树可能失去平衡,造成搜索效率低下的情况。从而,引出了平衡二叉搜索树的概念。对于“平衡”这个约束不同的结构有不同的规定,如AVL树要求任何节点的两个子树的高度最大差别为1,可谓是高度平衡啊;而红黑树仅仅确保没有一条路径会比其他路径长出两倍,因而达到接近平衡的目的。红黑数不仅是一个平衡二叉搜索树,而且还定义了相当多的约束来确保插入和删除等操作后能达到平衡。
那么,红黑树究竟是怎么定义,来使得能够达到平衡的目的呢?我们接着看下去。
红黑树的定义
红黑树既然属于二叉搜索树的一种,当然需要满足上述二叉搜索树的性质,除此之外,红黑树还为每一个节点增加了一个存储位来表示节点的颜色属性,它可以为red或者black,通过对任何一条从根到叶子节点的路径上每个点进行着色方式的限制,来确保没有一条路径会比其他路径长出两倍,因而达到接近平衡的目的。
那么,红黑树是如何进行着色的呢?下面引出了红黑树的五条性质:
- 每个节点或者是黑色,或者是红色。
- 根节点是黑色。
- 每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
- 如果一个节点是红色的,则它的子节点必须是黑色的。
- 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
正是这五条性质,使得红黑树的高度能保持在logn,从而达到平衡的目的,进而使得其在查找、插入和删除的时间复杂度最坏为O(logn),下面就是一棵典型的红黑树。
注: 因本人能力有限可能无法将红黑树讲得很清楚全面,而且STL红黑树的实现也较为复杂,建议先到下面推荐的几篇博客里去补补知识
红黑树的节点结构
红黑树的节点在二叉树的节点结构上增加了颜色属性,而且,为了更好的进行插入和删除操作,进而增加了指向父节点的指针。为了更好的弹性,STL红黑树的节点采用双层设计,将不依赖模板的参数提取出来,作为base结构,然后用带模板的节点结构取继承它。下面是红黑树节点结构的源码:
typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red = false;
const __rb_tree_color_type __rb_tree_black = true;
struct __rb_tree_node_base
{
typedef __rb_tree_color_type color_type;
typedef __rb_tree_node_base* base_ptr;
color_type color;
base_ptr parent;
base_ptr left;
base_ptr right;
static base_ptr minimum(base_ptr x)
{
while (x->left != 0) x = x->left;
return x;
}
static base_ptr maximum(base_ptr x)
{
while (x->right != 0) x = x->right;
return x;
}
};
template <class Value>
struct __rb_tree_node : public __rb_tree_node_base
{
typedef __rb_tree_node<Value>* link_type;
Value value_field;
};
- 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
- 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
红黑树的迭代器
为了将RBtree实现为一个泛型容器,迭代器的设计很关键。我们要考虑它的型别,以及前进(increment)、后退(devrement)、提领(dereference)和成员访问(member access)等操作。
迭代器和节点一样,采用双层设计,STL红黑树的节点__rb_tree_node继承于__rb_tree_node_base;STL的迭代器结构__rb_tree_iterator继承于__rb_tree_base_iterator,我们可以用一张图来解释这样的设计目的。
将这些分开设计,可以保证对节点和迭代器的操作更具有弹性。下面来看迭代器的源码:
struct __rb_tree_base_iterator
{
typedef __rb_tree_node_base::base_ptr base_ptr;
typedef bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
base_ptr node;
void increment()
{
if (node->right != 0) {
node = node->right;
while (node->left != 0)
node = node->left;
}
else {
base_ptr y = node->parent;
while (node == y->right) {
node = y;
y = y->parent;
}
if (node->right != y)
node = y;
}
}
void decrement()
{
if (node->color == __rb_tree_red &&
node->parent->parent == node)
node = node->right;
else if (node->left != 0) {
base_ptr y = node->left;
while (y->right != 0)
y = y->right;
node = y;
}
else {
base_ptr y = node->parent;
while (node == y->left) {
node = y;
y = y->parent;
}
node = y;
}
}
}
template <class Value, class Ref, class Ptr>
struct __rb_tree_iterator : public __rb_tree_base_iterator
{
typedef Value value_type;
typedef Ref reference;
typedef Ptr pointer;
typedef __rb_tree_iterator<Value, Value&, Value*> iterator;
typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator;
typedef __rb_tree_iterator<Value, Ref, Ptr> self;
typedef __rb_tree_node<Value>* link_type;
__rb_tree_iterator() {}
__rb_tree_iterator(link_type x) { node = x; }
__rb_tree_iterator(const iterator& it) { node = it.node; }
reference operator*() const { return link_type(node)->value_field; }
pointer operator->() const { return &(operator*()); }
self& operator++() { increment(); return *this; }
self operator++(int) {
self tmp = *this;
increment();
return tmp;
}
self& operator--() { decrement(); return *this; }
self operator--(int) {
self tmp = *this;
decrement();
return tmp;
}
};
- 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
- 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
在上述源代码中,一直提到STL RBTree特殊节点header的设计,这个会在RBTree结构中讲到,下面跟着我一起继续往下看吧。
红黑树的数据结构
有了上面的节点和迭代器设计,就能很好的定义出一颗RBTree了。废话不多说,一步一步来剖析源代码吧。
template <class Key, class Value, class KeyOfValue, class Compare,
class Alloc = alloc>
class rb_tree {
protected:
typedef void* void_pointer;
typedef __rb_tree_node_base* base_ptr;
typedef __rb_tree_node<Value> rb_tree_node;
typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;
typedef __rb_tree_color_type color_type;
public:
typedef Key key_type;
typedef Value value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef rb_tree_node* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
protected:
size_type node_count;
link_type header;
Compare key_compare;
link_type& root() const { return (link_type&) header->parent; }
link_type& leftmost() const { return (link_type&) header->left; }
link_type& rightmost() const { return (link_type&) header->right; }
static link_type& left(link_type x) { return (link_type&)(x->left); }
static link_type& right(link_type x) { return (link_type&)(x->right); }
static link_type& parent(link_type x) { return (link_type&)(x->parent); }
static reference value(link_type x) { return x->value_field; }
static const Key& key(link_type x) { return KeyOfValue()(value(x)); }
static color_type& color(link_type x) { return (color_type&)(x->color); }
static link_type& left(base_ptr x) { return (link_type&)(x->left); }
static link_type& right(base_ptr x) { return (link_type&)(x->right); }
static link_type& parent(base_ptr x) { return (link_type&)(x->parent); }
static reference value(base_ptr x) { return ((link_type)x)->value_field; }
static const Key& key(base_ptr x) { return KeyOfValue()(value(link_type(x)));}
static color_type& color(base_ptr x) { return (color_type&)(link_type(x)->color); }
static link_type minimum(link_type x) {
return (link_type) __rb_tree_node_base::minimum(x);
}
static link_type maximum(link_type x) {
return (link_type) __rb_tree_node_base::maximum(x);
}
public:
typedef __rb_tree_iterator<value_type, reference, pointer> iterator;
typedef __rb_tree_iterator<value_type, const_reference, const_pointer>
const_iterator;
public:
Compare key_comp() const { return key_compare; }
iterator begin() { return leftmost(); }
const_iterator begin() const { return leftmost(); }
iterator end() { return header; }
const_iterator end() const { return header; }
bool empty() const { return node_count == 0; }
size_type size() const { return node_count; }
size_type max_size() const { return size_type(-1); }
};
- 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
- 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
我们看到,在RBTree的数据结构中,定义了RBTree节点和迭代器,然后添加了header节点,以及node_count参数,其他都是一下简单的函数声明和类型声明。除此之外,并没有过多的增加东西。这里理解起来还是比较简单,至于header有什么作用,请继续往下看。
红黑树的构造与内存管理
红黑树的构造函数
红黑树的空构造函数将创建一个空树,此”空树“非彼二叉树的空树也。空构造函数首先配置一个节点空间,使header指向该节点空间,然后将header的leftmost和rightmost指向自己,父节点指向0。非空的STL RBTree中,header和root之间互为父节点,然后header的leftmost始终指向该树的最小值节点,rightmost始终指向该树的最大值节点,其示例图如下(左图为空树,右图为非空树):
下面来看看它的构造函数代码吧:
template <class Key, class Value, class KeyOfValue, class Compare,
class Alloc = alloc>
class rb_tree {
protected:
typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;
link_type get_node() { return rb_tree_node_allocator::allocate(); }
link_type create_node(const value_type& x) {
link_type tmp = get_node();
__STL_TRY {
construct(&tmp->value_field, x);
}
__STL_UNWIND(put_node(tmp));
return tmp;
}
void init() {
header = get_node();
color(header) = __rb_tree_red;
root() = 0;
leftmost() = header;
rightmost() = header;
}
rb_tree(const Compare& comp = Compare())
: node_count(0), key_compare(comp) { init(); }
rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x)
: node_count(0), key_compare(x.key_compare)
{
header = get_node();
color(header) = __rb_tree_red;
if (x.root() == 0) {
root() = 0;
leftmost() = header;
rightmost() = header;
}
else {
__STL_TRY {
root() = __copy(x.root(), header);
}
__STL_UNWIND(put_node(header));
leftmost() = minimum(root());
rightmost() = maximum(root());
}
node_count = x.node_count;
}
template <class K, class V, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<K, V, KeyOfValue, Compare, Alloc>::link_type
rb_tree<K, V, KeyOfValue, Compare, Alloc>::__copy(link_type x, link_type p) {
link_type top = clone_node(x);
top->parent = p;
__STL_TRY {
if (x->right)
top->right = __copy(right(x), top);
p = top;
x = left(x);
while (x != 0) {
link_type y = clone_node(x);
p->left = y;
y->parent = p;
if (x->right)
y->right = __copy(right(x), y);
p = y;
x = left(x);
}
}
__STL_UNWIND(__erase(top));
return top;
}
link_type clone_node(link_type x) {
link_type tmp = create_node(x->value_field);
tmp->color = x->color;
tmp->left = 0;
tmp->right = 0;
return tmp;
}
}
- 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
- 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
红黑树的析构函数
析构函数负责清除和释放红黑树上的每一个节点,并且初始化该红黑树为空树,即恢复header为初始状态
template <class Key, class Value, class KeyOfValue, class Compare,
class Alloc = alloc>
class rb_tree {
protected:
void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }
void destroy_node(link_type p) {
destroy(&p->value_field);
put_node(p);
}
~rb_tree() {
clear();
put_node(header);
}
void clear() {
if (node_count != 0) {
__erase(root());
leftmost() = header;
root() = 0;
rightmost() = header;
node_count = 0;
}
}
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__erase(link_type x) {
while (x != 0) {
__erase(right(x));
link_type y = left(x);
destroy_node(x);
x = y;
}
}
}
- 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
- 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
红黑树的插入
红黑树在插入节点的时候,会破坏其平衡,这时候需要旋转和变色来使红黑树重新达到平衡。这才是红黑树的精髓所在啊!所以这部分很长,大家耐心看,最好拿纸笔画一下。
AVL树的插入
我们先来看看AVL树的旋转问题。AVL树中,插入一个节点后,有可能会破坏二叉树的平衡,这时候可以通过左旋和右旋函数来使其重新恢复平衡。
通常破坏AVL树平衡的插入情况有如下四种:
- 插入点位于X节点的左子节点的左子树,左左
- 插入点位于X节点的右子节点的右子树,右右
- 插入点位于X节点的左子节点的右子树,左右
- 插入点位于X节点的右子节点的左子树,右左
其中,情况1和2彼此对称,称为外侧插入,可以采用单旋转操作来调整;情况3和4彼此对称,称为内侧插入,需要采用双旋转操作来调整。
外侧插入
对于外侧插入,我们通常采用一次旋转就能解决问题,请看下面两种外侧插入的示意图,其中左图对应上述情况1,右图对应上述情况2。
对于左图的情况,采用一次右旋操作,可以使二叉树重新恢复平衡,操作示意图如下所示:
对于右图的情况,采用一次左旋操作,可以使二叉树重新恢复平衡,操作示意图如下所示:
内侧插入
对于内侧插入,通常比较复杂,需要采用两次旋转操作来调整平衡。请看下面的内侧插入的示意图,其中左图对于上述情况3,右图对应上述情况4。
对于左图的情况,需要先进行依次左旋操作,再进行一次右旋操作即可调整平衡,操作示意图如下:
对于右图的情况,需要先进行依次右旋操作,再进行一次左旋操作即可调整平衡,操作示意图如下:
红黑树的插入
有了上面的单旋转和双旋转知识,应该就很好理解红黑数的平衡调整过程。红黑树在插入节点的时候,不仅需要考虑插入导致的不平衡,还要考虑颜色属性是否满足其性质要求。为了更清楚的表达整个过程,我们先来定义一下几个标示量,使用X来表示一个新插入的节点,使用P来表示新插入节点的父节点,使用U来表示P节点的兄弟节点,使用G来表示P节点的父亲节点,使用N代表NIL节点。于是,可以将插入情况分为一下几类:
树为空
新插入的节点为红色,因为此时树为空,那么插入该节点后只需要把节点颜色调整为黑色即可。
父节点为黑
如果插入的节点的父节点为黑色,那么插入一个红节点将不会影响树的平衡,直接插入即可。这里就体现了黑红树的优势,O(1)时间内就能判断是否破坏了平衡,如果这里是AVL树的话就需要进行一次O(logn)判断是否平衡。
父节点为红色
当父节点为红色的时候,就不满足条件4,即父节点为红色的时候,子节点必须为黑色,而新加入的节点为红色。这个时候需要考虑如下两种情况
1)叔父节点为红色
这种情况下,需要将父节点和叔父节点变为黑色,将祖父节点变为红色即可,不过如果祖父节点为红色的话,还是违反了红黑树的性质,此时必须执行一个继续向上迭代的程序来对红黑树的颜色进行调整,最后需要将根节点设置为黑色,如下图所示:
2)叔父节点为黑色(Nil节点为黑)
这时候,需要对其进行旋转操作,和上面AVL树的旋转一样,分为4种情况,下面一一举例来说明这四种情况:
红黑树的插入源代码分析
红黑树的插入主要靠以下三个函数来实现:
inline void
__rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)
inline void
__rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)
inline void
__rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
iterator __insert(base_ptr x, base_ptr y, const value_type& v);
上述三个函数就代表了上一小节示例图中的左旋,右旋和变色的源代码接口。
另外,STL还提供了两个个接口函数,如下:
iterator insert_equal(const value_type& x);
iterator insert_unique(iterator position, const value_type& x);
下面就针对这五个函数一一来分析一下他们的源代码(以insert_unique为例):
template<class Key , class Value , class KeyOfValue , class Compare , class Alloc>
pair<typename rb_tree<Key , Value , KeyOfValue , Compare , Alloc>::iterator , bool>
rb_tree<Key , Value , KeyOfValue , Compare , Alloc>::insert_unique(const Value &v)
{
rb_tree_node* y = header;
rb_tree_node* x = root();
bool comp = true;
while(x != 0)
{
y = x;
comp = key_compare(KeyOfValue()(v) , key(x));
x = comp ? left(x) : right(x);
}
iterator j = iterator(y);
if(comp)
{
if(j == begin())
return pair<iterator , bool>(_insert(x , y , z) , true);
else
--j;
}
if(key_compare(key(j.node) , KeyOfValue()(v) ))
return pair<iterator , bool>(_insert(x , y , z) , true);
return pair<iterator , bool>(j , false);
}
template<class Key , class Value , class KeyOfValue , class Compare , class Alloc>
typename<Key , Value , KeyOfValue , Compare , Alloc>::_insert(base_ptr x_ , base_ptr y_ , const Value &v)
{
link_type x = (link_type) x_;
link_type y = (link_type) y_;
link_type z;
if(y == header || x != 0 || key_compare(KeyOfValue()(v) , key(y) ))
{
z = create_node(v);
left(y) = z;
if(y == header)
{
root() = z;
rightmost() = z;
}
else if(y == leftmost())
leftmost() = z;
}
else
{
z = create_node(v);
right(y) = z;
if(y == rightmost())
rightmost() = z;
}
parent(z) = y;
left(z) = 0;
right(z) = 0;
_rb_tree_rebalance(z , header->parent);
++node_count;
return iterator(z);
}
inline void _rb_tree_rebalance(_rb_tree_node_base* x , _rb_tree_node_base*& root)
{
x->color = _rb_tree_red;
while(x != root && x->parent->color == _rb_tree_red)
{
if(x->parent == x->parent->parent->left)
{
_rb_tree_node_base* y = x->parent->parent->right;
if(y && y->color == _rb_tree_red)
{
x->parent->color = _rb_tree_black;
y->color = _rb_tree_black;
x->parent->parent->color = _rb_tree_red;
x = x->parent->parent;
}
else
{
if(x == x->parent->right)
{
x = x->parent;
_rb_tree_rotate_left(x , root);
}
x->parent->color = _rb_tree_black;
x->parent->parent->color = _rb_tree_red;
_rb_tree_rotate_right(x->parent->parent , root);
}
}
else
{
_rb_tree_node_base* y = x->parent->parent->left;
if(y && y->color == _rb_tree_red)
{
x->parent->color = _rb_tree_black;
y->color = _rb_tree_black;
x->parent->parent->color = _rb_tree_red;
x = x->parent->parent;
}
else
{
if(x == x->parent->left)
{
x = x->parent;
_rb_tree_rotate_right(x , root);
}
x->parent->color = _rb_tree_black;
x->parent->parent->color = _rb_tree_red;
_rb_tree_rotate_left(x->parent->parent , root);
}
}
}
root->color = _rb_tree_black;
}
inline void _rb_tree_rotate_left(_rb_tree_node_base* x , _rb_tree_node_base*& root)
{
_rb_tree_node_base* y = x->right;
x->right = y->left;
if(y->left != 0)
y->left->parent = x;
y->parent = x->parent;
if(x == root)
root = y;
else if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
inline void _rb_tree_rotate_right(_rb_tree_node_base* x , _rb_tree_node_base*& root)
{
_rb_tree_node_base* y = x->left;
x->left = y->right;
if(y->right != 0)
y->right->parent = x;
y->parent = x->parent;
if(x == root)
root = y;
else if(x == x->parent->right)
x->parent->right = y;
else
x->parent->left = y;
y->right = x;
x->parent = y;
}
- 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
- 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
红黑树的删除
红黑树在删除节点后,需要调整以使得红黑树保持平衡,由于删除后调节平衡实在太复杂,本文就不做分析,只提供其接口函数。
如果对其感兴趣的话,可以参考一下这篇博文:(图解)红黑树的插入和删除
inline __rb_tree_node_base*
__rb_tree_rebalance_for_erase(__rb_tree_node_base* z,
__rb_tree_node_base*& root,
__rb_tree_node_base*& leftmost,
__rb_tree_node_base*& rightmost);
STL为红黑树提供了以下删除操作的节点函数:
void erase(iterator position);
void erase(iterator first, iterator last);
void clear();
下面来看看它们的源码实现:
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline void
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator position) {
link_type y = (link_type) __rb_tree_rebalance_for_erase(position.node,
header->parent,
header->left,
header->right);
destroy_node(y);
--node_count;
}
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator first,
iterator last) {
if (first == begin() && last == end())
clear();
else
while (first != last) erase(first++);
}
void clear() {
if (node_count != 0) {
__erase(root());
leftmost() = header;
root() = 0;
rightmost() = header;
node_count = 0;
}
}
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__erase(link_type x) {
while (x != 0) {
__erase(right(x));
link_type y = left(x);
destroy_node(x);
x = y;
}
}
- 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
- 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
红黑树的元素搜寻
find函数用于查找是否存在键值为k的节点。
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k) {
link_type y = header;
link_type x = root();
while (x != 0)
if (!key_compare(key(x), k))
y = x, x = left(x);
else
x = right(x);
iterator j = iterator(y);
return (j == end() || key_compare(k, key(j.node))) ? end() : j;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
另外,STL的红黑树还针对multiset和multimap提供了几个搜寻函数,分别如下:
size_type count(const key_type& x)
pair<iterator,iterator> equal_range(const key_type& x);
iterator lower_bound(const key_type& x);
iterator upper_bound(const key_type& x);
其实现函数也一并贴出来,让大家好理解一下吧。
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::size_type
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::count(const Key& k) {
pair<const_iterator, const_iterator> p = equal_range(k);
size_type n = 0;
distance(p.first, p.second, n);
return n;
}
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator,
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::equal_range(const Key& k) {
return pair<iterator, iterator>(lower_bound(k), upper_bound(k));
}
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::lower_bound(const Key& k) {
link_type y = header;
link_type x = root();
while (x != 0)
if (!key_compare(key(x), k))
y = x, x = left(x);
else
x = right(x);
return iterator(y);
}
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::upper_bound(const Key& k) {
link_type y = header;
link_type x = root();
while (x != 0)
if (key_compare(k, key(x)))
y = x, x = left(x);
else
x = right(x);
return iterator(y);
}