C++实现红黑树

红黑树的基本概念:

红黑树是一个平衡二叉树(左子节点比当前节点小,右子节点比当前节点大)。

一棵红黑树需要满足以下条件:

1.根节点的颜色是黑色的。

2.一个节点要么是黑色,要么是红色。

3.红色节点的子节点必须是黑色节点。(红色节点被黑色节点隔开)

4.叶子节点的颜色是黑色的。

5.从根节点出发到叶子节点,每一条路径的黑色节点数量是相同的。(黑高)。

红黑树的类声明:

#include"iostream"
#include"math.h"
using namespace std;


#define RED 0
#define BLACK 1

class RBtree{
private:
// 红黑树的属性


    

    

public:


    RBtree();
    // 根节点
    RBtree *root;
    // 数据
    int data;
        // 颜色
    bool color;
    // 父亲节点
    RBtree *parent;
    // 左子节点
    RBtree *left;
    // 右子节点
    RBtree *right;




    // 节点插入函数,传入一个数据和一个根节点
    RBtree *rbinsert(int data,RBtree *root);
    // 节点删除传入一个要删除的数据和一个节点
    RBtree *rbdelete(int data,RBtree *root);
    // 节点的查找
    RBtree *rbsearch(int data,RBtree *root);
    
    // 最大值
    RBtree *rbmax(RBtree *root);
    // 最小值
    RBtree *rbmin(RBtree *root);

   // 右旋转
    RBtree *rrotate(RBtree *root,RBtree *x);
     // 左旋转
    RBtree *lrotate(RBtree *root,RBtree *x);

    // 插入修复
    RBtree *rbinsertfixup(RBtree *x);

    // 树的遍历
    void rbprint(RBtree *x);



    
    ~RBtree();

};

红黑树的插入:

#include"RBtree.h"
// 插入修复
RBtree *insert_fixup(RBtree *root,RBtree *x)
{

//  如果x的父节点的color是red,并且x节点不是root节点
    while (x->parent && x->parent->color==RED)
    {
        // 如果x的父是在祖父节点的左边
        if(x->parent == x->parent->parent->left)
        {
            // 确定叔叔节点
            RBtree *y = x->parent->parent->right;
            // 情况1:y节点的颜色是red,并且y不是空节点
            if(y && y->color==RED)
            {
                x->parent->color=BLACK;
                y->color=BLACK;
                x= y->parent;
                x->color=RED;
            }
            // 情况2:y节点是黑色的,并且x的位置是三角型
            else 
            if(x==x->parent->right)
            {
                x=x->parent;
                root=root->lrotate(root,x);
            }
            // 情况3:y的节点是黑色,并且x的位置是直线
            else
            {
                x->parent->color=BLACK;
                x->parent->parent->color=RED;
                root=root->rrotate(root,x->parent->parent);
            }
        }
        else
        // x的父节点在祖父节点的右边
        {
            // 确定叔叔节点
            RBtree *y = x->parent->parent->left;
            // 情况1:y节点的颜色是red,并且y不是空节点
            if(y && y->color==RED)
            {
                x->parent->color=BLACK;
                y->color=BLACK;
                x= y->parent;
                x->color=RED;
            }
            // 情况2:y节点是黑色的,并且x的位置是三角型
            else 
            if(x==x->parent->left)
            {
                x=x->parent;
                root=root->rrotate(root,x);
            }
            // 情况3:y的节点是黑色,并且x的位置是直线
            else
            {
                x->parent->color=BLACK;
                x->parent->parent->color=RED;
                root=root->lrotate(root,x->parent->parent);
            }
        }
    }
    // 根节点的颜色始终是黑色
    root->color=BLACK;
    return root;
    
}
RBtree * RBtree::rbinsert(int data,RBtree *root)
{
    //  实现将data插入rbtree

    // 创建一个节点得到数据
    RBtree *newnode = new RBtree;

    newnode->data = data;

    // 如果root为空,第一个节点
    if(root== nullptr)
    {
        // 直接就是根节点
        root=newnode;
    }
    // 如果root不为空
    // 开始插入
    else
    {
        //辅助指针
        RBtree *x = root;
        RBtree *y;
        // 如果x不为空
        while(x)
        {
            // y的位置始终在x的后面
            y=x;
            // 如果newnode的data比x的data小
            if(newnode->data<x->data)
            {
                // 从左边走
                x=x->left;
            }
            else
            {
                // 从右边走
                x=x->right;
            }
        }
        // 开始连接
        // 确定newnode的父节点
        newnode->parent=y;
        if(newnode->data<y->data)
        {
            // 连接左边
            y->left=newnode;
        }
        else
        {
            y->right=newnode;
        }

        

    }
    // 对newnode节点进行修复
    root=insert_fixup(root,newnode);


    return root;
}

