紅黑樹RB_tree

   紅黑樹也是一種而叉搜索樹,因此二叉搜索樹的性質紅黑樹都具有,同時,我們知道爲了避免最壞情況下的二叉搜索樹(就是高度不平衡的情況)衍生出了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

 /

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章