STL源碼分析之紅黑樹

主要分析一下STL裏的紅黑樹,紅黑樹相對來說是一種較爲複雜的數據結構,具體的學習方法建議看那種帶有很多圖解的博客,先理解其原理流程,再自己寫下代碼,其實就能理解了。STL裏紅黑樹的實現有幾個特點,一個它設置了一個空頭結點header,它的左節點指向樹最小元素,有節點指向樹最大元素,實際帶有有意義值的頭結點爲root,root的父節點爲header.這使在一些插入刪除操作時要討論下特殊情況,附上代碼分析

//紅色爲false,黑色爲true
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;
};


//迭代器
struct __rb_tree_base_iterator
{
    typedef __rb_tree_node_base::base_ptr base_ptr;
    //迭代器種類爲bidirectional_iterator
    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; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
    pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_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;
    }
};

template <class Key, class Value, class KeyOfValue, class Compare,
        class Alloc = alloc>
/* key紅黑樹上存儲節點時依據的值
 * value節點的值
 * KeyOfValue仿函數
 * Compare爲比較key大小的標準
 * 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:
    //獲取一個新的節點
    link_type 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();
        __STL_TRY{
                construct(&tmp->value_field, x);
        }
        __STL_UNWIND(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;
    //header節點
    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); }

    //獲取當前節點的value
    static reference value(link_type x) { return x->value_field; }

    //通過value獲取當前節點的key
    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;

private:
    //插入
    iterator __insert(base_ptr x, base_ptr y, const value_type &v);

    //複製
    link_type __copy(link_type x, link_type p);

    //刪除
    void __erase(link_type x);

    //初始化,申請一空頭結點
    void init() {
        header = get_node();
        color(header) = __rb_tree_red;
        root() = 0;
        leftmost() = header;
        rightmost() = header;
    }

public:
    //構造函數
    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;
    }

    ~rb_tree() {
        clear();
        put_node(header);
    }

    //重載操作符=,即賦值
    rb_tree<Key, Value, KeyOfValue, Compare, Alloc> &
    operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc> &x);

    //重載操作符==
    template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>
    inline bool operator==(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc> &x,
                           const rb_tree<Key, Value, KeyOfValue, Compare, Alloc> &y) {
        return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
    }

public:
    Compare key_comp() const { return key_compare; }

    //起始迭代器是最小節點,即header結點的左節點
    iterator begin() { return leftmost(); }

    const_iterator begin() const { return leftmost(); }

    //末尾迭代器是header
    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); }
}

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_ptr y_, const Value& v) {
    /* x爲新的插入點
     * y爲要插入的點的父節點
     * v爲插入的值
     */
    link_type x = (link_type) x_;
    link_type y = (link_type) y_;
    link_type z;

    //y爲header或x不爲空或者要插入的值的key與y不重複
    if (y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))) {
        //創建並初始化值爲v的節點,爲紅色
        z = create_node(v);
        //將header的左孩子設置爲z
        left(y) = z;
        if (y == header) {

            root() = z;
            rightmost() = z;
        }
        else if (y == leftmost())
            leftmost() = z;
    }
    else {
        //否則創建值爲v的節點
        z = create_node(v);
        //將y的右孩子設置爲z
        right(y) = z;
        //更新最大點
        if (y == rightmost())
            rightmost() = z;
    }
    //設置新節點的父節點、左孩子節點、右孩子節點
    parent(z) = y;
    left(z) = 0;
    right(z) = 0;
    //平衡調節
    __rb_tree_rebalance(z, header->parent);
    //節點數加1
    ++node_count;
    //返回迭代器指向新增節點
    return iterator(z);
}

//左旋
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)
        //將左子節點的父節點設置爲x
        y->left->parent = x;
    y->parent = x->parent;

    //將x的位置替換成y
    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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章