红黑树的删除:

#include"RBtree.h"

RBtree *delete_fixup(RBtree *root,RBtree *x)
{
    while(x!=root && x->color==BLACK)
    {
        // 判断x的位置
        if(x==x->parent->left)
        {
            // 确定w节点
            RBtree *w=x->parent->right;
            

            // 情况1:w是红色节点
            if(w->color==RED)
            {
                // 将w的颜色染成黑色
                w->color=BLACK;
                // x的父节点的颜色染成红色
                x->parent->color=RED;
                // 对x的父节点左旋
                root=root->lrotate(root,x->parent);
                // 使得w成为新的兄弟节点
                w=x->parent->right;

            }
            // 情况2:w的左右子节点都是黑色,或者w左右都是空节点,因为空节点的颜色本来就是黑色的
            if((w->left==nullptr && w->right==nullptr)
            // 或者w的left是一个黑节点或者w的right节点是一个空节点
             || (w->left && w->left->color==BLACK && w->right==nullptr)
            //  或者w的right是一个黑色节点或者w的left节点是一个空节点
             || ((w->right && w->right->color==BLACK && w->left==nullptr))
             || (
                    // 确保w的左边和右边不是空节点
                    (w->left && w->right) 
                    && 
                    // 确保w的左边和右边都是黑色节点
                    (w->left->color==BLACK && w->right->color==BLACK)
                )
              )
            {
                // w的颜色直接染成红色
                w->color=RED;
                // x直接上移一个
                x=x->parent;
            }
            // 情况3:w右孩子是黑色,或者w的右孩子是空的
            else
            if(w->right==nullptr || w->right->color==BLACK)
            {
                w->left->color=BLACK;
                w->color=RED;
                root=root->rrotate(root,w);
                w=x->parent->right;

            }
            // 情况4:结束
            else
            {
                w->color=x->parent->color;
                x->parent->color=BLACK;
                // 判断w的right是否是节点
                if(w->right)
                {
                    w->right->color=BLACK;
                }
                root=root->lrotate(root,x->parent);
                x=root;
            }
        }
        else
        {
            // 确定w节点
            RBtree *w=x->parent->left;
            

            // 情况1:w是红色节点
            if(w->color==RED)
            {
                // 将w的颜色染成黑色
                w->color=BLACK;
                // x的父节点的颜色染成红色
                x->parent->color=RED;
                // 对x的父节点右旋
                root=root->rrotate(root,x->parent);
                w=x->parent->left;

            }
            // 情况2:w的左右子节点都是黑色,或者w左右都是空节点,因为空节点的颜色本来就是黑色的
            if((w->left==nullptr && w->right==nullptr)
            // 或者w的left是一个黑节点或者w的right节点是一个空节点
             || (w->left && w->left->color==BLACK && w->right==nullptr)
            //  或者w的right是一个黑色节点或者w的left节点是一个黑色节点
             || ((w->right && w->right->color==BLACK && w->left==nullptr))
             || (
                    // 确保w的左边和右边不是空节点
                    (w->left && w->right) 
                    && 
                    // 确保w的左边和右边都是黑色节点
                    (w->left->color==BLACK && w->right->color==BLACK)
                )
              )
              {
                // w的颜色直接染成红色
                w->color=RED;
                // x直接上移一个
                x=x->parent;
            }
            // 情况3:w右孩子是黑色,或者w的右孩子是空的
            else
            if(w->left==nullptr || w->left->color==BLACK)
            {
                w->right->color=BLACK;
                w->color=RED;
                root=root->lrotate(root,w);
                w=x->parent->left;

            }
            // 情况4:结束
            else
            {
                w->color=x->parent->color;
                x->parent->color=BLACK;
                // 判断w的left是否是节点
                if(w->left)
                {
                    w->left->color=BLACK;
                }
                root=root->rrotate(root,x->parent);
                x=root;
            }
        }
    }
    x->color=BLACK;
    return root;
}


