红黑树

> 红黑树

    红黑树(RB-Tree)是一种平衡二叉搜索树,虽然在本科的教材中对于红黑树讲解的内容很少,但是是一种被广泛应用的平衡二叉树,也是SGI STL唯一
实现的一种搜索树,作为关联式容器的底部机制之用。在C++ STL中,很多部分(包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中
的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)。因此不言而喻其重要性了,但是也是最难啃的一块骨头之一。
    红黑树不仅是一个二叉排序树,而且具有以下的性质:
1.每个节点不是红色就是黑色。
2.根节点为黑色。
3.如果一个节点的颜色为红色,则其子节点的颜色必须为黑色。
4.任何一个节点至NULL(树尾端)的任何路径,所含黑节点数必须相同。
5.为计算方便,我们一般视NULL为黑色节点。
    由于红黑树以上的性质使一棵n个结点的红黑树始终保持了log2n的高度,从而也就说明了红黑树的查找、插入、删除的时间复杂度最坏为O(log2n)。
红黑树(RB-Tree)的节点设计:
    红黑树有红黑两种颜色,并且拥有左右子节点,由于红黑树的各种操作需要方便的上溯到其父节点,因此增加一个指向其父节点的指针parent。
typedef struct _rb_tree_node_base
{
    typedef bool color_type
    color_type color; 
    _rb_tree_node_base* left;
    _rb_tree_node_base* right;
    _rb_tree_node_base* parent;
}node;
enum color{Black,Red};//插入一个节点,颜色初始化为红色
    红黑树(RB-Tree)的插入:(该部分内容确认你已经了解了二叉排序树的插入以及树的旋转等内容)
红黑树中插入一个新的元素记为节点X,X的父节点记为P,X的父节点的父节点记为G,X的叔父节点记为U,后文中都是使用该符号,在图中显示如下图:

如果我们需要找到节点X的祖父节点G和叔父节点U,实现代码如下:
//查找祖父节点G
int grandparent(node x)
{
    return x->parent->parent;
}
//查找叔父节点U
int uncle(node x)
{
    if(x->parent==grandparent(x)->left)
    {
        return grandparent(x)->right;
    }
    else
    {
        return grandparent(x)->left;
    }
}
红黑树插入新节点的情况分类:
S1.新插入节点X位于树根上,其父节点为NULL,则直接将给节点的颜色设置为Black,如图s1:

这里写图片描述

void Insert_S1(node x)
{
    if(x->parent==NULL)
    {
        x->color=Black;
    }
    else  Insert_S2(x);
}
S2.新插入节点X的父节点为黑色节点,直接插入即可,如图s2:

这里写图片描述

void Insert_S2(node x)
{
    if(x->parent->color==Black)
    {       
return ;
    }
    else Insert_S3(x);
}
S3.新插入节点X的父节点P以及叔父节点U都为红色,如图s3:(仅改变了颜色,其他情况不需要列出)

这里写图片描述

红黑树只要求红色节点的子节点必须为黑色,但是没有要求黑色节点的孩子也必须是红色,因此这种情况只需要改变其父节点和叔父节点的颜色为黑即可,不需要继续向上一层遍历,具体实现如下:

void Insert_S3(node x)
{
    if(uncle(x)!=NULL && uncle(x)->color==Red)
    {
        x->parent->color=Black;
        uncle(x)->color=Black;          
    }
    else Insert_S4_1(x);
}
S4.新插入节点X的父节点为红色节点,叔父节点为黑色节点(NULL),如图s4:
由图可以知道在S4中还分为4中情况,其中2和3可以通过旋转变成1,4的情况,然后就可以统一处理。

这里写图片描述
2,3情况如下:2和3的情形可以通过一次旋转变成情形1和4,由于2,3是对称的,画图只画了情形2
这里写图片描述

void Insert_S4_1(node x)
{
    if(x->parent==grandparent(x)->left && x==x->parent->right)
    //对应情况2
    {
        RotateLeft(x->parent);
        n=n->left;
Insert_S4_2(x);
    }
    else 
    if(x->parent==grandparent(x)->right && x==x->parent->left)
    //对应情况3
    {
        RotateRight(x->parent);
        n=n->right; 
Insert_S4_2(x);
    }
}
1,4情况如下:由于2,3是对称的,画图只画了情形2

这里写图片描述

void Insert_S4_2(node x)
{
    if(x->parent==grandparent(x)->left && x==x->parent->left)
    //对应情况1
    {
        RotateRight(grandparent(x));
        x->parent->color=Black;
        grandparent(x)->color=Red;
    }
    else
    if(x->parent==grandparent(x)->right&&x==x->parent->right)
    //对应情况4
    {
        RotateLeft(grandparent(x));
        x->parent->color=Black;
        grandparent(x)->color=Red;
    }
}
1,4情况的代码还可以简化如下:
void Insert_S4_2(node x)
{
    x->parent->color=Black;
    grandparent(x)->color=Red;
    if(x->parent==grandparent(x)->left && x==x->parent->left)
    //对应情况1
    {
        RotateRight(grandparent(x));
    }
    else
    if(x->parent==grandparent(x)->right&&x==x->parent->right)
    //对应情况4
    {
        RotateLeft(grandparent(x));
    }
}
本篇中还使用到的其他函数如下:
void RotateRight(node x)
{
    temp=new node();
    temp=x;
    x=x->lchild;
    x->rchild=temp;
    temp->lchild=x->lchild->rchild;
}
void RotateLeft(node x)
{
    temp=new node();
    temp=x;
    x=x->rchild;
    x->lchild=temp;
    temp->rchild=x->rchild->lchild;
}
本文是我自己学习了红黑树以后的一些见解,可能会有不对的地方,如果有请联系我,以便可以及时的更新,QQ179560574.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值