数据结构-红黑树(RB-Tree)

来源:互联网 发布:中国出境旅游数据统计 编辑:程序博客网 时间:2024/05/17 22:17
  • 红黑树的概念和性质

红黑树是这样一颗二叉搜索树:树中的每个结点的颜色不是黑色就是红色。可以看作是一颗扩充二叉树。
特性描述如下:
特性1:根结点一定是黑色
特性2:没有连续的两个红色结点
特性3:所有从根结点到叶子结点的路径上都有相同数目的黑色结点
通过保持这三个性质从而使维持一颗红黑树的平衡。

  • 红黑书的结点
enum COLOR{    BLACK,    RED};//将结点默认为红色,这样如果父节点为黑色就可以直接插入,并且保持路径黑色结点数目相等template<class K,class V>struct RBTNode{    RBTNode<K, V>* _left;    RBTNode<K, V>* _right;    RBTNode<K, V>* _parent;    K _key;    V _value;    COLOR _col;    RBTNode(const K& key,const V& value)        :_key(key)        , _value(value)        , _parent(NULL)        , _left(NULL)        , _right(NULL)        ,``_col(RED)    {}};
  • 红黑树的搜索

由于每一颗红黑书都是二叉搜索树,在搜索过程中可以使用普通二叉搜索树时所使用的相同算法。不需要对颜色进行判断。

bool Find(const K& key){    if (_root == NULL)        return false;    Node* cur = _root;    while (cur)    {        if (key < cur->_key)        {            cur = cur->_left;        }        else if (key>cur->_key)        {            cur = cur->_right;        }        else        {            return te}        }    return false;    }
  • 红黑树的插入
    插入出现的情况:
    1)首先使用二插搜索树的插入将结点插入到红黑书中,该元素将作为新的叶子结点。
    2)如果是空树,则根据特性1,根结点必须为黑色,因为我们默认结点是红色,所以我们需要将结点染成黑色
    3)如果不是空树,那我们就要进行一系列旋转,染色,调整操作:
    cur为新插入结点,uncle为叔叔节点,pparent为祖父节点。

1-父亲为黑色
直接插入,因为我们结点默认是红色,不会影响树的黑色结点数目。
2-父亲为红色,叔叔为红色
这时我们插入一个结点相当于已经有两个连续红色结点出现,我们需要就行变色处理,将父亲和叔叔的颜色改成黑色,将祖父的颜色改为红色,然后向上回溯调整。
3-父亲为红色,叔叔为红色
这时仅仅变色已经不能使树保持特性,这里还得对树就行旋转操作。
- 旋转一共分为四种情况:
左单旋
这里写图片描述

    void RotateL(Node* parent)    {        Node* SubR = parent->_right;        Node* SubRL = SubR->_left;        parent->_right = SubRL;        if (SubRL)            SubRL->_parent = parent;            Node* pparent = parent->_parent;        SubR->_left = parent;        parent->_parent = SubR;        if (pparent == NULL)        {            _root = SubR;             SubR->_parent = NULL;        }        else        {            if (parent == pparent->_left)                pparent->_left = SubR;            else                pparent->_right = SubR;        }        SubR->_parent = pparent;    }

右单旋
这里写图片描述

void RotateR(Node* parent)    {        Node* SubL = parent->_left;        Node* SubLR = SubL->_right;        parent->_left = SubLR;        if (SubLR)            SubLR->_parent = parent;        Node* pparent = parent->_parent;        SubL->_right = parent;        parent->_parent = SubL;        if (pparent == NULL)        {            _root = SubL;            _root->_parent = NULL;        }        else        {            if (parent == pparent->_left)                pparent->_left = SubL;            else                pparent->_right = SubL;        }        SubL->_parent = pparent;    }

左右双旋
这里写图片描述
这里我们可以看到先进行左旋
旋转后cur为父结点而parent为子结点,所以我们旋转一次后交换cur和parent(swap(parent,cur))

