算法导论学习---红黑树详解之插入(C语言实现)

前面我们学习二叉搜索树的时候发现在一些情况下其高度不是很均匀,甚至有时候会退化成一条长链,所以我们引用一些”平衡”的二叉搜索树。红黑树就是一种”平衡”的二叉搜索树,它通过在每个结点附加颜色位和路径上的一些约束条件可以保证在最坏的情况下基本动态集合操作的时间复杂度为O(nlgn).下面会总结红黑树的性质,然后分析红黑树的插入操作,并给出一份完整代码。

先给出红黑树的结点定义:

#define RED 1
#define BLACK 0

///红黑树结点定义,与普通的二叉树搜索树相比多了一个颜色域
typedef struct node
{
      int key,color; ///定义1为红,0为黑
      node *p,*left,*right;
      node(){
         color=BLACK; ///默认结点颜色为黑
      }
}*RBTree;

一.从红黑树的性质讲起
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是RED或BLACK。通过堆任何一条从根到叶子结点的简单路径上各个结点颜色进行约束,红黑树确保没有一条路径会比其它路径要长出两倍,因而是近似于平衡的。下面给出红黑树的五条”红黑性质”,这几条性质是后面插入和删除的基础。
1).每个结点或是红色或是黑色。
2).根结点是黑色的。
3).每个叶结点是黑色的
4).如果一个结点是红色的,那么它的两个子节点都是黑色的。
5).对于每个结点,从该结点出发到其所有后代叶结点的简单路径上均包含相同数目的黑结点。
我们设从某个结点x出发(不含该结点)到达一个叶结点的一条简单路径上的黑结点个数为该结点的黑高,记为bh(x)。显然根据性质5,每个结点的黑高都是唯一的。下面我们来证明:一棵含有n个内部结点的红黑树的高度至多为2lg(n+1).
先证明以任一结点x为根的子树中至少包含2^bh(x)-1个内部结点。我们采用数学归纳法,对x的黑高进行归纳。如果x的黑高高度为0即x为叶子结点,则显然正确。x的黑高为bh(x),则其两棵子树的黑高为bh(x)或bh(x)-1(取决与它们本身的颜色),则可归纳出对应的内部结点至少为2^(bh(x)-1)-1,即x包含的内部结点至少为2^(bh(x)-1)-1+2^(bh(x)-1)-1+1=2^bh(x)-1,因此得证。然后现在我们设含n个结点的树高为h,然后根据性质4,可以知道从根到叶结点(不包括根结点)的任一条简单路径上都至少有一半的结点为黑色。因此树的黑高至少为h/2;然后有上面的结论得n>=2^(h/2)-1.解得h<=2lg(n+1)。于是我们就证明了动态集合操作Search,Minimum,Successor等都可以在O(lgn)时间复杂度内完成了。

下面给一张红黑树的图片。
这里写图片描述

二.旋转操作
后面的插入和删除过程中都会有破坏红黑树性质的情况发送,为了维护这些性质,必须要改变树中某些结点的颜色和指针结构。指针结构的修改是通过旋转来完成的,旋转被分为左旋和右旋;在插入和删除操作中这两个操作会多次出现,我们先来分析一下这两个操作。
这两个操作对应的图像如下:
这里写图片描述

从图像上可以看出,左旋和右旋操作并不是很复杂。下面我们以左旋为例进行解析:如图我们假设结点x的右儿子为y。左旋的前提是:结点必须要有右儿子。左旋的结果是:y代替x,x成为y的左儿子,x成为y的左儿子,y的左儿子成为x的右儿子。下面是具体的代码实现:

///左旋:对具有任意具有右孩子的结点可以进行
///传入要选择的结点指针的引用
///旋转以后x的右孩子y取代了x,而x成为y的左孩子,y的左孩子成为x的右孩子
///下面的代码就是完成这三个部分
void LeftRotate(RBTree x)
{
      RBTree y=x->right; ///y表示x的右孩子
      x->right=y->left; ///第一步:将x的右孩子设为y的左孩子
      if(y->left!=Nul)
            y->left->p=x;

     y->p=x->p;  ///更改y的父结点为x的父结点
  
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值