您的位置:首页 > 其它

红黑树RB_tree

2016-05-10 18:01 309 查看
红黑树也是一种而叉搜索树,因此二叉搜索树的性质红黑树都具有,同时,我们知道为了避免最坏情况下的二叉搜索树(就是高度不平衡的情况)衍生出了AVL树,使其任何节点的左右子树的高度差相差最多1,从而达到平衡,以确保最坏情况下的搜索效率。当然红黑树为了比较好的搜索效率降低了对平衡的要求,但是红黑树仍然具有良好的平衡状态。

AVL树与RB_tree

AVL树也称为高度平衡树,其插入,删除,查找在平均和最坏情况下都是O(log n),增加和删除要通过一次或多次树的旋转来重新平衡这个树。

RB_tree并不追求完全平衡,只要求部分达到平衡要求,降低了对旋转的要求,从而提高了性能,红黑树能够以O(log 2 n)的时间复杂度进行插入,删除,查找,此外由于它的设计任何不平衡都会在3次旋转之内解决。相比较而言红黑树和AVL树的算法时间复杂度相同,但统计性能比AVL树高。同时,红黑树的应用比AVL树广泛

例如:(1)红黑树广泛应用于c++的STL中,比如关联式容器set, map,multiset, multimap都以RB_tree为底层机制。

(2)epoll在内核中的实现,用红黑树管理事件块。

(3)linux进程调度上,用红黑树管理进程控制块。

(4)nginx中用红黑树管理timer

下面自己分析了SGI中的stl_tree.h源码的分析

#ifndef __SGI_STL_INTERNAL_TREE_H

#define __SGI_STL_INTERNAL_TREE_H

//RB-tree的节点设计

//设计思路节点设计分为两层__rb_tree_node继承__rb_tree_node_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)

{

wile(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;

};

//因为红黑树是非线性的结构,所以要找到一个节点的前面的节点或者后面的节点比较麻烦,且红黑树节点的显示是

//按中序排列的,所以对迭代器的前进和后退操作要借用内置函数increment()和decrement()

//RB_tree迭代器结构设计,也是采用双层迭代其结构

struct __rb_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;

//迭代器的前进操作operator++()调用了基层迭代器的increment()

//(1)如果node有右子树,但这个右子树没有左子节点,那么node前进一个节点为node->right.如果这个右子 树有左子树,那么node后面的节点就是这个左子树的最左边的那个节点。

//(2)如果node没有右子树,并且node是node->parent的左子树,那么node后面的节点是node->parent。如果node是node->parent的右子树,则一直上朔,直到不再是右子节点比如为y,那么node后面的节点是就是y->parent这个节点


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;

}

}

}

//迭代器的后退操作operator--()调用基层迭代器ecrement()

//(1)node有左子树,且node的左子树没有右子树,那么node前面的节点就是node->left。如果node的左子树有右子树,那么node前面的节点就是这个右子树的最右边的节点。

//(2)node没有左子树,且node为其父节点的左节点,那么就上朔直到node不为node->parent的左节点,那么node的前面的节点就是这个node->parent。如果为其父节点的右节点,那么node的前面的节点就是node->parent。


void decrement()

{

//判断node就是header这个虚节点

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<calss 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){ode = it.node;}

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;

}

};

inline bool operator==(const __rb_tree_base_iterator& x,

const __rb_tree_base_iterator& y)

{

return x.node == y.node;

}

inline bool operator!=(const __rb_tree_base_iterator& x,

const __rb_tree_base_iterator& y)

{

return x.node != y.node;

}

//RB_tree数据结构

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;

public:

rb_tree(const Compare& comp = Compare())

: node_count(0), key_compare(comp) { init(); }

~rb_tree() {

clear();

put_node(header);

}

rb_tree<Key, Value, KeyOfValue, Compare, Alloc>&

operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x);

protected:

get_node(){return rb_tree_node_allocator::allocate();}

void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }

link_type create_node(const value_type& x) {

link_type tmp = get_node();

put_node(tmp);

return tmp;

}

//复制一个节点

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;

}

void destroy_node(link_type p) {

destroy(&p->value_field);

put_node(p);

}

protected:

size_type node_count; // keeps track of size of tree

link_type header;

Compare key_compare;

//这三个函数方便取得header的成员

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; }

//这六个函数方便取得节点x的成员(自身做参数)自己对这12个函数没有具体搞明白为什么写两种

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); }

//这六个函数方便取得节点x的成员(以父类类型的节点做参数)

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;}

//最后的一个节点应该是rightmost但是end()指向的是最后节点的后一个节点自然就是header

iterator end(){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);}

public:

pair<iterator, bool>insert_unique(const value_type& x);

iterator insert_equal(const value_type& x);

iterator insert_unique(iterator position, const value_type& x);

iterator insert_equal(iterator position, const value_type& x);

};

