让你彻底理解红黑树

/*首先呢,按照套路,介绍一下什么是红黑树?
一、定义:
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结
点的颜色,可以是red或者black,通过对任何一条从根节点到叶子结点上
的简单路径来约束,红黑树保证最长路径不超过最短路径的两倍,因而近视
平衡。
然后呢,我么就看一下红黑树有哪些性质呢?
二、性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个根节点是红色的,则它的两个叶子结点是黑色的(没有两个连续
的红色结点)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相
同数目的黑色结点(每条路径上黑色结点的数量相等)
5. 每个叶子结点都是黑色的(*此处的叶子结点指的是空结点*)
三、接下来,就开始上干货了->红黑树的插入(ps:有图有真相哦)!
注意:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
1、首先呢,要想在红黑树中插入节点(默认插入节点的颜色为红色哦,读者可以思考下为什么?),我们可以分为以下几种情况:
(0)空树直接插入,并把插入结点的颜色置为红色
(0)插入节点的双亲若为黑色,直接插入
以上这两种情况灰常简单,我们就不做过多介绍了,重点介绍以下三种情况:
【情况一】
cur为红,p为红,g为黑,u存在且为红,则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
【情况二】
cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色--p变黑,g变红。
【情况三】
cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转则转换成了情况2。
是不是看着好懵逼哈,别急,接下来我们就直接上图,这样就简单明了了:
*/

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

#include<iostream>
#include<windows.h>
//#pragma warning(disable :4996)
using namespace std;
enum Color{ RED, BLACK };
template<typename K, typename V>
struct RBTreeNode
{
    RBTreeNode(const K& key, const V& value)
    :_pLeft(NULL)
    , _pRight(NULL)
    , _pParent(NULL)
    , _key(key)
    , _value(value)
    , _color(RED)
    {}
    RBTreeNode<K, V>*_pLeft;
    RBTreeNode<K, V>*_pRight;
    RBTreeNode<K, V>*_pParent;
    K _key;
    V _value;
    Color _color;
};
template<typename K, typename V>
class RBTree
{
public:
    typedef  RBTreeNode<K, V> Node;
    RBTree()
        :_pRoot(NULL)
    {}
    bool Insert(const K&key, const V&value)
    {   //空树直接插入结点,并把颜色置黑
        if (NULL == _pRoot)
        {
            _pRoot = new Node(key, value);
            _pRoot->_color = BLACK;
            return true;
        }

        //树不空,找插入位置
        Node*pCur = _pRoot;
        Node*pParent = NULL;
        while (pCur)
        {
            if (pCur->_key<key)
            {
                pParent = pCur;
                pCur = pCur->_pRight;
            }
            else if (pCur->_key>key)
            {
                pParent = pCur;
                pCur = pCur->_pLeft;
            }
            else
                return false;//说明插入的结点树里已经有
        }
        pCur = new Node(key, value);//new的节点默认的颜色为红色,
        if (pParent->_color == BLACK)//插入节点的pParent->_color若为黑色,直接插,不会对树造成影响
        {
            if (key > pParent->_key)
            {
                pParent->_pRight = pCur;
            }
            else
            {
                pParent->_pLeft = pCur;
            }
            pCur->_pParent = pParent;
            return true;
        }
        else
        {
            if (key > pParent->_key)
            {
                pParent->_pRight = pCur;
            }
            else
            {
                pParent->_pLeft = pCur;
            }
            pCur->_pParent = pParent;
        }
        while (_pRoot != pCur&&RED == pParent->_color)
        {
            Node*GrandFather = pParent->_pParent;
            if (BLACK == GrandFather->_color)
            {
                if (pParent == GrandFather->_pLeft)//左边
                {
                    Node*Uncle = GrandFather->_pRight;
                    if (Uncle&&Uncle->_color == RED)//情况3,u存在且为红,
                    {
                        pParent->_color = BLACK;
                        Uncle->_color = BLACK;
                        GrandFather->_color = RED;

                        pCur = pParent;
                        pParent = pParent->_pParent;//向上更新
                    }
                    else   //情况四和情况五
                    {
                        if (pCur == pParent->_pRight)//先处理情况五 ,五包含四
                        {
                            _RotateLeft(pParent);
                            std::swap(pCur, pParent);//否则旋转后仍然不满足
                        }

                        _RotateRight(GrandFather);
                        pParent->_color = BLACK;
                        GrandFather->_color = RED;
                    }
                }
                else      //右边
                {
                    Node*Uncle = GrandFather->_pLeft;
                    if (Uncle&&Uncle->_color == RED)//情况3,u存在且为红,
                    {
                        pParent->_color = BLACK;
                        Uncle->_color = BLACK;
                        GrandFather->_color = RED;

                        pCur = pParent;
                        pParent = pParent->_pParent;//向上更新
                    }
                    else     //右边的情况四和情况五
                    {
                        if (pCur == pParent->_pLeft)//先处理情况五 ,五包含四
                        {
                            _RotateRight(pParent);
                            std::swap(pCur, pParent);//否则旋转后仍然不满足
                        }

                        _RotateLeft(GrandFather);
                        pParent->_color = BLACK;
                        GrandFather->_color = RED;
                    }
                }               
            }
            _pRoot->_color = BLACK;     
        }
        return true;
    }
    void InOrder()
    {
        cout << "InOrder:" << endl;
        _InOrder(_pRoot);
        cout << endl;
    }
protected:
    void _RotateLeft(Node*pParent)
    {
        Node*pSubR = pParent->_pRight;
        Node*pSubRL = pSubR->_pLeft;
        pParent->_pRight = pSubRL;
        if (pSubRL)
        {
            pSubRL->_pParent = pParent;
        }
        pSubR->_pLeft = pParent;
        Node*pPparent = pParent->_pParent;
        pParent->_pParent = pSubR;
        if (NULL == pPparent)
        {
            _pRoot = pSubR;
        }
        else
        {
            if (pParent == pPparent->_pLeft)
            {
                pPparent->_pLeft = pSubR;
            }
            else
            {
                pPparent->_pRight = pSubR;
            }
        }
        pSubR->_pParent = pPparent;     
    }
    void _RotateRight(Node*pParent)
    {
        Node*pSubL = pParent->_pLeft;
        Node*pSubLR = pSubL->_pRight;
        pParent->_pLeft = pSubLR;
        if (pSubLR)
        {
            pSubLR->_pParent = pParent;
        }
        Node*pPParent = pParent->_pParent;
        pParent->_pParent = pSubL;
        pSubL->_pRight = pParent;
        pSubL->_pParent = pPParent;
        if (NULL == pPParent)
        {
            _pRoot = pSubL;
        }
        else
        {
            if (pPParent->_pLeft == pParent)
            {
                pPParent->_pLeft = pSubL;
            }
            else
                pPParent->_pRight = pSubL;
        }
    }

