红黑树的模拟实现

红黑树的概念
红黑树 ,是一种 二叉搜索树 ,但 在每个结点上增加一个存储位表示结点的颜色,可以是 Red
Black 。 通过对 任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路
径会比其他路径长出俩倍 ,因而是 接近平衡 的。

红黑树的模拟实现_第1张图片

红黑树的性质
1. 每个结点不是红色就是黑色 
2. 根节点是黑色的  
3. 如果一个节点是红色的,则它的两个孩子结点必须是黑色的  
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点  
5. NIL结点都是黑色的

//模拟实现红黑树

#include
using namespace std;
enum Color
{
    RED,
    Black
};
template
struct RBTreeNode
{
    RBTreeNode* _left;
    RBTreeNode* _right;
    RBTreeNode* _parent;
    pair _kv;
    Color _col;
    RBTreeNode()
        :_left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
        , _kv(nullptr)
        , _col(RED)
    {}
};
template
class RBTree
{
    typedef RBTreeNode Node;
public:
    bool checkColor(Node* root,int blackment ,int benchmark) //检查是否存在连续的红色结点
    {
        if (root == nullptr)
        {
            if (blackment != benchmark)
            {
                return false;
            }
            return true;
        }
        if (root->_col == Black)
        {
            benchmark++;
        }
        if (root->_col == RED && root->_parent && root->_parent->_col == RED)
        {
            cout << root->_kv.first << "其父亲出现了连续的红色结点" << endl;
            return false;
        }
        return  checkColor(root->_left,blackment,benchmark) && checkColor(root->_right, blackment, benchmark);
    }
    //检查路径黑色结点的数量  遍历查找所有叶子结点,根据叶子结点的值,将路线走一遍统计黑色节点的数量 2N
    

    //遍历:找到所有叶子结点,
    bool isBalance()
    {
        return _isBalance();
    }
    bool _isBalance()
    {
        int benchmark = 0;
        //单条路径上的所有黑色结点
        Node* cur = _root;
        if (cur)
        {
            if (cur->_col == Black)
            { 
                benchmark++;
            }
            cur = cur->_left;
        }
        return checkColor(_root,0,benchmark);
    }
    void RotateL(Node*& parent)  //左单旋 调整父子节点树中顺序,建立链接(parent与cur,parent的parent与cur),调整平衡因子
    {
        Node* cur = parent->_right;
        Node* cur_left = cur->_left;

        parent->_right = cur_left;//将cur的左节点放入parent的右结点
        if (cur_left)
        {
            cur_left->_parent = parent;  //cur_left控制_parent
        }

        cur->_left = parent;//将parent放入cur的左节点
        Node* ppNode = parent->_parent;
        cur->_parent = parent->_parent; //cur的父节点为原parent的父亲
        parent->_parent = cur; //parent的父节点为cur
        if (parent == _root)   //建议原先父节点的父节点与cur的链接
        {
            _root = cur;
        }
        else
        {
            if (ppNode->_left == parent)
            {
                ppNode->_left = cur;
            }
            else
            {
                ppNode->_right = cur;
            }
        }
    }
    void RotatelR(Node*& parent) //右单旋 调整父子节点树中顺序,建立链接(cur_right(?空)与parent,parent与cur,parent的parent(root?)与cur),调整平衡因子
    {
        Node* cur = parent->_left;
        Node* cur_right = cur->_right;

        parent->_left = cur_right;//1:将cur的右节点放入parent的左结点
        if (cur_right)
        {
            cur_right->_parent = parent;  //cur_right控制_parent
        }

        cur->_right = parent;//2:将parent放入cur的右节点
        Node* ppNode = parent->_parent;
        cur->_parent = parent->_parent; //cur的父节点为原parent的父亲
        parent->_parent = cur; //parent的父节点为cur
        if (parent == _root)   //建议原先父节点的父节点与cur的链接
        {
            _root = cur;
        }
        else
        {
            if (ppNode->_left == parent)
            {
                ppNode->_left = cur;
            }
            else
            {
                ppNode->_right = cur;
            }
        }
    }
    void RotatelRL(Node*& parent)  //预处理右旋+左单旋
    {
        Node* cur = parent->_right;
        Node* cur_left = cur->_left;

        RotatelR(parent->_right);
        RotateL(parent);

    }
    void RotatelLR(Node*& parent) //预处理左单旋+右旋
    {
        Node* cur = parent->_left;
        Node* cur_right = cur->_right;


        RotateL(cur);
        RotatelR(parent);
    }

