红黑树的基本概念

        红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由鲁道夫·贝尔发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。

一个具体的红黑树的图例:

        

        红黑树和AVL树一样都对插入时间、删除时间和查找时间提供了最好可能的最坏情况担保。这不只是使它们在时间敏感的应用如实时应用(real time application)中有价值,而且使它们有在提供最坏情况担保的其他数据结构中作为建造板块的价值;例如,在计算几何中使用的很多数据结构都可以基于红黑树。

        红黑树在函数式编程中也特别有用,在这里它们是最常用的持久数据结构之一,它们用来构造关联数组和集合,在突变之后它们能保持为以前的版本。除了O(log n)的时间之外,红黑树的持久版本对每次插入或删除需要O(log n)的空间。

        红黑树是 2-3-4树的一种等同。换句话说,对于每个 2-3-4 树,都存在至少一个数据元素是同样次序的红黑树。在 2-3-4 树上的插入和删除操作也等同于在红黑树中颜色翻转和旋转。这使得 2-3-4 树成为理解红黑树背后的逻辑的重要工具,这也是很多介绍算法的教科书在红黑树之前介绍 2-3-4 树的原因,尽管 2-3-4 树在实践中不经常使用。


性质:

性质1. 节点是红色或黑色。

性质2. 根是黑色。

性质3. 所有叶子都是黑色(叶子是NIL节点)。

性质4. 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)

性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。

        那么来看看这5个性质吧:性质1,结点的颜色域代表其父结点指向该节点的指针的颜色,如果为黑色,那么这两个结点在对应的2-3-4树中应该是父子结点的关系,如果为红色,那么这两个结点在对应的2-3-4树中应该在同一个结点中。这样每个结点有两个颜色就很容易理解了。性质2,根是黑色,因为其没有父结点,令为黑色可以理解,令为红色的话就有些矛盾了。性质3,所有叶子都是黑色,对应2-3-4树中的所有叶结点在同一层上,所有叶子结点的儿子结点都是空的。性质4,每个红色结点都必须有两个黑色的子结点,红色结点对应其在2-3-4树中位于某个3结点或者4结点,那么红色结点在红黑书中有两个黑色的子结点就很容易理解了,如果有两个连续的红色结点,那么对应在2-3-4树中这俩结点和其最近的父结点应该在一个4结点中,可是这不符合结点的拆分方式,因为结点都是由4结点的中值元素作为新的树根的。性质5,一个黑色结点可以对应到2-3-4树中的一层,而2-3-4树中所有的叶结点位于同一层,那么即路径上单纯算黑结点的深度应该是一样的。

        

为了后面的分析,我们还得知道以下知识点。

    (1)黑高度:从某个结点x出发(不包括该结点)到达一个叶结点的任意一条路径上,黑色结点的个数称为该结点x的黑高度。

    (2)一颗有n个内结点的红黑树的高度至多为2lg(n+1)。   (内结点视为红黑树中带关键字的结点)

    (3)包含n个内部节点的红黑树的高度是 O(log(n))。

证明(来自维基百科):

定义:

  • h(v) = 以节点v为根的子树的高度。
  • bh(v) = 从v到子树中任何叶子的黑色节点的数目(如果v是黑色则不计数它)(也叫做黑色高度)。

引理: 以节点v为根的子树有至少2bh(v) − 1个内部节点。

引理的证明(通过归纳高度):

基础: h(v) = 0

如果v的高度是零则它必定是 nil,因此 bh(v) = 0。所以:

                       2bh(v) − 1 = 20 − 1 = 1 − 1 = 0