    void _InOrder(Node*pRoot)
    {
        if (pRoot)
        {
            _InOrder(pRoot->_pLeft);
            cout << pRoot->_key<<" ";
            _InOrder(pRoot->_pRight);
        }
    }

public:

    bool CheckRBTree()
    {
        if (NULL == _pRoot)
            return true;
        if (NULL == _pRoot->_pLeft&&_pRoot->_pRight)
            return false;
        Node*pCur = _pRoot;
        size_t blackcount = 0;
        size_t k = 0;
        while (pCur)
        {
            if (BLACK== pCur->_color)
            {
                ++blackcount;           
            }
            pCur = pCur->_pLeft;
        }
        return _CheckRBTree(_pRoot, blackcount, k);
    }

    bool _CheckRBTree(Node*pRoot, size_t _count, size_t k)
    {
        if (NULL == pRoot)
            return true;
        if (BLACK == pRoot->_color)
            k++;        
        if (NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)
        {
            if (_count != k)
            {
                cout << "树中某一路径黑颜色节点个数不同" << endl;
                return false;
            }           
        }
        Node*pParent = pRoot->_pParent;
        if (pParent&&RED == pParent->_color&&RED == pRoot->_color)
        {
            cout << "树中有两个连在一起的红色节点" << endl;
            return false;
        }
        return _CheckRBTree(pRoot->_pLeft, _count, k) && _CheckRBTree(pRoot->_pRight, _count, k);
    }

private:
    Node* _pRoot;
};

void FUNRBTree()
{
    RBTree<int, int>RBT;
    int count = 0;
    int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
    for (size_t idx = 0; idx < sizeof(a) / sizeof(a[0]); idx++)
    {
        count++;
        RBT.Insert(a[idx], idx);
    }
    RBT.InOrder();
    bool flag = RBT.CheckRBTree();
    if (flag)
        cout << "是红黑树"<<endl;
    else
        cout << "不是红黑树" << endl;

}
int main()
{
    FUNRBTree();
    system("pause");
    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值