C++实现红黑树

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

性质1. 节点是红色或黑色。

性质2. 根节点必须是黑色。

性质3. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡(也称近似平衡)的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。

如图,一棵简单的红黑树:
这里写图片描述

因为红黑树是一棵近似平衡的二叉树,其最长的可能路径不多于最短的可能路径的两倍长,所以它的查找时间复杂度是o(2log n),忽略常数,它的时间复杂度就是o(log n),而且它同AVLTree一样,为了保持平衡,插入节点以后要进行旋转(红黑树还要变色处理),但是由于它的限制相对宽松,所以它旋转的次数较少,程序执行相对效率就较高,所以红黑树的使用相对于AVLTree更广泛一些。

红黑树的调平是通过硬性要求满足性质2和性质4,在当前插入一个红结点,然后通过变色以及旋转处理使之满足性质3,然后就达到近似平衡。

具体的变色调平处理分为以下六种:
1.叔叔结点在出入结点的右侧时
a.叔叔结点存在接为红色
b.插入节点在其父节点的左侧并且叔叔结点不存在或者叔叔结点存在且为黑色
c.插入节点在其父节点的右侧并且叔叔结点不存在或者叔叔结点存在且为黑色

2.叔叔结点在插入节点的左侧时
a.叔叔结点存在接为红色
b.插入节点在其父节点的左侧并且叔叔结点不存在(此时下图中的cur没有子树)或者叔叔结点存在且为黑色
c.插入节点在其父节点的右侧并且叔叔结点不存在(此时下图中的cur没有子树)或者叔叔结点存在且为黑色

这里只简单地分析情况一中的三种情况,如下图:

a.只需变色处理,如果grandfather之上为红,则继续进行向上变色处理

这里写图片描述

b.此时需要进行右单旋
这里写图片描述

c.进行左单旋之后变为情况b

这里写图片描述

下面看代码实现:

#pragma once

enum Color  //枚举定义红色和和黑色属性
{
    RED,
    BLACK,
};


template <class K,class V>
struct RBTreeNode
{
    K _key;
    V _value;
    Color _color;
    RBTreeNode<K, V>* _left;
    RBTreeNode<K, V>* _right;
    RBTreeNode<K, V>* _parent;

    RBTreeNode(const K& k,const V& v)
        :_key(k)
        ,_value(v)
        ,_color(RED)
        ,_left(NULL)
        ,_right(NULL)
        ,_parent(NULL)
    {}


};


template <class K,class V>
class RBTree
{
    typedef RBTreeNode<K, V> Node;
public:

    RBTree()
        :_root(NULL)
    {}

    bool Insert(const K& key, const V& value)
    {
        //1.为空时直接新创建一个结点,并将颜色设置为黑色以满足性质2
        if (NULL == _root)
        {
            _root = new Node(key, value);
            _root->_color = BLACK;
            return true;
        }

        //不问空就要寻找插入位置
        else
        {
            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 false;
            }  //出循环即为找到相应位置

            cur = new Node(key, value);

            //按照大小关系进行连接
            if (key<parent->_key)
            {
                cur->_parent = parent;
                parent->_left = cur;
            }
            else
            {
                cur->_parent = parent;
                parent->_right = cur;
            }

            // 有插入节点开始向根节点进行旋转和调色处理
            while (parent && RED == parent->_color)
            {
                Node* grangfather = parent->_parent;
                if (parent == grangfather->_left)
                {
                    //1.叔叔在右
                    Node* uncle = grangfather->_right;

                    //1.1叔叔存在且为红
                    if (grangfather != _root && uncle && RED == uncle->_color)
                    {
                        grangfather->_color = RED;
                        parent->_color = uncle->_color = BLACK;
                        cur = grangfather;
                        parent = cur->_parent;
                    }
                    //1.2叔叔不存在或者存在且为黑
                    else
                    {
                        //1.2.1 cur位于paret的right --> 左右双旋
                        if (cur == parent->_right)
                        {
                            RotateL(parent);
                            swap(parent, cur);
                        }
                        //1.2.2 cur位于parent的left --> 右单旋
                        RotateR(grangfather);

                        parent->_color = BLACK;
                        grangfather->_color = cur->_color = RED;

                    }
                }
                else
                {
                    //2.叔叔在左
                    Node* uncle = grangfather->_left;
                    //1.1叔叔存在且为红
                    if (grangfather!=_root && uncle && RED == uncle->_color)
                    {
                        grangfather->_color = RED;
                        parent->_color = uncle->_color = BLACK;
                        cur = grangfather;
                        parent = cur->_parent;
                    }
                    //2.2叔叔不存在或者存在且为黑
                    else
                    {
                        //2.2.1 cur位于paret的left --> 右左双旋
                        if (cur == parent->_left)
                        {
                            RotateR(parent);
                            swap(parent, cur);
                        }

                        //2.2.2 cur位于parent的 --> 左单旋
                        RotateL(grangfather);

                        parent->_color = BLACK;
                        grangfather->_color = cur->_color = RED;
                    }
                }

                return true;

            }
        }
    }

    bool IsBalance()
    {
        if (NULL == _root)
            return true;
        if (BLACK == _root->_color)
            return true;

        Node* leftroad = _root;
        int blackNum = 0;
        while (leftroad)
        {
            if (BLACK == leftroad->_color)
                blackNum++;
            leftroad = leftroad->_left;
        }

        int curNum = 0;
        return _IsBalance(_root, blackNum, curNum);
    }

    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }

