简单实现红黑树

构建

红黑树是一个较平衡二叉树,最深的叶子节点最多不能超过最浅的叶子节点的深度二倍
具有性质:

  1. 节点是红色或黑色。
  2. 根节点是黑色。
  3. 所有叶子都是黑色。(叶子是NUIL节点)
  4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点

对于结点的信息有:该节点的颜色、左右儿子指针、该节点储存的数据

#define RED 1
#define BLACK 0
template <typename T>
class RBTNode{
public:
    T data;
    int color;
    RBTNode*l,*r;
    RBTNode(T data){
        this.data=data;
        color=RED;
        l=r=NULL;
    }
};

对于红黑树的操作:主要 插入、查找、删除

template <typename T> class RBT{
private:
    RBTNode<T> *Root;
    void getColor(RBTNode<T> *root);
    void insert(RBTNode<T> *&root,T data);
    RBTNode<T> * find(RBTNode<T> *root,T data);
    void clear(RBTNode<T> *root);
public:
    void insert(T data);
    void remove(T data);
    bool find(T data);
    void clear();
    RBT();
    ~RBT();
};
template <typename T>
RBT<T>::RBT(){
    root=NULL;
}
template <typename T>
RBT<T>::~RBT(){
    clear();
}

插入

插入的过程就想 普通的二叉搜索树一样插入
插入一个节点就是直接插入一个红色叶子。
插入之后可能会破坏红黑树的 第一条性质第四条性质
当出现之后 可以通过 变色和旋转使得再次恢复红黑树的五条性质

插入时需要旋转和变色的情况具体的分可以分为8种
在这里插入图片描述
对于每一中情况的旋转变色方案的解决方法
在这里插入图片描述
对于前四种不需要旋转,只需要对第一层第二层变色既可以恢复其第四条性质
然后递归到上一层在解决
在这里插入图片描述
在这里插入图片描述
对于后四种情况,既需要选择也需要变色,其前后变化关系从图中可用看出

template <typename T>
void RBT<T>::getColor(RBTNode<T> *root){
    return  root==NULL?BLACK:root->color;
}
template <typename T>
void RBT<T>::insert(RBTNode<T> *&root,T data){
    if(root==NULL)root=new RBTNode<T>(data);
    else insert(data<root->data?root->l:root->r,data);
    if(getColor(root->l)==BLACK&&getColor(root->r)==BLACK)return;
    if(getColor(root->l)==RED&&getColor(root->r)==RED){
        root->l->color=root->r->color=BLACK;
        root->color=RED;
    }
    if(getColor(root->l)==RED&&getColor(root->l->l)==RED){
            root->l->l=BLACK;
            RBTNode<T> * lson= root->l;
            root->l=lson->r;
            lson->r=root;
            root=lson;
    }
    if(getColor(root->l)==RED&&getColor(root->l->r)==RED){
            root->l=BLACK;
            RBTNode<T> * lrson= root->l->r;
            root->l->r=lrson->l;
            lrson->l=root->l;
            root->l=lrson->r;
            lrson->r=root;
            root=lrson;
    }
    if(getColor(root->r)==RED&&getColor(root->l->l)==RED){
            root->r=BLACK;
            RBTNode<T> * rlson= root->r->l;
            root->r->l=rlson->r;
            rlson->r=root->r;
            root->r=rlson->l;
            rlson->l=root;
            root=rlson;
    }
    if(getColor(root->r)==RED&&getColor(root->l->r)==RED){
            root->r->r=BLACK;
            RBTNode<T> * rson= root->r;
            root->r=rson->l;
            rson->l=root;
            root=rson;
    }
}
template <typename T>
void RBT<T>::insert(T data){
    insert(Root,data);
    Root->color=BLACK;
}

查找

template <typename T>
RBTNode<T> * RBT<T>::find(RBTNode<T> *root,T data){
    if(root==NULL)return NULL;
    if(root->data==data)return root;
    return data<root->data?find(root->l,data):find(root->r,data);
}
template <typename T>
bool RBT<T>::find(T data){
    return find(Root,data)!=NULL;
}
//clear 顺便直接加上
template <typename T>
void RBT<T>::clear(RBTNode<T> *root){
    if(root==NULL)return;
    clear(root->l);
    clear(root->r);
    delete root;
}
template <typename T>
void RBT<T>::clear(){
    clear(Root);
}

删除

删除的情况讨论比较多

  1. 删除的节点是一个叶子节点
  2. 删除的节点拥有一个儿子节点
  3. 删除的节点拥有两个儿子节点

删除节点是叶子节点

如果删除节点是红色的话:
直接删掉就好。

如果删除节点为黑色

  1. 兄弟节点为红色
    在这里插入图片描述

  2. 兄弟节点的儿子节点为红色
    在这里插入图片描述
    在这里插入图片描述

  3. 父节点为红色
    在这里插入图片描述

  4. 兄弟节点,兄弟节点儿子节点,父亲节点都是黑色

在这里插入图片描述

删除节点拥有一个儿子节点

如果只有一个儿子,显然那个儿子不能为黑色,而且是个叶子节点
如果为黑色或者拥有其他儿子节点,那么久不可能满足 上面的性质5。
所以,如果被删除节点有一个儿子,那么那个儿子节点一定为红色叶子节点。

所以删除操作很简单,就是用那个叶子节点代替我们被删除的节点就可以。

在这里插入图片描述

删除节点拥有两个儿子节点

寻找该节点的前继(一定是一个叶子节点),删除掉前继,转化为第一种情况,然后使用被删除前继的值,代替当前节点的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值