RBtree *RBtree::rbdelete(int data,RBtree *root)
{
    // 搜索节点要删除的节点
    RBtree *delenode = root->rbsearch(data,root);

    // 直到delenode被释放
    while(delenode!=nullptr)
    {
        // 如果删除的是根节点
        if(delenode == root)
        {
            // 如果根节点有两个子节点
            if(delenode->right && delenode->left)
            {
                // 首先找到delenode的right的最小值
                RBtree *rmin = delenode->rbmin(delenode->right);
                // 把rmin的data给到delenode的data
                delenode->data=rmin->data;
                // 直接去删除rmin
                delenode = rmin;

                // // 就直接把delenode的data改成,deletnode的right的最小值
                // delenode->data=delenode->right->rbmin(delenode->right)->data;
                // // 去删除delenode
                // delenode=delenode->right->rbmin(delenode->right);
            }
            else
            // 如果根节点只有一个右节点
            if(delenode->right)
            {
                // 对delenode 修复
                root=delete_fixup(root,delenode);

                // 新的根
                root=delenode->right;
                root->parent = nullptr;

                //删除根
                delete delenode; 
                delenode =nullptr;
            }
            else
            // 根节点只有一个左节点
            if(delenode->left)
            {
                // 对delenode 修复
                root=delete_fixup(root,delenode);

                root=delenode->left;
                root->parent=nullptr;
                delete delenode;
                delenode = nullptr;
            }
            else
            // 删除根节点
            {

                root =nullptr;
                delete delenode;
                delenode = nullptr;
            }
        }
    // 删除的是除了根节点以外的节点
        else
        {
            // 判断要删除节点的方向
            if(delenode->parent->left==delenode)
            {
                // 要删除的节点在delenod的父节点的左边

                // 
                if(delenode->right && delenode->left)
                {
                    // 情况1:delenode有两个子节点
                    RBtree *rmin = root->rbmin(delenode->right);
                    // 替换内容
                    delenode->data=rmin->data;
                    // 直接删除rmin
                    delenode = rmin;
                    // 将第四种情况转换成第一种情况
                }
                else
                if(delenode->left)
                {
                    // 对delenode 修复
                    root=delete_fixup(root,delenode);
                    // 情况2:deletnode有一个left节点

                    // delenode父节点的左边连接denode的左边
                    delenode->parent->left=delenode->left;
                    // delenode的的左孩子的父节点连接delenode的父节点
                    delenode->left->parent=delenode->parent;
                    // 删除节点
                    delete delenode;
                    delenode = nullptr;
                }
                else
                if(delenode->right)
                {
                    // 对delenode 修复
                    root=delete_fixup(root,delenode);
                    // 情况3:deletnode有一个right节点

                    // delenode父节点的左边连接denode的左边
                    delenode->parent->left=delenode->right;
                    // delenode的的左孩子的父节点连接delenode的父节点
                    delenode->right->parent=delenode->parent;
                    // 删除节点
                    delete delenode;
                    delenode = nullptr;
                }
                else
                {
                    // 对delenode 修复
                    root=delete_fixup(root,delenode);
                    // 情况4:delenode没有子节点
                    delenode->parent->left =nullptr;
                    delete delenode;
                    delenode=nullptr;
                }


            }
            else
            {
                // 要删除的节点在delenod的父节点的右边
                

                // 
                if(delenode->right && delenode->left)
                {
                    // 情况1:delenode有两个子节点
                    RBtree *rmin = root->rbmin(delenode->right);
                    // 替换内容
                    delenode->data=rmin->data;
                    // 直接删除rmin
                    delenode = rmin;
                    // 将第四种情况转换成第一种情况
                }
                else
                if(delenode->left)
                {
                    // 对delenode 修复
                    root=delete_fixup(root,delenode);
                    // 情况2:deletnode有一个left节点

                    // delenode父节点的左边连接denode的左边
                    delenode->parent->right=delenode->left;
                    // delenode的的左孩子的父节点连接delenode的父节点
                    delenode->left->parent=delenode->parent;
                    // 删除节点
                    delete delenode;
                    delenode = nullptr;
                }
                else
                if(delenode->right)
                {
                    // 对delenode 修复
                    root=delete_fixup(root,delenode);
                    // 情况3:deletnode有一个right节点

                    // delenode父节点的左边连接denode的左边
                    delenode->parent->right=delenode->right;
                    // delenode的的左孩子的父节点连接delenode的父节点
                    delenode->right->parent=delenode->parent;
                    // 删除节点
                    delete delenode;
                    delenode = nullptr;
                }
                else
                {
                    // 对delenode 修复
                    root=delete_fixup(root,delenode);
                    // 情况4:delenode没有子节点
                    delenode->parent->right =nullptr;
                    delete delenode;
                    delenode=nullptr;
                }
            }
        }
    }
    



    return root;
}