protected:


    //右单旋
    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;

        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;

        subL->_right = parent;


        Node* ppNode = parent->_parent;
        parent->_parent = subL;

        if (NULL == ppNode)
        {
            _root = subL;
            subL->_parent = NULL;
        }
        else
        {
            if (ppNode->_left == parent)
                ppNode->_left = subL;
            else
                ppNode->_right = subL;

            subL->_parent = ppNode;
        }
    }

    //左单旋
    void RotateL(Node* parent)
    {

        Node* subR = parent->_right;
        Node* subRL = subR->_left;

        parent->_right = subRL;
        if (subR)
            subR->_parent = parent;

        subR->_left = parent;

        Node* ppNode = parent->_parent;
        parent->_parent = subR;

        if (parent == _root)
        {
            _root = subR;
            subR->_parent = NULL;
        }
        else
        {
            if (ppNode->_left == parent)
                ppNode->_left = subR;
            else
                ppNode->_right = subR;

            subR->_parent = ppNode;
        }
    }

    bool _IsBalance(Node* root, const int& blackNum, int curNum)
    {
        if (NULL == root)
        {
            if (blackNum != curNum)
            {
                cout << "当前结点的黑色结点数目不相等!"<< endl;
                return false;
            }

        }
        if (root->_parent && root->_color == root->_parent->_color)
        {
            cout << "该结点与上一个结点是两个连续的红结点!" << root->_key << endl;
        }

    return _IsBalance(root->_left,blackNum,curNum) && _IsBalance(root->_right,blackNum,curNum);


    }
        void _InOrder(Node* root)
        {
            if (NULL == root)
                return;
            _InOrder(root->_left);
            cout << root->_key << "  ";
            _InOrder(root->_right);

        }

        //右单旋
        void RotatelR(Node* parent)
        {
            Node* subL = parent->_left;
            Node* subLR = subL->_right;

            parent->_left = subLR;
            if (subLR)
                subLR->_parent = parent;
            subL->_right = parent;
            parent->_parent = subL;
            Node* ppNode = parent->_parent;
            if (ppNdoe->_left == parent)
                ppNode->_left = subL;
            else
                ppNode->_right = subL;

        }

        //左单旋
        void RotatelL(Node* parent)
        {

            Node* subR = parent->_right;
            Node* subRL = subR->_left;

            parent->_right = subRL;
            if (subR)
                subR->_parent = parent;
            subR->_left = parent;
            parent->_parent = subR;

            Node* ppNode = parent->_parent;
            if (ppNode == _root)
            {
                _root = subR;
                subR->_parent = NULL;
            }
            else
            {
                if (ppNode->_left == parent)
                    ppNode->_left = subR;
                else
                    ppNode->_right = subR;
            }
        }
protected:
    Node* _root;
};


测试用例:

void TestRBTree()
{
    RBTree<int, int> t1;
    int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
    {
        t1.Insert(a[i], i);
        cout << a[i] << "结点IsBalance?  " << t1.IsBalance() << endl;

    }

    cout << "中序遍历:";
    t1.InOrder();
    cout << "t1 IsBalance?  " << t1.IsBalance() << endl;
}

运行结果:
这里写图片描述

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值