//这里的返回值是个RB_tree迭代器,所以前面加那么多

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>::insert_equal(const value& v)

{

link_type y = header;

link_type x = root();

while(x != 0){

y = x;

x = key_compare(KetOfValue()(v), key(x)) ? left(x):right(x);

}

//x为新插入节点,Y为插入的父节点,v为插入的新值

return __insert(x, y, v);

}

template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>

//注意这一行,返回值是pair类型,pair称为对组,这样写则返回值不返回一个值,而是返回两个值,这里可以看出返回的

//第一个值是iterator类型,即返回插入点的位置。返回的第二个值是bool类型,通过true或者false来判断插入是否成功


pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool>

rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const value_type& v)

{

link_type y = header;

link_type x = root();

bool comp = true;

//从根节点开始查找适当的插入点

while(x != 0){

y = x;

comp = key_compare(KeyOfValue()(v), key(y));

//当插入的元素v<找到的插入点即y,则v往y的左边插入,否则右边

x = comp ? left(x) : right(x);

}

//这里大家要注意理解,画图可以最直观的分析,这里自己也是看了好久才弄明白

//下面的代码的作用是防止插入值重复。

//分两种情况

//(1)如果插入点的父节点是树的最左边节点,那么直接插入

//(2)如果插入点的父节点不是树的最左边的节点,这个时候要考虑到插入的新节点

// 是否可能跟已经插入的节点值重复,因此要进行回朔


iterator j = iterator(y);

//if(com)为真,也就是说当v<y,往左节点插入新值

if(comp){

if(j === begin()){

return pair<iterator, bool>(__insert(x, y, v), true);

}else{

--j;

}

}

//满足这个条件即表示新插入的键值不与已经插入的节点的键值相等

if(key_compare(key(j.node), KeyOfValue()(v))){

return pair<iterator, bool>(__insert(x, y, v), true);

}

//键值重复不进行插入操作

return pair<iterator, bool>(__insert(j, false);

}

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>::__insert(base_ptr x_, base_type y_, const value_type& v)

{

link_type x = (link_type)x_;

link_type y = (link_type)y_;

link_type z;

//当key_compare(KeyOfValue()(v), keyy(y))为真时,也就是说v<y,往y的左节点插入,分3种情况

//(1)y==header,插入的节点是root,这样就要注意要让root()=插入的节点,并且让header的左指针指向插入节点

//即leftmost()=z

//(2)y==leftmost,插入的地方是树的最左边的节点,注意的是要让header的左指针指向这个插入节点即leftmost()=z

//(3)插入的仅仅是个普通的节点,直接让父节点y的左指针指向这个插入的节点即可


if(y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))){

z = create_node(v);

//让leftmost() = z

left(y) = z;

//如果插入的节点是root节点,则让root作为header的左子节点

if(y == header){

root() = z;

rightmost = z;

//如果插入的地方是树的最左边的节点

}else if(y == leftmost()){

leftmost() = z;

}

}

//当key_compare(KeyOfValue()(v), key(y))为假时,也就是说v>y,(注意这里规定的默认的key_compare规则是小与)

//往插入点的父节点y的右节点插入,分1种情况

//这里不用判断插入点为root节点,因为规定root节点只能作为header的左子节点插入


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 iteratro(z);

}

//红黑树的旋转以及颜色的调整比较麻烦,所以大家要静下心来

//一:当插入点的父节点为祖父节点的左子树:

// (1)如果伯父节点存在且为红

// (2)如果伯父节点不存在或者为黑,

// (1)则又要判断插入节点为父节点的左子树

// (2)插入节点为父节点的右子树

//二:当插入点的父节点为祖父节点的右子树

// (1)如果伯父节点存在且为红

// (2)如果伯父节点不存在或者为黑

// (1)插入点为父节点的左子树

// (2)插入点为父节点的右子树


inline void __rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)

{

//新插入的节点必须为红节点,因为如果插入的新节点为黑节点,这样就打破了红黑树的约束条件

//红黑树要求任一节点到NULL的任何的路径,所含之黑节点数目必须相等


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 = __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;

}

//下面两个函数是红黑树节点的旋转

//x为旋转对象

//红黑树的旋转根AVL树的旋转一样,只是由于红黑树的节点又parent这个指针,所以旋转的时后要特别的注意这个指针的连接

//左旋:

//(1)将旋转目标x的右子节点Y的左子树挂在x的右子树上,

//(2)将y树挂在x的父节点上,

//(3)将y的左指针指向x;


//

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;

}

//右旋:

//(1)将旋转目标x的左子树y的右子树挂在x的左链上

//(2)将y树挂在x的父节点上

//(3)将x树挂在y的右链上


inline void __rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)

{

__rb_tree_node_base* y = x->right;

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->left){

x->parent->left = y;

}else{

x->parent->right = y;

}

y->right = x;

x->parent = y;

}

};

#endif

/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: