C++实现红黑树

来源:互联网 发布:淘宝旧版本5.9.0下载 编辑:程序博客网 时间:2024/06/13 22:08

红黑树简介

红黑树是一个高效的平衡搜索树,保证最长路径不超过最短路径的两倍,因而近似平衡,保证了高度,也就保证了效率。增删查改时间复杂度都是O(logN)

性质:

  1. 每个结点不是红色就是黑色的。
  2. 根结点是黑色的。
  3. 如果一个结点是红色的,则它的两个子节点是黑色的(没有连续的红结点)
  4. 对于每个结点,从该结点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点(每条路径的黑色节点的数目相等
  5. 每个叶子结点都为黑色(此处叶子结点是空结点)

这几条规则保证了红黑树最长路径不超过最短路径的两倍(给个极端情况全黑色,然后在结点之间插入红色结点,即可得到结论)

结点的实现

三叉链实现RBtree,用KV存储结构,最后用枚举包含了相应的颜色。

树的实现

共有成员为空的构造函数,插入函数
私有成员为根,

红黑树的插入

为什么插入结点的颜色为红色好?
如果插入结点为黑色首先违背了第四条规则,每条路径黑色结点数目相同,虽然可以调整但是难调,我们原则上的保持第四条规则,所以选择插入红色节点。

方法:
首先判断是否为空树,接着找到插入结点,根据插入结点的情况来调整。 cur为插入结点,g为组父节点,p是父亲结点,u是叔叔结点
1. 如果插入结点为根结点,则直接插入,并且将根结点赋值为黑色。
2. 如果插入结点的父节点为黑色结点,那么直接插入。
3. 如果插入结点的父节点为红色结点,那么再次插入时,必然会有两个红色结点相连接,此时需要调整。

叔叔结点的情况和调整有关,叔叔的情况有以下几种:
叔叔存在且为红色
叔叔不存在
叔叔为黑色

插入分为三种情况

  1. 组父节点为黑色,父节点和叔叔结点为为红色,插入节点的为红色。
    此种情况下父亲结点和叔叔结点变为黑色,祖父结点变为红色,如果祖父结点是根结点则不影响,如果祖父结点不是根结点,则需要向上更新,
  2. 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(单旋)

    • 第一种情况,叔叔不存在,cur为新增结点,
    • 第二种情况,叔叔存在且为黑色,parent的一边C一定存在且为黑色,cur为红色结点,cur此时不是新插入的结点,cur存在左右孩子,并且cur原先为黑色((cur此时左右为黑色吗?))

此时旋转来调整结点,观察p和cur均为左孩子,此时右单旋,p和cur均为右孩子,此时左单旋。

  1. 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(双旋)
    • 第一种情况:u存在并且一定为黑色,cur不是新插入的结点,cur存在左右孩子,并且cur原先为黑色。
    • 第二种情况:u不存在,cur一定为新插入的结点。

实现代码如下

#include <iostream>#include <assert.h>using namespace std;enum Colour{    RED,    BLACK,};template <class K,class V>struct RBTreeNode{    RBTreeNode* _left;    RBTreeNode* _right;    RBTreeNode* _parent;    K _key;    V _value;    Colour _col;    RBTreeNode(const K& key = K(), const V& value = V(), const Colour& color = RED)        :_left(NULL)        , _right(NULL)        , _parent(NULL)        , _key(key)        , _value(value)        , _col(color)    {}};template <class K,class V>class RBTree{    typedef RBTreeNode<K, V> Node;public:    RBTree()        :_root(NULL)    {}    ~RBTree()    {        //if (_root)        //  _root = _Destroy(_root);    }    RBTree(const RBTree<K, V>& rb)    {        if (this != &rb)            _root = _Copy(_root);    }    RBTree<K, V> operator=(const RBTree<K, V>& rb)    {        if (*this != rb)        {            Node* tmp = _Copy(rb->_root);            _root = _Destroy(_root);            _root = tmp;        }        return *this;    }    bool Insert(const K& key, const V& value)    {        if (_root == NULL)        {            _root = new Node(key, value);            _root->_col = BLACK;            return true;        }        Node* pCur = _root;        Node* pParent = NULL;        while (pCur)        {            if (key < pCur->_key)            {                pParent = pCur;                pCur = pCur->_left;            }            else if (key > pCur->_key)            {                pParent = pCur;                pCur = pCur->_right;            }            else                return false;        }        pCur = new Node(key, value);        if (key < pParent->_key)            pParent->_left = pCur;        else            pParent->_right = pCur;        pCur->_parent = pParent;        //未调整到根节点且父节点还是红色        while (pCur != _root && pParent->_col == RED)        {            Node* grandfather = pParent->_parent;            //先处理左边            if (grandfather->_left == pParent)            {                Node* uncle = pParent->_right;                //叔叔存在且为红色                if (uncle && uncle->_col == RED)                {                    pParent->_col = uncle->_col = BLACK;                    grandfather->_col = RED;                    pCur = grandfather;                    pParent = pCur->_parent;                }                //叔叔不存在或者叔叔为黑色                else                {                    //pCur为pParent的右孩子                    if (pParent->_right == pCur)                    {                        RotateL(pParent);                        std::swap(pCur, pParent);                    }                    //pCur为pParent的左孩子                    else                    {                        RotateR(grandfather);                        grandfather->_col = RED;                        pParent->_col = BLACK;                    }                }            }            //再处理右边的情况(与上述情况刚好位置相反)            else            {                Node* uncle = grandfather->_left;                //叔叔存在且为红                if (uncle && uncle->_col == RED)                {                    pParent->_col = uncle->_col = BLACK;                    pCur->_col = RED;                    pCur = grandfather;                    pParent = pCur->_parent;                }                //叔叔不存在或者叔叔为黑色                else                {                    //pCur为pParent的左孩子                    if (pParent->_left == pCur)                    {                        RotateR(pParent);                        std::swap(pCur, grandfather);                    }                    //pCur为pParent的右孩子                    else                    {                        RotateL(grandfather);                        grandfather->_col = RED;                        pParent->_col = BLACK;                    }                }            }        }        _root->_col = BLACK;        return true;    }    void RotateR(Node* parent)    {        assert(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->_left == parent)        {            pparent->_left = subL;            subL->_parent = pparent;        }        else if (pparent->_right == parent)        {            pparent->_right = subL;            subL->_parent = pparent;        }        else        {            _root = subL;            subL->_parent = NULL;        }    }    void RotateL(Node* parent)    {        assert(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->_left = subR->_parent)        {            pparent->_left = subR;            subR->_parent = pparent;        }        else if (pparent->_right = subR->_parent)        {            pparent->_right = subR;            subR->_parent = pparent;        }        else        {            _root = subR;            subR->_parent = NULL;        }    }    bool IsBalance()    {        if (NULL == _root)            return true;        if (_root->_col == RED)            return false;        size_t count = 0;        Node* cur = _root;        while (cur)        {            if (cur->_col == BLACK)                count++;            cur = cur->_left;        }        size_t k = 0;        _IsBalance(_root, count, k);    }    void InOrder()    {        _Inorder(_root);        cout << endl;    }private:    bool _IsBalance(Node* _root, size_t count, size_t k)    {        if (_root == NULL)            return true;        if (_root->_parent&&_root->_col == _root->_parent->_col == RED)            return false;        if (_root->_col == BLACK)            k++;        if (_root->_left == NULL&&_root->_right == NULL)        {            if (count == k)                return true;            else                return false;        }        return ((_IsBalance(_root->_left, count, k))&&(_IsBalance(_root->_right, count, k)));    }    void _Inorder(Node* Root)    {        if (Root)        {            _Inorder(Root->_left);            cout << Root->_key << endl;            _Inorder(Root->_right);        }    }    Node* _Copy(Node* pRoot)    {        Node* pCur = pRoot;        if (pCur)        {            pCur = new Node(pRoot->_key, pRoot->_value);            pCur->_left= _Copy(pRoot->_left);            pCur->_right = _Copy(pRoot->_right);        }        return pCur;    }    //销毁    Node* _Destory(Node* pRoot)    {        if (pRoot)        {            pRoot->_left = _Destory(pRoot->_left);            pRoot->_right = _Destory(pRoot->_right);            delete pRoot;            pRoot = NULL;        }        return pRoot;    }    Node* _root;};

测试文件:

#include "RBtree.h"using namespace std;void test(){    RBTree<int, int> rb;    int arr[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };    for (size_t idx = 0; idx < sizeof(arr) / sizeof(arr[0]); ++idx)    {        rb.Insert(arr[idx], idx);    }    rb.InOrder();    if (rb.IsBalance())        cout << "是红黑树." << endl;    else        cout << "不是红黑树." << endl;    rb.InOrder();}int main(){    test();    system("pause");    return 0;}

红黑树的应用

红黑树是一颗高效的二叉搜索树,用途很广,例如STL中set\map\unorder_map\unorder_set都运用到了红黑树。

原创粉丝点击