【資料結構】實現紅黑樹!!!

doctor_xiong發表於2018-02-27

相對於AVL樹來說,紅黑樹去掉了AVL樹裡面的平衡因子,利用樹節點的顏色來調整數的平衡。
紅黑樹的建立原則:

  1. 每個節點的顏色不是黑色就是紅色
  2. 樹的根節點是黑色的
  3. 如果一個節點的顏色是紅色的,那麼它的裡兩個孩子結點顏色是黑色的(即,沒有兩個連續的紅色結點)
  4. 對於每個節點,在其後面的簡單路徑上面的黑色結點的個數是相同的
  5. 每個葉子節點都是黑色的(葉子節點是指空節點)

:當滿足上面的顏色限制的時候,最長路徑上面的結點個數最多不超過最短路徑的兩倍

在紅黑樹裡面需要掛入的結點的顏色無論紅黑都可以的,但是假如是黑色,那麼就不滿足條件4,相對來說需要調整的範圍大。假如是紅色,那麼不滿足區域性,對區域性結點進行調整就可以了。所以在建立結點的時候結點的顏色標記成紅色。


紅黑樹的插入
情況1:當樹是空樹的時候?
這裡寫圖片描述
解決辦法:將插入的結點直接掛上面,並且將結點的顏色標記成黑色。

情況2:插入的結點的父節點是黑色的?
這裡寫圖片描述
解決方法:直接插入結點

情況3:當g–黑色,p–紅色,u–紅色?
這裡寫圖片描述
解決方法:將p、u結點顏色改為黑色,g結點的顏色改為紅色,然後再以g結點為基準向上調整

情況4:當g–黑,p–紅,u不存在或者u–黑?
這裡寫圖片描述
解決方法:將p、g結點的位置交換,並且兩結點改變顏色。

情況5:當g–黑,p–紅,u不存在或者u–黑,並且當p為g的左孩子,cur為p的右孩子或者p為g的右孩子,cur為p的左孩子?
這裡寫圖片描述
解決方法:將cur結點進行左單旋或者右單旋,然後再按照情況4的解決方法進行調整。

紅黑樹的實現(僅建立):


#ifndef _RWTREE_H
#define _RWTREE_H
#include<iostream>
using namespace std;


enum color{RED,BLACK};
template<class T>
struct RBTreeNode
{
    RBTreeNode(T d)
    :left(NULL)
    ,right(NULL)
    ,_parent(NULL)
    ,_color(RED)
    ,value(d)
    {}
    RBTreeNode<T>* left;
    RBTreeNode<T>* right;
    RBTreeNode<T>* _parent;
    color _color;
    T value;
};

template<class T>
class RWTree
{
    typedef RBTreeNode<T> Node;
    public:
    RWTree(T* arr,size_t size)
    :_root(NULL)
    {
        if(NULL == arr)
            return ;
        for(int i=0;i<size;i++)
            Insert(arr[i]);
    }
    void Insert(T d)
    {
        _Insert(_root,d);
    }

private:


    void _Insert(Node* root ,T d)
    {
        Node* cur = new Node(d);
        if(NULL == root)
            _root = cur;
        else
        {
            while(root)
            {
                if(d < root->value)
                    root = root->left;
                else
                    root = root->right;
            }       
            if(d < root->value)
                root->left = cur;
            else
                root->right = cur;
        }
        Adjust(cur);
    }

    void Adjust(Node* cur)
    {
        Node* parent = cur->_parent;
        if(parent == NULL)              //情況1
            _root = cur;
        else 
        {
            if(parent->_color == RED )
            {
                Node* grand = parent->_parent;
                Node* uncle = NULL;
                if(grand->left == parent)
                    uncle = grand->right;
                else if(grand->right == parent)
                    uncle = grand->left;
                if(uncle && uncle->_color == RED)       //情況3
                {
                    grand->_color = RED;
                    parent->_color = BLACK;
                    uncle->_color = BLACK;
                    Adjust(grand);
                }
                else
                {
                    if(cur == parent->left && parent == grand->left)     //情況4
                     {
                        parent->_color = BLACK;
                        grand->_color = RED;
                        swap_R(grand);
                    }
                    else if( cur == parent->right && parent == grand->right )
                    {
                        parent->_color = BLACK;
                        grand->_color = RED;
                        swap_L(parent);
                    }
                    else if(cur == parent->right && parent == grand->left) //情況5
                    {
                        grand->left = cur;
                        cur->_parent = grand;
                        parent = cur->left;
                        parent->_parent = cur;
                        Adjust(parent);
                    }
                    else if(cur == parent->left && parent == grand->right)
                    {
                        grand->right = cur;
                        cur->_parent = grand;
                        parent = cur->right;
                        parent->_parent = cur;
                        Adjust(grand);
                    }
                }
            }
        }
    }
    void swap_L(Node* parent)
    {
        Node* subR = parent->right;
        Node* subRL = subR->left;
        Node* pparent = parent->_parent;
        if(subRL)
            subRL->_parent = parent;
        parent->right = subRL;
        subR->left = parent;
        if(pparent == NULL)
        {
            _root = subR;
        }

        else if(pparent->left == parent)
        {
            pparent->left = subR;
        }
        else
            pparent->right = subR;
        subR->_parent = pparent;
        parent->_parent = subR;

    }

    void swap_R(Node* parent)
    {
        Node* pparent = parent->_parent;
        Node* subL = parent->left;
        Node* subLR = subL->right;
        if(subLR)
            subLR->_parent = parent;
        parent->left = subLR;
        subL->right = parent;
        parent->_parent = subL;
        if(NULL == pparent)
            _root = subL;
        else if(pparent->left == parent)
            pparent->left = subL;
        else
            pparent->right = subL;
        subL->_parent = pparent;
    }

    Node* _root;
};



#endif

相關文章