RB-tree 红黑树

除AVL树外,还有RBtree也是经常用到的平衡二叉搜索树
RBtree必须满足以下四条规则:
1.每个节点不是红色就是黑色
2.根节点为黑色
3.如果一个节点是红色,则它的 子节点是黑色的(即没有连续的红节点)
4.任一节点至NULL(树尾端)的任何路径,所含黑节点数必须相同
那AVL和RBtree有什么区别
AVltree 是严格平衡的二叉搜索树,其复杂度接近lgN,旋转多,维护起来麻烦,但是更加直观
RBree 是近似平衡的二叉搜索树,其复杂度一定小于2*(LgN),但是曾有人做过大量试验证明,红黑树的效率仍能达到lgN,旋转则较少,维护起来简单,今后项目什么的一定会优先RBtree,其比较抽象
插入操作
注意:cur为当前节点 P为父节点 g为祖父节点 u为父亲的兄弟节点即叔叔节点
状况1:该树为空树,直接插入根结点的位置,违反性质1,把节点颜色有红改为黑即可。
状况2:插入节点N的父节点P为黑色,不违反任何性质,无需做任何修改。
接下来是真正需要调整的状况了
状况3:当cur为红,P为红,g为黑,u存在且为红
先将p,u变为黑色,g改成红,然后把cur给g,继续向上搜索
这里写图片描述
状况4: cur为红,P为红,g为黑,u不存在/u为黑(cur为p的左节点)
这里写图片描述
状态5:cur为红,P为红,g为黑,u不存在/u为黑(cur为p的右节点)
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转,则转换成了情况2
这里写图片描述
删除操作
状况1:cur的兄弟b是红色的。
这里写图片描述
情况2:cur的兄弟b是黑色的,且cur的俩个孩子都是黑色的。
b变为红色后经过b节点的路径的黑节点数目也减少了1,那个从P出发到其叶子节点到所有路径所包含的黑节点数目相等了。但是这个数目比之前少了1,因为左右子树中的黑节点数目都减少了。P是他父节点g的一个孩子,那么由g到其叶子节点的黑节点数目就不相等了,所以说没有结束,需把P当做新的起始点开始向上检索。
这里写图片描述
情形3:P为红(S一定为黑),S的孩子们都为黑。
这里写图片描述
情形4:P任意色,b为黑,cur是P的左孩子,b的右孩子bR为红,b的左孩子任意(或者是cur是P的右孩子,b的左孩子为红,b的右孩子任意)。
P、b旋转有变色,等于给cur这边加了一个黑节点,P位置(是位置而不是P)的颜色不变,b这边少了一个黑节点;bR有红变黑,b这边又增加了一个黑节点;这样一来又恢复了平衡
这里写图片描述
情形5:P任意色,b为黑,cur是P的左孩子,b的左孩子bL为红,b的右孩子bR为黑(或者cur是P的右孩子,b的右孩子为红,b的左孩子为黑)。
这如果你按情形4的操作的话,由于bR本来就是黑色,无法弥补由于P、b的变换(旋转)给b这边造成的损失!所以没先对b、SL进行变换之后就变为情形4的情况了
这里写图片描述

#pragma once
#include<stdio.h>
#include<iostream>

using namespace std;
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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值