红黑树的应用及原理(干货)

介绍:
红黑树是应用很广泛的一种数据结构。一般用于内存的排序,时间复杂度较低,为O(logn),STL中map和set内部使用的就是红黑树。红黑树是平衡二叉树的一种,每个节点之中红色和黑色两种颜色,根结点都为黑色,红节点的孩子都是黑色,还有就是根结点到叶子结点黑色孩子的高度相同。

红黑树的操作

创建结点

红黑树的结点结构如下:
struct rbtree_node {
int key;
struct rbtree_node* left;
struct rbtree_node* right;
struct rbtree_node* parent;
};
struct rbtree {
struct rbtree_node* root;
};
这个数据结构如果在代码中出现的话,可以百分之百的确定就是红黑树的结构。内部主要有三根指针,指向左孩子,右孩子以及双亲;还有一个数据就是存放具体的数据。创建的话其实就是初始化的过程。

销毁结点

结点的销毁也很简单,将内部的指针都释放,然后再free掉结点占用的内存。

查找结点

查找结点的操作和正常的二叉查找树的方法相同。从根部开始遍历,比当前结点大的话就到他的右子数,如果比当前结点小的话就到他的左子数。直到找到结点为止。

插入结点

接下来就是红黑树的两个重要的操作,插入和删除。插入的话实际上可以分为以下几种情况。
首先我们需要知道插入的结点,都是红的,因为红色插入之后黑高还是保持一致。插入的时候,根据二叉树的性质可以得出插入的结点在叶子结点。
插入结点时,根据祖父结点和叔叔结点的颜色不同共有四种情况:
(1)插入结点为父结点的左结点,叔叔结点为黑色。这个时候我们做的操作是先以父结点为中心右旋,然后改变父结点和祖父结点的颜色,使其满足红黑树的性质
(2)插入的结点为父结点的右结点,叔叔结点为黑色。此时我们先以父结点为中心左旋,改变新父结点和祖父结点的颜色,然后再以新的父结点为中心右旋。
(3)插入结点为父结点的左结点,并且叔叔结点为红色,那么就不用旋转,改变父结点和叔叔结点的颜色为黑色,新结点的颜色和祖父结点一致。然后祖父结点变为新的当前结点,向上判断时候新结点是否会影响红黑树的性质。
三种情况说完之后,后面就是按照父结点在祖父结点的左子树还是右子树分为两种情况。这两种情况是对立的状况,只需要修改左右旋的方向即可。

删除结点

删除结点的操作比较复杂,需要配上图片好好的分析。
删除结点总结性的来说其实只有四种情况。
(1)删除结点的左右子树都非空
(2)删除结点的左子树为空
(3)删除结点的右子树为空
(4)删除结点的左右子树都为空
其中第一种情况的删除和AVL树的删除类似,都是转换为后面的情况处理。因为左右子树都非空的话,肯定是选择左子树的最大值或者是右子树的最小值来替代原结点,而这两种结点都只有一个子树或者没有子树。红黑树的删除实际上删除的并不是当前的结点,因为我们删除结点之后,肯定都是让结点的直接后继代替删除结点,因此我们可以直接将直接后继的值赋给要删除的结点,然后将后继结点删除即可。在删除结点之后再对平衡性做出调整,使其满足性质。
因此实际上在操作的时候删除的是替代的结点,考虑的是替代结点的情况。并且替代结点在删除之前还需要参与树的平衡,平衡后再替换到删除结点的额位置才算是真正的结束。
删除的情况:
(1)替换结点是红色,这个处理是比较简单的,因为删除红色结点也不会破坏红黑树的性质,因此只需要将替代结点设置为删除结点的颜色。
(2)替换结点为黑色
此时我们就不得不进行平衡的操作了,判断父结点P,兄弟结点S,以及兄弟结点的孩子结点的颜色分为以下几种情况。
1. 替换结点为P的左子树
1.1 替换结点的兄弟结点为红色
此时将S涂为黑色,P涂为红色,然后以P为中心左旋
1.2 替换结点的兄弟结点为黑色
此时由于不能判断P的颜色,因此需要考虑一下几种情况
1.2.1 替换结点的兄弟结点的右子结点为红色,左子结点颜色任意
此时我们为了黑色结点的平衡,需要做一下操作,先将S设为P的颜色,P设为黑色,将S的右子结点设为黑色,以P为中心左旋。左旋之后删除替换结点就平衡了
1.2.2 替换结点的兄弟结点的左结点为红色,右结点为黑色。
此时我们将左子结点设为黑色,S设为红色,以S为中心右旋,这样就形成了1.2.1的情况,再按照上面的情况处理
1.2.3 兄弟结点的左右结点都是黑色
此时兄弟结点已经无法借到红色结点了,只能向上搜索。因此需要将兄弟结点设置为红色(因此需要保证替换结点被删除之后的平衡性),然后以父结点为新的替换结点进行新的删除处理。
2. 替换结点为父结点的右子树,这种情况和上面的情况是对称的,只需要将左右旋的方向变换一下即可。

以上就是红黑树的操作以及详细的情况介绍,图后面会补。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值