数据结构(二)、红黑树(RBT)

上一篇文章我们讲到了平衡二叉树的AVL树,本篇就介绍另一种平衡二叉树:红黑树(Red Black Tree)。

数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)

目录

简介

性质

自平衡

变色

旋转

在线测试


简介

红黑树(Red Black Tree)是一种自平衡的二叉树,在插入和删除操作时可能会打破树的平衡,它会重新自处理以达到平衡状态。红黑树是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(logn)时间内做查找,插入和删除,这里的n是树中元素的数目。

性质

红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树强制的一般性质以外还有下面几个性质:

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

新增的节点都是红色,然后对其他节点'变色'或'旋转'以达到平衡状态;

红黑树从根节点到叶子节点的最长路径不会超过最短路径的2倍;

下图是个红黑树的示例,为了简洁,在后面的内容中我们把Nil叶子节点省略: 

自平衡

上面提到,当对红黑树中增删节点时若打破了红黑树的平衡条件时会将对该树做节点的'变色'和'旋转'操作,以重新达到平衡状态。

变色

下图是一个变色场景,给红黑树新增节点4和节点14,为了简洁,这里省略Nil叶子节点:

  1. 新增14节点后,由于新增节点都是红色,此时14和13节点是连续的红色节点,打破了规则4
  2. 发生变色操作,13节点变为黑色,但此时由于12到14节点和12到20节点之间的黑色节点数量不一致,前者是3后者是2,打破了规则5
  3. 于是20节点也变为黑色,此时该二叉树的右子树根节点到叶子节点的黑色节点数量为3,而左子树的根节点到叶子节点之间的黑色节点数量为2,再次打破了规则5
  4. 于是节点16由黑色变成红色,此时红黑树恢复平衡状态;
  5. 对于新增的节点4,它的加入没有打破红黑树的平衡,所以直接就插入成功;

旋转

下图是一个 变色+旋转 场景,给红黑树新增节点9,为了简洁,这里省略Nil叶子节点:

(1). 变色:

  1. 插入节点9,将6,8父节点和叔节点变为黑色
  2. 祖父节点7变为红色

(2). 左旋转:

  1. 节点7的父节点5左旋作为7的左孩子
  2. 节点7升级为节点5的父节点
  3. 节点6转为节点5的右孩子

(3). 变色:

  1. 节点7变为黑色
  2. 根节点12变为红色

(4). 右旋转:

  1. 节点7的父节点12右旋为7节点的右孩子
  2. 节点7升级为根节点
  3. 节点8转为节点12的左节点

此时红黑树完成变色+旋转的操作,重新恢复平衡状态

在线测试

由于红黑树理解起来比较复杂,这里也提供一个html附件,方便大家理解和使用,包含变色和旋转步骤:

红黑树测试

 

希望本文对你有帮助,请点个赞鼓励一下作者吧~ 谢谢!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
是一种自平衡的二叉搜索,其在实现上相对复杂。下面是一个的Python实现的示例代码: ```python # 节点类 class Node: def __init__(self, key): self.key = key self.parent = None self.left = None self.right = None self.color = 1 # 色为1,色为0 # 类 class RedBlackTree: def __init__(self): self.nil = Node(None) # 哨兵节点 self.nil.color = 0 self.root = self.nil def insert(self, key): node = Node(key) node.parent = None node.left = self.nil node.right = self.nil node.color = 1 y = None x = self.root while x != self.nil: y = x if node.key < x.key: x = x.left else: x = x.right node.parent = y if y == None: self.root = node elif node.key < y.key: y.left = node else: y.right = node if node.parent == None: node.color = 0 return if node.parent.parent == None: return self.fix_insert(node) def fix_insert(self, node): while node.parent.color == 1: if node.parent == node.parent.parent.right: uncle = node.parent.parent.left if uncle.color == 1: uncle.color = 0 node.parent.color = 0 node.parent.parent.color = 1 node = node.parent.parent else: if node == node.parent.left: node = node.parent self.right_rotate(node) node.parent.color = 0 node.parent.parent.color = 1 self.left_rotate(node.parent.parent) else: uncle = node.parent.parent.right if uncle.color == 1: uncle.color = 0 node.parent.color = 0 node.parent.parent.color = 1 node = node.parent.parent else: if node == node.parent.right: node = node.parent self.left_rotate(node) node.parent.color = 0 node.parent.parent.color = 1 self.right_rotate(node.parent.parent) if node == self.root: break self.root.color = 0 def left_rotate(self, node): y = node.right node.right = y.left if y.left != self.nil: y.left.parent = node y.parent = node.parent if node.parent == None: self.root = y elif node == node.parent.left: node.parent.left = y else: node.parent.right = y y.left = node node.parent = y def right_rotate(self, node): y = node.left node.left = y.right if y.right != self.nil: y.right.parent = node y.parent = node.parent if node.parent == None: self.root = y elif node == node.parent.right: node.parent.right = y else: node.parent.left = y y.right = node node.parent = y # 创建对象 rbt = RedBlackTree() # 插入节点 rbt.insert(10) rbt.insert(20) rbt.insert(30) rbt.insert(40) rbt.insert(50) # 相关问题:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王义凯_Rick

遇见即是缘,路过就给个评论吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值