红黑树

红黑树:红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是red或者black,通过对任何一条从根节点到叶子结点上的简单路径来约束,红黑树保证最长路径不超过最短路径的两倍,因而近视平衡。
性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个根节点是红色的,则它的两个叶子结点是黑色的(没有两个连续
的红色结点)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相
同数目的黑色结点(每条路径上黑色结点的数量相等)
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
插入的实现:
pCur为当前结点,parent为父亲结点,uncle为叔叔结点,grandpa为祖父结点
第一种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle存在且为红色
做如下调整:parent改为黑色,grandpa改为红色,uncle改为黑色
这里写图片描述
第二种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle不存在或存在且为黑色
做如下调整:grandpa的左孩子为parent,parent的左孩子为pCur时,对grandpa进行右单旋,parent改为黑色,grandpa改为红色;
grandpa的右孩子为parent,parent的右孩子为pCur时,对grandpa进行左单旋,parent改为黑色,grandpa改为红色;
这里写图片描述
第三种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle不存在或存在且为黑色
做如下调整:grandpa的左孩子为parent,parent的右孩子为pCur时,先对parent进行左单旋并交换pCur和parent,然后对grandpa进行右单旋,pCurt改为黑色,grandpa改为红色;
grandpa的右孩子为parent,parent的左孩子为pCur时,先对parent进行右单旋并交换pCur和parent,然后对grandpa进行左单旋,pCurt改为黑色,grandpa改为红色;
这里写图片描述
完整代码如下:
rbt.cpp

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
enum Color
{
    RED,
    BLACK
};
template<class K,class V>
struct RBTreeNode
{
    RBTreeNode(const K& key,const V& value, Color color=RED)
    : _value(value)
    , _key(key)
    , _left(NULL)
    , _right(NULL)
    , _parent(NULL)
    , _color(color)
    {}
    K _key;
    V _value;
    RBTreeNode<K,V>* _left;
    RBTreeNode<K, V>* _right;
    RBTreeNode<K, V>* _parent;
    Color _color;
};
template<class K, class V>
class RBTree
{
    typedef RBTreeNode<K, V>Node;
public:
    RBTree()
    :_pRoot(NULL)
    {}
    //插入
    bool Insert(const K& key,const V& value)
    {
        if (NULL == _pRoot)
        {
            _pRoot = new Node(key, value);
            return true;
        }
        //寻找插入位置
        Node* pCur = _pRoot;
        Node* parent = NULL;
        while (pCur)
        {
            if (pCur->_key < key)
            {
                parent = pCur;
                pCur = pCur->_right;
            }
            else if (pCur->_key>key)
            {
                parent = pCur;
                pCur = pCur->_left;
            }
            else
            {
                return false;
            }
        }
        //插入结点
        pCur = new Node(key, value);
        if (parent->_key > key)
        {
            parent->_left=pCur;
            pCur->_parent = parent;
        }
        else
        {
            parent->_right=pCur;
            pCur->_parent = parent;
        }
        while (parent != _pRoot && parent->_color == RED)
        {
            Node* grandpa = parent->_parent;
            if ( grandpa->_left==parent)
            {
                Node* uncle = grandpa->_right;
                {
                    Node* uncle = grandpa->_right;
                    //叔叔结点存在且为红色
                    if (uncle &&uncle->_color == RED)
                    {
                        parent->_color = BLACK;
                        uncle->_color = BLACK;
                        grandpa->_color = RED;
                        //继续向上调整
                        pCur = grandpa;
                        parent = pCur->_parent;
                    }
                    //叔叔结点不存在或叔叔结点存在为黑色
                    else
                    {
                        //pCur为parent的右孩子
                        if (pCur == parent->_right)
                        {
                            RotateL(parent);
                            swap(pCur, parent);
                        }
                        parent->_color = BLACK;
                        grandpa->_color = RED;
                        RotateR(grandpa);
                        break;
                    }
                }
            }
            //parent=grandpa->_right
            else
            {
                Node* uncle = grandpa->_left;
                //叔叔结点存在且为红色
                if (uncle &&uncle->_color == RED)
                {
                    parent->_color = BLACK;
                    uncle->_color = BLACK;
                    grandpa->_color = RED;
                    //继续向上调整
                    pCur = grandpa;
                    parent = pCur->_parent;
                }
                else
                {
                    //pCur为parent的左孩子
                    if (pCur == parent->_left)
                    {
                        RotateR(parent);
                        swap(pCur, parent);
                    }
                    parent->_color = BLACK;
                    grandpa->_color = RED;
                    RotateL(grandpa);
                    break;
                }
            }
            _pRoot->_color = BLACK;
            return true;
        }
    }

