二叉搜索树---红黑树节点插入

1.红黑树的概念:红黑树是一棵二叉搜索树,它在每个节点上增加一个存储位来表示节点的颜色,可以是red或black,通过对任何一条从根节点到叶子节点上的间单路径来约束,红黑树保证最长路径不超过最短路径的两倍,因而近视平衡。

2.红黑树的性质

  • 性质1,每个节点不是黑色就是红色
  • 性质2,根节点是黑色的;
  • 性质3,如果一个根节点是红色的,则它的两个叶子节点是红色的,即没有两个连续节点是红色节点
  • 性质4,对于每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点,即每条路径上黑色节点的个数是相等的;
  • 性质5,每个节点其空指针域是颜色的黑色的

满足上诉性质的二叉搜索树是二叉搜索树

3.具体插入节点的步骤:
这里写图片描述

对于插入节点的双亲节点是红色时,我们又分为三种情况对其调整

  • 情况1
    这里写图片描述

  • 情况2
    这里写图片描述

  • 情况3
    这里写图片描述

4.根据上述的五种情况,实现代码

#include<stdio.h>
#include<iostream>
using namespace std;

enum COLOR{RED,BLACK,};

template<class k,class v>
struct RBTreeNode
{
    RBTreeNode(const k& key,const v& value,COLOR color = RED)
        :_pLeft(NULL)
        ,_pRight(NULL)
        ,_pParent(NULL)
        ,_key(key)
        ,_value(value)
        ,_color(color)
    {}

    RBTreeNode<k,v>* _pLeft;
    RBTreeNode<k,v>* _pRight;
    RBTreeNode<k,v>* _pParent;
    k _key;
    v _value;
    COLOR _color;
};
template<class k,class v>
class RBTree
{
public:
    typedef RBTreeNode<k,v> Node;
    RBTree()
        :_pRoot(NULL)
    {}

    bool Insert(const k& key,const v& value)
    {
        return _Insert(key,value);
    }

    void InOrder()
    {
        cout<<"InOrder: ";
        _InOrder(_pRoot);
        cout<<endl;
    }