    bool insert(const pair& kv)
    {
        if (_root == nullptr)
        {
            _root = new Node(kv);
            _root->_col = Black;
            return true;
        }
        //插入数据
        Node* cur = _root;
        Node* parent = cur;
        while (cur)
        {
            parent = cur;
            if (kv.first == cur->_kv.first)
            {
                return false;
            }
            else if (kv.first > cur->_kv.first)
            {
                cur = cur->_right;
            }
            else if (kv.first < cur->_kv.first)
            {
                cur = cur->_left;
            }
        }
        cur = new Node(kv);
        cur->_col = RED;
        if (parent->_kv.first < kv.first)
        {
            parent->_right = cur;
        }
        else
        {
            parent->_left = cur;
        }
        cur->_parent = parent;
        //1->插入新的结点cur为红色结点,如果其父亲parent是黑色结点直接true
        if (parent && parent->_col == Black) return true;
        //2->父亲是红色结点,爷爷一定为黑色结点,将爷爷节点变成红色,父亲节点变成黑色,叔叔结点变成黑色,爷爷继续向上查找;
        //2->父亲是红色结点,爷爷一定为黑色结点,将爷爷节点变成红色,父亲节点变成黑色,当叔叔结点存在且为黑色的时候,叔叔路线多了黑色结点,叔叔结点这一路线损失去一个黑节点,将parent红节点旋转变黑向上;
        //2->父亲是红色结点,爷爷一定为黑色结点,将爷爷节点变成红色,父亲节点变成黑色,当叔叔结点不存在的时候,以上操作会使得叔叔结点这一路线损失去一个黑节点,此时需要根据情况进行旋转
        //2.1 -> 向上查找,爷爷是根直接true ---- 爷爷cur ,爷爷的父亲为parent,重复1,2操作
        while (parent && parent->_col == RED)
        {
            Node* grandfather = parent->_parent; //爷爷
            Node* uncle = nullptr;
            grandfather->_left == parent ? uncle = grandfather->_right : uncle = grandfather->_left; //叔叔
            if (uncle && uncle->_col == RED) //叔叔存在且为红色,叔叔结点变成黑色
            {
                grandfather->_col = RED;
                parent->_col = uncle->_col = Black;
                cur = grandfather; //继续向上处理
                parent = grandfather->_parent;
                continue;
            }
            if (uncle == nullptr || uncle && uncle->_col == Black)//叔叔结点不存在 或者 叔叔结点存在且为黑色  旋转+变色
            {
                //四种旋转情况
                if (uncle == grandfather->_right)  //叔叔在右边
                {
                    if (cur == parent->_left)
                    {
                        RotatelR(grandfather);
                        parent->_col = Black; grandfather->_col = RED;
                        break;
                    }
                    else if (cur == parent->_right)
                    {
                        RotatelLR(grandfather);
                        cur->_col = Black; grandfather->_col = RED;
                        break;
                    }
                }
                else if (uncle == grandfather->_left) //叔叔在左边
                {
                    if (cur == parent->_right)
                    {
                        RotatelL(grandfather);
                        parent->_col = Black; grandfather->_col = RED;
                        break;
                    }
                    else if (cur == parent->_right)
                    {
                        RotatelRL(grandfather);
                        cur->_col = Black; grandfather->_col = RED;
                        break;
                    }
                }
            }
        }
        _root->_col = Black;
        return true;
    }
private:
    Node* _root=nullptr;
};

int main()
{
    return 0;
}

你可能感兴趣的:(算法,数据结构)