平衡搜索树—红黑树RBTree

红黑树

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


红黑树的性质

  1. 每个节点,不是红色就是黑色;
  2. 根节点是黑色;
  3. 如果一个节点是红色的,那么它的子节点都是黑色的;
  4. 对于每一个节点,从该节点到其多有的后代叶子节点的简单路径上,均包含相同数目的黑色节点。

插入

cur为红有两种情况:
  1. cur为新增节点
  2. cur不是新增节点,而是cur的子树新增节点,相当于调节完子树后cur为红,则需要再向上调整。

其中两种情况比较简单:

1.第一种情况:

树为空,cur是新插入的节点,cur为红,则需要将cur变为黑

2.第二种情况:

cur为红,P为黑,所以整个树的颜色都不用变

3. 第三种情况
cur为红,g为黑, p为红,u存在且为红.

调整后:
cur为红,g改为红, p.U改为黑.

这里写图片描述

4. 第四种情况
cur为红,g为黑, p为红,u不存在/u为黑.

调整后:
p.g变颜色—p变黑,g变红.

情况1:左单旋转

这里写图片描述

情况2:右单旋转

这里写图片描述

5. 第五种情况
cur为红,g为黑, p为红,u不存在/u为黑.

1. 而p为g的左孩子,cur为p的右孩子,则需要对p先做出左单旋转;
2. 而p为g的右孩子,cur为p的左孩子,则需要对p先做出右单旋转;
最后将情况转为第二种情况。

1.
这里写图片描述
2.
这里写图片描述


代码实现:

#include<iostream>
using namespace std;


enum Colour 
{ 
    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;    
    Colour _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) 
    {  
        //1.为空则插入新节点 并且把颜色置为黑色 
        //2.不为空则找到要插入的位置
        if(_root == NULL)
        {
            _root = new Node(key,value);
            _root->_col = BLACK;
            return true;
        }
        Node* cur = _root;
        Node* parent = NULL;
        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->_left = cur;
            cur->_parent = parent;
        }else
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        //检验规则
        //1. parent 不为黑且parent存在
        //2. cur 为红 parent为红 uncle存在且为红
        //3. cur 为红 parent为红 uncle不存在或者存在为黑
        while(parent && parent->_col == RED)
        {
            Node* grandfather = parent->_parent ;
            if(parent == grandfather->_left )
            {
                Node* uncle = grandfather->_right ;
                //uncle 存在且为红-----第2种情况
                if(uncle && uncle->_col == RED)
                {
                    parent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    //接着向上检查
                    cur = grandfather;
                    parent = cur->_parent ;
                }
                else  //uncle 不存在或者存在且为黑-----第三种情况
                {
                    if(cur = parent->_right )
                    {
                        RotateL(parent);
                    }
                    RotateR(grandfather);
                }
            }
            else
            {
                // 父亲在祖父右边
                Node* uncle = grandfather->_left ;
                if(uncle && uncle->_col == RED)
                {
                    parent->_col = uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent ;
                }
                else
                { 
                    if(cur = parent->_left )//右左双旋
                    {
                        RotateR(parent);
                    }
                    RotateL(grandfather);
                }
            }
        }
        _root->_col = BLACK;
        return true;
    } 

    void RotateR(Node* parent) //右单旋转
    {
        Node* subL = parent->_left ;
        Node* subLR = subL->_right ;
        Node* ppNode = parent->_parent ;
        parent->_left = subLR;
        if(subLR)
        {
            subLR->_parent = parent;
        }
        subL->_right = parent;
        parent->_parent = subL;
        if(ppNode == NULL)
        {
            _root = subL;;
            subL->_parent = NULL;
        }else if(ppNode->_left == parent)
        {
            ppNode->_left = subL;
            subL->_parent  = ppNode;
        }else
        {
            ppNode->_right = subL;
            subL->_parent = ppNode;
        }
        parent->_col = RED;
        subL->_col = BLACK;
        parent = subL;
    }
    void RotateL(Node* parent) //左单旋转
    {
        Node* subR = parent->_right ;
        Node* subRL = subR ->_left ;
        Node* ppNode = parent->_parent ;
        parent->_right = subRL;
        if(subRL)
        {
            subRL->_parent = parent;
        }
        subR->_left = parent;
        parent->_parent = subR;
        if(ppNode == NULL)
        {
            _root = subR;
            subR->_parent = NULL;
        }else if(ppNode->_left == parent)
        {
            ppNode->_left = subR;
            subR->_parent = ppNode;
        }else
        {
            ppNode->_right = subR;
            subR->_parent = ppNode;
        }
        parent->_col = RED;
        subR->_col = BLACK;
        parent = subR;
    }

    void InOrder() 
    {
        _InOrder(_root);
    }
    void _InOrder(Node* root)
    {
        if(root == NULL)
        {
            return;
        }
        _InOrder(root->_left );
        cout<<root->_key <<" ";
        _InOrder(root->_right );
    }
    bool IsBalance()
    {
        //通过规则来评定是否是红黑树
        //1.根为黑
        //2.每条路的黑节点相同 (可以从叶子节点向上遍历然后带回黑色节点的个数)
        //3.红色不相邻
        if(_root && _root->_col == RED)
        {
            return false;
        }
        int k = 0;
        Node* cur = _root;
        while(cur)
        {
            if(cur->_col == BLACK)
            {
                ++k;
            }
            cur = cur->_left ;
        }
        int blacknum = 0;
        return _IsBalance(_root,k,blacknum);

    }

    bool _IsBalance(Node* root,int k,int blacknum)
    {
        if(root == NULL)
        {
            if(k != blacknum)
            {
                cout<<"黑节点的个数不同"<<endl;
                return false;
            }
            return true;
        }

        if(root->_col == RED && (root->_parent)->_col == RED)
        {
                cout<<"有连续的红节点"<<endl;
                return false;
        }

        if(root->_col == BLACK)
        {
            blacknum++;
        }

        return _IsBalance(root->_left ,k,blacknum)&&_IsBalance(root->_right  ,k,blacknum);
    }
private: 
    Node* _root; 
};

猜你喜欢

转载自blog.csdn.net/qq_37941471/article/details/79750529