if (cur == parent->_right)    {        //左旋        RotateL(parent);        std::swap(parent, cur);//因为左旋后cur已经变成父节点,parent为子节点    }        RotateR(pparent);        pparent->_col = RED;        parent->_col = BLACK;        break;

右左双旋
这里写图片描述

if (cur == parent->_left)    {        RotateR(parent);        std::swap(parent, cur);    }        RotateL(pparent);        parent->_col = BLACK;        pparent->_col = RED;        break;
  • 红黑树的运用–高效的二叉搜索树
    C++ STL库 – map
    Java 库
    linux内核
    其他一些库

    http://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html

  • 红黑树和AVL树的比较
    红黑树和AVL树都是高效的平衡二叉树, 增删查改的时间复杂度都是O(lg(N))
    红黑树的不追求完全平衡, 保证最长路径不超过最短路径的2倍, 相对而言, 降低了旋转的要求, 所以性能会优于AVL树, 所以实际运用
    中红黑树更多。
    另外关于红黑书的删除:(参考别人的东西)

    http://www.cnblogs.com/fornever/archive/2011/12/02/2270692.html
    http://blog.csdn.net/chenhuajie123/article/details/11951777

整体实现代码:

#include<iostream>using namespace std;enum COLOR{    BLACK,    RED};template<class K,class V>struct RBTNode{    RBTNode<K, V>* _left;    RBTNode<K, V>* _right;    RBTNode<K, V>* _parent;    K _key;    V _value;    COLOR _col;    RBTNode(const K& key,const V& value)        :_key(key)        , _value(value)        , _parent(NULL)        , _left(NULL)        , _right(NULL)        , _col(RED)    {}};template<class K,class V>class RBTree{    typedef RBTNode<K, V> Node;public:    RBTree()        :_root(NULL)    {}    ~RBTree()    {        _root = _DestoryRBTree(_root);    }    RBTree(const RBTree<K, V>& r)    {        _root = _Copy(r._root);    }    RBTree<K, V> operator=(const RBTree<K, V>& r)    {        if (this != &r)        {            Node* tmp = _Copy(r._root);            _root = _DestoryRBTree(_root);            _root = tmp;        }        return *this;    }    bool Find(const K& key)    {        if (_root == NULL)            return false;        Node* cur = _root;        while (cur)        {            if (key < cur->_key)            {                cur = cur->_left;            }            else if (key>cur->_key)            {                cur = cur->_right;            }            else            {                return true;            }        }        return false;    }    pair<Node*, bool> Insert(const K& key, const V& value)    {        if (_root == NULL)        {            _root = new Node(key, value);            _root->_col = BLACK;            return make_pair(_root, true);        }        Node* parent = NULL;        Node* cur = _root;        while (cur)        {            if (key < cur->_key)            {                parent = cur;                cur = cur->_left;            }            else if (key > cur->_key)            {                parent = cur;                cur = cur->_right;            }            else            {                return make_pair(cur, false);            }        }        cur = new Node(key, value);        Node* node = cur;        if (key < parent->_key)        {            parent->_left = cur;        }        else        {            parent->_right = cur;        }        cur->_parent = parent;        //父亲不为空并且为红色进行调整,父亲为黑色不用进行调整        while (parent != NULL&&parent->_col == RED)        {            Node* pparent = parent->_parent;            Node* uncle = NULL;            //父亲为红,叔叔也为红,直接变色            if (parent == pparent->_left)            {                uncle = pparent->_right;                if (uncle&&uncle->_col == RED)                {                    parent->_col = uncle->_col = BLACK;                    pparent->_col = RED;                    cur = pparent;                    parent = pparent->_parent;                }                else//uncle不存在或者uncle为黑色                {                    if (cur == parent->_right)                    {                        //左旋                        RotateL(parent);                        std::swap(parent, cur);//因为左旋后cur已经变成父节点,parent为子节点                    }                    RotateR(pparent);                    pparent->_col = RED;                    parent->_col = BLACK;                    break;                }            }            else//parent==pparent->right            {                uncle = pparent->_left;                if (uncle&&uncle->_col == RED)                {                    uncle->_col = parent->_col = BLACK;                    pparent->_col = RED;                    //向上调整                    cur = pparent;                    parent = cur->_parent;                }                else//uncle不存在或uncle为黑色                {                    if (cur == parent->_left)                    {                        RotateR(parent);                        std::swap(parent, cur);                    }                    RotateL(pparent);                    parent->_col = BLACK;                    pparent->_col = RED;                    break;                }            }        }        _root->_col = BLACK;        return make_pair(node, true);    }protected:    Node* _DestoryRBTree(Node* root)    {        if (root != NULL)        {            root->_left = _DestoryRBTree(root->_left);            root->_right = _DestoryRBTree(root->_right);            root = NULL;        }        return root;    }    Node* _Copy(Node* root)    {        Node* newnode;        if (root != NULL)        {            newnode = new Node(root->_key, root->_value);            newnode->_left = _Copy(root->_left);            newnode->_right = _Copy(root->_right);        }        return newnode;    }    void RotateL(Node* parent)    {        Node* SubR = parent->_right;        Node* SubRL = SubR->_left;        parent->_right = SubRL;        if (SubRL)            SubRL->_parent = parent;            Node* pparent = parent->_parent;        SubR->_left = parent;        parent->_parent = SubR;        if (pparent == NULL)        {            _root = SubR;             SubR->_parent = NULL;        }        else        {            if (parent == pparent->_left)                pparent->_left = SubR;            else                pparent->_right = SubR;        }        SubR->_parent = pparent;    }    void RotateR(Node* parent)    {        Node* SubL = parent->_left;        Node* SubLR = SubL->_right;        parent->_left = SubLR;        if (SubLR)            SubLR->_parent = parent;        Node* pparent = parent->_parent;        SubL->_right = parent;        parent->_parent = SubL;        if (pparent == NULL)        {            _root = SubL;            _root->_parent = NULL;        }        else        {            if (parent == pparent->_left)                pparent->_left = SubL;            else                pparent->_right = SubL;        }        SubL->_parent = pparent;    }    void InOrder()    {        _InOrder(_root);        cout << endl;    }    void _InOrder(Node* root)    {        if (root == NULL)            return;        _InOrder(root->_left);        cout << root->_key << endl;        _InOrder(root->_right);    }protected:    Node* _root;};
2 0