寻找节点的最大值

// 查找最大值
#include"RBtree.h"
RBtree *RBtree::rbmax(RBtree *root)
{
    RBtree *x =root;
    RBtree *y;
    while (x)
    {
        y=x;
        x=x->right;
    }
    return y;
    
}

寻找最小值:

// 查找最小值
#include"RBtree.h"
RBtree *RBtree::rbmin(RBtree *root)
{
    RBtree *x =root;
    RBtree *y;
    while (x)
    {
        y=x;
        x=x->left;
    }
    return y;
    
}

红黑树的遍历输出:

#include"RBtree.h"

 // 树的遍历
void RBtree::rbprint(RBtree *x)
{
    if(x)
    {
        rbprint(x->left);
        cout<<x->data<<endl;
        rbprint(x->right);
    }
}

红黑树的查找:

#include"RBtree.h"

// rb树的查找
RBtree* RBtree::rbsearch(int data,RBtree *root)
{
    RBtree *snode =root;
    while (snode!=nullptr)
    {
        // 如果snode的data比data要小
       if(snode->data<data)
       {
        // 右边走
            snode=snode->right;
       }
    //    如果snode的data比data要大
       else if(snode->data>data)
       {
        // 左边边走
            snode = snode->left;
       }
       else
       {
         // 找到了
            // 返回这个节点的地址
            return snode;

       }

    }
    return nullptr;
    
    
}

红黑树的左旋:

#include"RBtree.h"
// 左旋转
RBtree *RBtree::lrotate(RBtree *root,RBtree *x)
{
    // 根节点的旋转
    RBtree *y;
    // y在x的右边
    y=x->right;
    // 开始旋转
    if(x == root)
    {
        // 如果x的right不是空节点
        if(x->right)
        {
            // x的右边
            x->right=y->left;
            // 判断y的left是否有节点
            if(y->left)
            {
                y->left->parent=x;
            }
            // y的左边
            y->left=x;
            x->parent=y;
            // 连接root
            root=y;
            y->parent=nullptr;
        }


    }
    else
    {
        // 判断x是左孩子还是右孩子
        if(x->parent->left==x)
        {
            // x在父节点的左边
            
            // 改变x父节点到y
            x->parent->left=y;

        }
        else
        {
            // x在父节点的右边
            // 改变x父节点到y
            x->parent->right=y;
        }
        y->parent=x->parent;

        // x的右边
        x->right=y->left;
        // 判断y是否有left节点
        if(y->left)
        {
            y->left->parent=x;
        }
        
        // y的左边
        y->left=x;
        x->parent=y;


    }
    return root;
}

红黑树的右旋:

#include"RBtree.h"
// 右旋转
RBtree *RBtree::rrotate(RBtree *root,RBtree *x)
{
    // 根节点的旋转
    RBtree *y;
    // y在x的左边
    y=x->left;
    // 开始旋转
    if(x == root)
    {
        // 如果x的left不是空节点
        if(x->left)
        {
            // x的左边
            x->left=y->right;
            // 判断y的left是否有节点
            if(y->right)
            {
                y->right->parent=x;
            }
            // y的右边
            y->right=x;
            x->parent=y;
            // 连接root
            root=y;
            y->parent=nullptr;
        }


    }
    else
    {
        // 判断x是左孩子还是右孩子
        if(x->parent->right==x)
        {
            // x在父节点的右边
            
            // 改变x父节点到y
            x->parent->right=y;

        }
        else
        {
            // x在父节点的右边
            // 改变x父节点到y
            x->parent->left=y;
        }
        y->parent=x->parent;

        // x的左边
        x->left=y->right;
        // 判断y是否有left节点
        if(y->right)
        {
            y->right->parent=x;
        }
        
        // y的右边
        y->right=x;
        x->parent=y;


    }
    return root;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值