    //中序遍历
    void Inorder()
    {
        return _Inorder(_pRoot);
    }

    //查找结点
    bool Find(const K& key)
    { 
        Node* pCur = _pRoot;
        if (pCur == NULL)
            return false;
        else
        {
            while (pCur)
            {
                if (pCur->_key < key)
                    pCur = pCur->_right;
                else if (pCur->_key>key)
                    pCur = pCur->_left;
                else
                    return true;
            }
        }
        return true;
    }

    //判断是否平衡
    bool IsBalance()
    {
        if (NULL == _pRoot)
            return true;
        if (_pRoot->_color == RED)
            return false;
        int k = 0;
        Node* pCur = _pRoot;
        while (pCur)
        {
            //记录其中一条路径黑色结点个数
            if (pCur->_color == BLACK)
                ++k;
            pCur = pCur->_left;
        }
        //另一条路径黑色结点个数
        int count = 0;
        return _IsBalance(_pRoot, k, count);
    }

    //左旋
    void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        subR->_left = parent;
        parent->_right = subRL;
        if (subRL)
            subRL->_parent = parent;
        Node* pparent = parent->_parent;
        if (NULL == pparent)
        {
            _pRoot = subR;
            subR->_parent = NULL;
        }
        else
        {
            if (pparent->_left == parent)
                pparent->_left = subR;
            else
                pparent->_right = subR;
            subR->_parent = pparent;
        }
        parent->_parent = subR;
    }

    //右旋
    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        subL->_right = parent;
        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;
        Node* pparent = parent->_parent;
        if (NULL == pparent)
        {
            _pRoot = subL;
            subL->_parent = NULL;
        }
        else
        {
            if (pparent->_left == parent)
                pparent->_left = subL;
            else
                pparent->_right = subL;
            subL->_parent = pparent;
        }
        parent->_parent = subL;
    }

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

    bool _IsBalance(Node* pRoot, int k, int count)
    {
        if (NULL == pRoot)
            return true;
        if (pRoot->_color == RED)
        {
            if (pRoot->_parent&&pRoot->_parent->_color == RED)
                return false;
        }
        else
            count++;
        if (pRoot->_left == NULL&&pRoot->_right == NULL)
        { 
            //比较两条路径黑色结点个数
            if (k == count)
                return true;
            else
                return false;
        }
        return _IsBalance(pRoot->_left, k, count) && _IsBalance(pRoot->_left, k, count);
    }

private:
    Node* _pRoot;
};
void test()
{
    RBTree<int, int> rbt;
    /*int array[] = {5,2,1,3,4,0,7,8,6};
    int size = sizeof(array) / sizeof(array[0]);
    for (int i = 0; i < size; i++)
    {
        rbt.Insert(array[i],i);
    }*/
    rbt.Insert(5, 5);
    rbt.Insert(2, 2);
    rbt.Insert(1, 1);
    rbt.Insert(3, 3);
    rbt.Insert(4, 4);
    rbt.Insert(0, 0);
    rbt.Insert(7, 7);
    rbt.Insert(8, 8);
    rbt.Insert(6, 6);
    rbt.Inorder();
    cout << "\n";
    cout<<rbt.Find(5)<<endl;
    cout << "\n";
    cout << rbt.IsBalance() << endl;

}
int main()
{
    test();
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值