RBTree——红黑树

来源:互联网 发布:佳能照片打印机软件 编辑:程序博客网 时间:2024/05/29 04:13

红黑树:

红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示结点的颜色,红色或黑色(Red或Black)
通过对任何一条从根到叶子简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,从而达到近似平衡。

红黑树必须满足的性质:
1,每个节点不是红色就是黑色。
2,根节点必须为黑色。
3,如果一个节点是红色,则它的两个子节点是黑色
(即不能有两个连续的红色节点)。
4,对每个节点,从该节点到其所有后代的叶子节点的简单路径上,均包含相同数目的黑色节点。
5,每个叶子节点都是黑色(这里的叶子节点指NIL结点(空结点))(如果是空结点默认为黑色)。

我们可以先来思考一个简单的问题:
为什么红黑树加上了上面的颜色约束性质,它可以保证最长的路径不超过最短路径的两倍?

我们想一下最短路径应该是全黑,最长路径应该是红黑红黑相间。这么看来,它就可以保证最长路径不超过最短路径的两倍。

学完AVL树,接触红黑树时,它们是非常相似的,都会插入删除之后调节平衡,AVL树通过平衡因子调节平衡,红黑树通过颜色约束平衡,我们把AVL树称为高度平衡的二叉搜索树,而红黑树是近似平衡的二叉搜索树
所以在插入,删除上,AVL树旋转的次数比红黑树多,所以红黑树的插入,删除效率更高。
在应用中,红黑树应用更为广泛,在STL中,set,map,multiset,multimap的底层实现都是通过红黑树来完成的

红黑树的节点结构:
因为我们用颜色约束平衡,所以我们创建一个枚举类型来保存结点的颜色

代码实现

enum Color{    RED,    BLACK,};template<class K, class V>struct RBTreeNode{    RBTreeNode<K, V>* _left;    RBTreeNode<K, V>* _right;    RBTreeNode<K, V>* _parent;    K _key;    V _value;    Color _col;    RBTreeNode(const K& key, const V& value)        :_left(NULL)        , _right(NULL)        , _parent(NULL)        , _key(key)        , _value(value)        , _col(RED)    {}};

插入:
我们将红黑树的插入分为五种情况:
第一种:
范甘迪

第二种:
你

情况二具体情况:1,u不存在
如上图:如果u不存在,那么,a,b,c,d,e也一定都不存在
就
u存在为黑:
如情况二的图:如果u存在为黑,那么,d,e不一定存在,是下图变上去的:
好看
第三种:
脚后跟

第四种:第四种情况与第二种情况是接近的,不同的是:p是g的右孩子,cur是p的右孩子。我们要进行的是左单旋。

第五种:第五种情况与第三种情况是接近的,不同的是:p是g的右孩子,cur是p的左孩子,要先进行右单旋,然后变为第四种情况。
最后两种就不用图演示了,相信看完前三种情况,最后两种也一定可以清除。

代码实现:

bool Insert(const K& key,const V& value)    {        if (_root == NULL)        {            _root = new Node(key,value);            _root->_col = BLACK;            return true;        }        Node* parent = NULL;        Node* cur = _root;        while (cur)        {            if (cur->_key > key)            {                parent = cur;                cur = cur->_left;            }            else if (cur->_key < key)            {                parent = cur;                cur = cur->_right;            }            else            {                return false;            }        }        //找到插入位置        cur = new Node(key, value);        if (parent->_key < key)        {            parent->_right = cur;            cur->_parent = parent;        }        else        {            parent->_left = cur;            cur->_parent = parent;        }        while (parent&&parent->_col == RED)        {            Node* grandparent = parent->_parent;            if (parent == grandparent->_left)            {                Node* uncle = grandparent->_right;                if (uncle&&uncle->_col == RED)                {                    parent->_col = BLACK;                    uncle->_col = BLACK;                    grandparent->_col = RED;                    cur = grandparent;                    parent = cur->_parent;                }                else //uncle不存在,或uncle为黑色                {                    if (cur == parent->_right)                    {                        RotateL(parent);                        swap(parent,cur);                    }                    RotateR(grandparent);                    parent->_col = BLACK;                    grandparent->_col = RED;                    break;                }            }            else//parent == grandparent->_right            {                Node* uncle = grandparent->_left;                if (uncle&&uncle->_col == RED)                {                    parent->_col = BLACK;                    uncle->_col = BLACK;                    grandparent->_col = RED;                }                else//uncle不存在或者为黑色                {                    if (cur == parent->_left)                    {                        RotateR(parent);                        swap(parent, cur);                    }                    RotateL(grandparent);                    parent->_col = BLACK;                    grandparent->_col = RED;                    break;                }            }        }        _root->_col = BLACK;        return true;    }

左单旋右单旋:这个在AVL树中讲过,这里只给出代码啦

    void RotateL(Node* parent)    {        Node* subR = parent->_right;        Node* subRL = subR->_left;        parent->_right = subRL;        if (subRL)        {            subRL->_parent = parent;        }        subR->_left = parent;        Node* parentparent = parent->_parent;        parent->_parent = subR;        if (parentparent==NULL)        {            _root = subR;            _root->_parent = NULL;//不置空,会死循环        }        else        {            if (parent == parentparent->_left)            {                parentparent->_left = subR;                subR->_parent = parentparent;            }            else            {                parentparent->_right = subR;                subR->_parent = parentparent;            }        }    }    void RotateR(Node* parent)    {        Node* subL = parent->_left;        Node* subLR = subL->_right;        parent->_left = subLR;        if (subLR)        {            subLR->_parent = parent;        }        subL->_right = parent;        Node* parentparent = parent->_parent;        parent->_parent = subL;        if (parentparent == NULL)        {            _root = subL;            _root->_parent = NULL;        }        else        {            if (parent == parentparent->_left)            {                parentparent->_left = subL;                subL->_parent = parentparent;            }            else            {                parentparent->_right = subL;                subL->_parent = parentparent;            }        }    }

判断是否为红黑树:
满足红黑树的性质

满足黑节点个数相同的方法:
根节点固定是黑色,为1是固定的,每个孩子都依赖于父亲,当前结点是黑色,那么黑色节点的数量是父亲数量+1,如果当前节点为红色,那么黑色节点数量是父亲数量本身,每个节点没必要都记下来,可以选择一个参数,选择参数方法:
1,当左右都为空时求出来的的黑色节点数量都push到容器中,最后该容器中数据如果一样为红黑树
2,先求出来最左(或右)黑色节点的个数,其他的路径的黑色结点与他相比,若相同为红黑树

下面代码用的是第二种方法:

bool IsBalance()    {        if (_root == NULL)        {            return true;        }        if (_root&&_root->_col==RED)        {            return false;        }        int BlackNum = 0;        Node* left = _root;        while (left)        {            if (left->_col == BLACK)            {                ++BlackNum;            }            left = left->_left;        }        int num = 0;        return _IsBalance(_root, num, BlackNum);    }    bool _IsBalance(Node* root, int num, const int blackNum)    {        if (root == NULL)        {            return true;        }        if (root->_col == RED&&root->_parent->_col == RED)        {            cout<<"存在连续的红节点"<<root->_key<<endl;            return false;        }        if (root->_col == BLACK)        {            ++num;        }        // num 是根节点到当前节点黑色节点的数量        if (root->_left == NULL && root->_right == NULL)        {            if (num != blackNum)            {                //cout<<"黑色节点的数量不相等"<<root->_key<<endl;                return false;            }            else            {                return true;            }        }        return _IsBalance(root->_left, num, blackNum)            && _IsBalance(root->_right, num, blackNum);    }

完整代码:

enum Color{    RED,    BLACK,};template<class K, class V>struct RBTreeNode{    RBTreeNode<K, V>* _left;    RBTreeNode<K, V>* _right;    RBTreeNode<K, V>* _parent;    K _key;    V _value;    Color _col;    RBTreeNode(const K& key, const V& value)        :_left(NULL)        , _right(NULL)        , _parent(NULL)        , _key(key)        , _value(value)        , _col(RED)    {}};template<class K,class V>class RBTree{    typedef RBTreeNode<K,V> Node;public:    RBTree()        :_root(NULL)    {}    bool Insert(const K& key,const V& value)    {        if (_root == NULL)        {            _root = new Node(key,value);            _root->_col = BLACK;            return true;        }        Node* parent = NULL;        Node* cur = _root;        while (cur)        {            if (cur->_key > key)            {                parent = cur;                cur = cur->_left;            }            else if (cur->_key < key)            {                parent = cur;                cur = cur->_right;            }            else            {                return false;            }        }        //找到插入位置        cur = new Node(key, value);        if (parent->_key < key)        {            parent->_right = cur;            cur->_parent = parent;        }        else        {            parent->_left = cur;            cur->_parent = parent;        }        while (parent&&parent->_col == RED)        {            Node* grandparent = parent->_parent;            if (parent == grandparent->_left)            {                Node* uncle = grandparent->_right;                if (uncle&&uncle->_col == RED)                {                    parent->_col = BLACK;                    uncle->_col = BLACK;                    grandparent->_col = RED;                    cur = grandparent;                    parent = cur->_parent;                }                else //uncle不存在,或uncle为黑色                {                    if (cur == parent->_right)                    {                        RotateL(parent);                        swap(parent,cur);                    }                    RotateR(grandparent);                    parent->_col = BLACK;                    grandparent->_col = RED;                    break;                }            }            else//parent == grandparent->_right            {                Node* uncle = grandparent->_left;                if (uncle&&uncle->_col == RED)                {                    parent->_col = BLACK;                    uncle->_col = BLACK;                    grandparent->_col = RED;                }                else//uncle不存在或者为黑色                {                    if (cur == parent->_left)                    {                        RotateR(parent);                        swap(parent, cur);                    }                    RotateL(grandparent);                    parent->_col = BLACK;                    grandparent->_col = RED;                    break;                }            }        }        _root->_col = BLACK;        return true;    }    void RotateL(Node* parent)    {        Node* subR = parent->_right;        Node* subRL = subR->_left;        parent->_right = subRL;        if (subRL)        {            subRL->_parent = parent;        }        subR->_left = parent;        Node* parentparent = parent->_parent;        parent->_parent = subR;        if (parentparent==NULL)        {            _root = subR;        }        else        {            if (parent == parentparent->_left)            {                parentparent->_left = subR;                subR->_parent = parentparent;            }            else            {                parentparent->_right = subR;                subR->_parent = parentparent;            }        }    }    void RotateR(Node* parent)    {        Node* subL = parent->_left;        Node* subLR = subL->_right;        parent->_left = subLR;        if (subLR)        {            subLR->_parent = parent;        }        subL->_right = parent;        Node* parentparent = parent->_parent;        parent->_parent = subL;        if (parentparent == NULL)        {            _root = subL;            _root->_parent = NULL;        }        else        {            if (parent == parentparent->_left)            {                parentparent->_left = subL;                subL->_parent = parentparent;            }            else            {                parentparent->_right = subL;                subL->_parent = parentparent;            }        }    }    void InOrder()    {        _InOrder(_root);        cout << endl;    }    void _InOrder(Node* root)    {        if (root == NULL)            return;        _InOrder(root->_left);        cout<<root->_key<<" ";        _InOrder(root->_right);    }    bool IsBalance()    {        if (_root == NULL)        {            return true;        }        if (_root&&_root->_col==RED)        {            return false;        }        int BlackNum = 0;        Node* left = _root;        while (left)        {            if (left->_col == BLACK)            {                ++BlackNum;            }            left = left->_left;        }        int num = 0;        return _IsBalance(_root, num, BlackNum);    }    bool _IsBalance(Node* root, int num, const int blackNum)    {        if (root == NULL)        {            return true;        }        if (root->_col == RED&&root->_parent->_col == RED)        {            cout<<"存在连续的红节点"<<root->_key<<endl;            return false;        }        if (root->_col == BLACK)        {            ++num;        }        // num 是根节点到当前节点黑色节点的数量        if (root->_left == NULL && root->_right == NULL)        {            if (num != blackNum)            {                //cout<<"黑色节点的数量不相等"<<root->_key<<endl;                return false;            }            else            {                return true;            }        }        return _IsBalance(root->_left, num, blackNum)            && _IsBalance(root->_right, num, blackNum);    }private:    Node* _root;};void TestRBTree(){        RBTree<int, int> t;        int a[] = {16, 3, 7, 11, 9, 26, 18, 14, 15};        //int a[] = {4, 2, 6, 1, 3, 5, 15, 7, 16, 14};        for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i)        {            t.Insert(a[i], i);        }        t.InOrder();        cout<<"IsBalance?"<<t.IsBalance()<<endl;}
原创粉丝点击