归纳假设: h(v) = k 的v有 2bh(v) − 1 − 1 个内部节点暗示了 h(v') = k+1 的v'2bh(v') − 1 个内部节点。

因为 v' 有 h(v') > 0 所以它是个内部节点。同样的它有黑色高度要么是 bh(v') 要么是 bh(v')-1 (依据v'是红色还是黑色)的两个儿子。通过归纳假设每个儿子都有至少2bh(v') − 1 − 1 个内部接点,所以v' 有:

                      2bh(v') − 1 − 1 + 2bh(v') − 1 − 1 + 1 = 2bh(v') − 1

个内部节点。

使用这个引理我们现在可以展示出树的高度是对数性的。因为在从根到叶子的任何路径上至少有一半的节点是黑色(根据红黑树属性4),根的黑色高度至少是h(root)/2。通过引理我们得到:

n \geq 2^{​{h(root) \over 2}} - 1 \leftrightarrow \; \log{(n+1)} \geq {h(root) \over 2} \leftrightarrow \; h(root) \leq 2\log{(n+1)}

因此根的高度是O(log(n))。



REF:

1,http://zh.wikipedia.org/wiki/红黑树

2,http://blog.youkuaiyun.com/wdzxl198/article/details/6882416

<think>嗯,用户想了解红黑树的基本操作以及如何用Python实现插入、删除和搜索。首先,我需要回忆一下红黑树基本概念和规则。红黑树是一种自平衡的二叉查找树,每个节点有颜色属性,红色或黑色,需要满足几个性质:根节点是黑色,叶子节点(NIL)是黑色,红色节点的子节点必须是黑色,从任一节点到其每个叶子节点的所有路径都包含相同数量的黑色节点。这些性质确保了红黑树在插入和删除时能保持相对平衡,从而保证操作的时间复杂度为O(log n)。 接下来,用户需要Python的实现。红黑树的主要操作包括插入、删除和搜索。搜索和普通二叉查找树类似,但插入和删除后需要调整颜色和旋转来维持红黑树的性质。我得先考虑节点的结构,每个节点应该包含颜色、值、左右子节点和父节点。颜色可以用布尔值表示,比如True代表红色,False代表黑色。 插入操作分为两步:首先按照二叉查找树的方式插入节点,并着色为红色,然后调整颜色和结构。插入后可能破坏红黑树的性质,比如出现连续的红色节点,这时候需要通过旋转和变色来修复。插入的情况可能有多种,比如父节点是红色,叔节点是红色,这时候需要变色并将问题上移;如果叔节点是黑色,可能需要旋转,比如左旋或右旋,然后变色。 删除操作更复杂,因为删除节点后可能会破坏黑高。删除时需要考虑被删除节点的子节点情况,以及替换节点的颜色。如果被删除节点是红色,可能不需要调整;如果是黑色,则需要通过旋转和变色来修复。删除后的调整需要考虑兄弟节点的颜色及其子节点的颜色,进行相应的旋转和变色操作。 在Python中实现这些操作时,需要注意指针的调整,特别是父节点、左子节点、右子节点的引用。例如,插入时可能需要更新父节点的子节点指向,旋转操作需要调整各个节点的左右和父指针。此外,处理NIL节点时需要特别小心,可能需要将叶子节点用NIL哨兵节点表示,以简化逻辑。 搜索操作相对简单,和普通的二叉搜索树一样,递归或迭代地比较值的大小,决定向左子树还是右子树查找。 现在,需要将这些逻辑转化为Python代码。首先定义节点类,包含颜色、值、左右子节点和父节点。然后定义红黑树类,包含根节点和NIL节点。插入方法需要找到合适的位置插入新节点,然后进行修复。删除方法需要找到节点,处理子节点情况,然后进行修复。旋转操作需要处理左旋和右旋的逻辑,确保指针正确调整。 在实现过程中,可能会遇到指针处理错误,导致树的结构不正确。需要仔细检查旋转和父节点更新的步骤。此外,处理颜色调整时,要确保不违反红黑树的性质,例如修复插入后的连续红色节点,或者删除后的黑高不一致。 最后,测试代码的正确性,可以通过插入和删除一系列节点,检查树是否保持平衡,颜色是否符合规则。也可以参考已有的红黑树实现,对比逻辑是否正确。 总结来说,实现红黑树的关键在于正确维护颜色和结构,处理插入和删除后的调整步骤,确保所有操作后仍满足红黑树的性质。Python实现需要注意指针操作和递归或迭代的逻辑,同时使用NIL节点简化边界条件处理。</think>### 红黑树基本操作及Python实现 红黑树是一种自平衡二叉搜索树,通过颜色标记和旋转操作维持平衡,保证插入、删除、搜索的时间复杂度为 $O(\log n)$[^3]。以下是核心操作及实现逻辑: --- #### 一、红黑树基本性质 1. 节点颜色为红或黑,根节点为黑 2. 叶子节点(NIL)为黑 3. 红节点的子节点必须为黑 4. 从任意节点到其所有叶子节点的路径包含相同数量黑节点(黑高一致) --- #### 二、Python实现框架 ```python class Node: def __init__(self, value, color=True, left=None, right=None, parent=None): self.value = value self.color = color # True=红,False=黑 self.left = left self.right = right self.parent = parent class RedBlackTree: def __init__(self): self.NIL = Node(None, False) # 哨兵节点 self.root = self.NIL ``` --- #### 三、关键操作实现 ##### 1. 插入操作 **步骤:** - 按二叉搜索树规则插入新节点,初始颜色为红色 - 修复颜色冲突(连续红节点): - **情况1**:叔节点为红 → 父、叔、祖父变色,递归处理祖父节点 - **情况2**:叔节点为黑,节点与父方向不一致 → 父节点旋转调整方向 - **情况3**:叔节点为黑且方向一致 → 祖父节点旋转并变色 **代码片段:** ```python def insert_fixup(self, node): while node.parent.color: if node.parent == node.parent.parent.left: uncle = node.parent.parent.right if uncle.color: # 情况1 node.parent.color = False uncle.color = False node.parent.parent.color = True node = node.parent.parent else: if node == node.parent.right: # 情况2 node = node.parent self.left_rotate(node) # 情况3 node.parent.color = False node.parent.parent.color = True self.right_rotate(node.parent.parent) else: # 对称处理右子树 # ...类似左子树逻辑 self.root.color = False ``` ##### 2. 删除操作 **步骤:** - 按二叉搜索树规则删除节点 - 若删除节点为黑色,需修复黑高: - **情况1**:兄弟节点为红 → 旋转父节点并重新染色 - **情况2**:兄弟节点为黑且其子节点全黑 → 兄弟变红,递归处理父节点 - **情况3**:兄弟节点为黑且存在红色子节点 → 通过旋转调整结构[^2] **代码片段:** ```python def delete_fixup(self, node): while node != self.root and not node.color: if node == node.parent.left: sibling = node.parent.right if sibling.color: # 情况1 sibling.color = False node.parent.color = True self.left_rotate(node.parent) sibling = node.parent.right # 处理情况2和3 # ...具体旋转和变色逻辑 else: # 对称处理右子树 # ...类似左子树逻辑 node.color = False ``` ##### 3. 搜索操作 与普通二叉搜索树一致: ```python def search(self, value): current = self.root while current != self.NIL: if value == current.value: return True elif value < current.value: current = current.left else: current = current.right return False ``` --- #### 四、旋转操作示例(左旋) ```python def left_rotate(self, x): y = x.right x.right = y.left if y.left != self.NIL: y.left.parent = x y.parent = x.parent if x.parent == self.NIL: self.root = y elif x == x.parent.left: x.parent.left = y else: x.parent.right = y y.left = x x.parent = y ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值