    bool CheckRBTree()
    {
        if(_pRoot == NULL)
            return true;
        if(_pRoot->_pLeft == NULL && _pRoot->_pRight == NULL)
        {
            if(_pRoot->_color == BLACK)
                return true;
            else
                return false;
        }

        int blackcount = 0;
        Node* pCur = _pRoot;
        while(pCur)
        {
            if(pCur->_color == BLACK)
                blackcount++;
            pCur= pCur->_pLeft;
        }

        int k = 0;
        return _CheckRBTree(_pRoot,blackcount,k);
    }

private:
    bool _CheckRBTree(Node* pRoot,int blackcount,int k)
    {
        if(pRoot == NULL)
            return true;
        if(pRoot->_color == BLACK)
            ++k;
        Node* pParent = pRoot->_pParent;
        if(pParent && pParent->_color == RED && pRoot->_color == RED)
        {
            cout<<"红色节点相邻,违反了性质3"<<endl;
            return false;
        }
        if(pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
        {
            if(k != blackcount)
            {
                cout<<"每条路径的黑色节点个数不同,违反了性质4"<<endl;
                return false;
            }
        }
        return _CheckRBTree(pRoot->_pLeft,blackcount,k)&&_CheckRBTree(pRoot->_pRight,blackcount,k);
    }
    void _InOrder(Node* pRoot)
    {
        if(pRoot == NULL)
            return;
        _InOrder(pRoot->_pLeft);
        cout<<pRoot->_key<<" ";
        _InOrder(pRoot->_pRight);
    }
    bool _Insert(const k& key,const v& value)
    {
        if(_pRoot == NULL)
        {
            _pRoot = new Node(key,value,BLACK);
            return true;
        }
        //找到要节点删除的位置
        Node* pNode = _pRoot;
        Node* pParent = NULL;
        while(pNode)
        {
            if(pNode->_key > key)
            {
                pParent = pNode;
                pNode = pNode->_pLeft;
            }
            else if(pNode->_key < key)
            {
                pParent = pNode;
                pNode = pNode->_pRight;
            }
            else 
            {
                return false;//找到key值节点,不用插入,直接退出
            }
        }

        //已经找到
        pNode = new Node(key,value);
        if(pParent->_key > key)
        {
            pParent->_pLeft = pNode;
            pNode->_pParent = pParent;
        }
        else
        {
            pParent->_pRight = pNode;
            pNode->_pParent = pParent;
        }

        //对红黑树进行调整


        while(pParent && pParent->_color == RED && pNode->_color == RED)
        {
            Node* grandFather = pParent->_pParent;
            Node* pUncle = NULL;

            找到pUncle节点
            //if(grandFather->_pLeft == pParent)
            //  pUncle = grandFather->_pRight;
            //else
            //  pUncle = grandFather->_pLeft;

            if(grandFather->_pLeft == pParent)//节点插在左子树
            {
                pUncle = grandFather->_pRight;
                if(pUncle && pUncle->_color == RED)//情况一
                {
                    pUncle->_color = BLACK;
                    pParent->_color = BLACK;
                    grandFather->_color = RED;

                    pNode = grandFather;
                    pParent = grandFather->_pParent;

                }

                else//在处理情况三的过程中顺便处理情况二
                {
                    if(pParent && pParent->_pRight == pNode)
                    {
                        //先左旋再右旋
                        _RotateL(pParent);
                        swap(pNode,pParent);
                    }
                    grandFather->_color = RED;
                    pParent->_color = BLACK;
                    _RotateR(grandFather);
                }
            }
            else
            {
                pUncle = grandFather->_pLeft;
                if(pUncle && pUncle->_color == RED)//情况一
                {
                    pUncle->_color = BLACK;
                    pParent->_color = BLACK;
                    grandFather->_color = RED;

                    pNode = grandFather;
                    pParent = grandFather->_pParent;


                }
                //在处理情况三的过程中顺便处理情况二

                else
                {
                    if(pUncle && pUncle->_color == BLACK && pParent->_pLeft == pNode)//情况三
                    {
                        //先左旋再右旋
                        _RotateR(pParent);
                        swap(pNode,pParent);
                    }
                    grandFather->_color = RED;//情况二
                    pParent->_color = BLACK;
                    _RotateL(grandFather);
                }
            }
        }
        _pRoot->_color = BLACK;
    }

    void _RotateL(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;

        pSubR->_pParent = pPParent;
        if(pPParent == NULL)
            _pRoot = pSubR;
        else if(pPParent->_pLeft == pParent)
            pPParent->_pLeft = pSubR;
        else 
            pPParent->_pRight = pSubR;
    }

    void _RotateR(Node*& pParent)
    {
        Node* pSubL = pParent->_pLeft;
        Node* pSubLR = pSubL->_pRight;

        pParent->_pLeft = pSubLR;
        if(pSubLR)
            pSubLR->_pParent = pParent;
        pSubL->_pRight = pParent;
        Node* pPParent = pParent->_pParent;
        pParent->_pParent = pSubL;

        pSubL->_pParent = pPParent;
        if(pPParent==NULL)
            _pRoot = pSubL;
        else if(pPParent->_pLeft == pParent)
            pPParent->_pLeft = pSubL;
        else
            pPParent->_pRight = pSubL;
    }
private:
    Node* _pRoot;
};

测试代码:

void funtest()
{
    RBTree<int ,int> rbt;
    int array[] = {40,30,60,10,50,80,20,70};
    for(size_t idx=0; idx<sizeof(array)/sizeof(array[0]); ++idx)
        rbt.Insert(array[idx],array[idx]);
    rbt.InOrder();
    if(rbt.CheckRBTree())
    {
        cout<<"该树是红黑树"<<endl;
    }
    else
    {
        cout<<"该树不是红黑树"<<endl;
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值