红黑树(Red-Black Tree)

        红黑树(Red-Black Tree)是一种自平衡的二叉查找树(Binary Search Tree, BST),它通过在每个节点上附加一个存储位表示颜色(红色或黑色)来确保树的平衡。红黑树能够在 O(log n) 时间内执行插入、删除和查找操作,这里的 n 是树中节点的数量。

性质

  • 每个节点要么是红色要么是黑色
  • 根节点是黑色
  • 每个叶子节点(NIL 节点)是黑色
  • 如果一个节点是红色的,则它的两个子节点都是黑色的
  • 从任一节点到其每个叶子的所有简单路径上包含相同数目的黑色节点

插入操作

  1. 插入节点:

    • 新插入的节点默认为红色。
    • 将新节点插入到适当的位置,以保持二叉查找树的性质。
  2. 修复红黑树:

    • 插入后,可能违反红黑树的性质,需要通过旋转和重新着色来恢复红黑树的性质。

    • 旋转:

      • 左旋:以某个节点为轴心,将其右子树变为左子树。
      • 右旋:以某个节点为轴心,将其左子树变为右子树。
    • 重新着色:

      • 改变节点的颜色,以恢复红黑树的性质。
  3. 插入修复:

    • Case 1: 如果插入节点是根节点,则将其颜色改为黑色。
    • Case 2: 如果插入节点的父节点是黑色,则不需要进行任何操作。
    • Case 3: 如果插入节点的父节点是红色:
      • Case 3.1: 如果叔叔节点(父节点的兄弟节点)是红色,则将父节点和叔叔节点都改为黑色,祖父节点改为红色,然后以祖父节点为起点继续向上修复。
      • Case 3.2: 如果叔叔节点是黑色或不存在:
        • Case 3.2.1: 如果插入节点是父节点的右子节点,则对父节点进行左旋,然后交换父节点和插入节点的角色,进入 Case 3.2.2。
        • Case 3.2.2: 如果插入节点是父节点的左子节点,则对祖父节点进行右旋,然后将父节点改为黑色,祖父节点改为红色。

删除操作

  1. 删除节点:

    • 删除指定的节点,并保持二叉查找树的性质。
  2. 修复红黑树:

    • 删除后,可能违反红黑树的性质,需要通过旋转和重新着色来恢复红黑树的性质。
  3. 删除修复:

    • Case 1: 如果删除的是红色节点,则不需要进行任何操作。
    • Case 2: 如果删除的是黑色节点:
      • Case 2.1: 如果删除节点的兄弟节点是红色,则对父节点进行旋转,使兄弟节点变为黑色,父节点变为红色。
      • Case 2.2: 如果删除节点的兄弟节点是黑色,且兄弟节点的两个子节点都是黑色:
        • 将兄弟节点改为红色。
        • 如果父节点是黑色,则继续向上修复。
        • 如果父节点是红色,则结束修复。
      • Case 2.3: 如果删除节点的兄弟节点是黑色,且兄弟节点的左子节点是红色,右子节点是黑色:
        • 对兄弟节点进行右旋。
        • 交换兄弟节点和兄弟节点的左子节点的颜色。
      • Case 2.4: 如果删除节点的兄弟节点是黑色,且兄弟节点的右子节点是红色:
        • 对父节点进行旋转。
        • 交换兄弟节点和父节点的颜色。
        • 将兄弟节点的右子节点改为黑色。

查找操作

  • 从根节点开始,根据比较结果决定向左子树还是向右子树递归查找。
  • 如果找到了匹配的节点,则返回该节点。
  • 如果没有找到匹配的节点,则返回 None 或者特定的标志。

代码示例

class Node:
    def __init__(self, data, color="RED"):
        self.data = data
        self.color = color
        self.parent = None
        self.left = None
        self.right = None

class RedBlackTree:
    def __init__(self):
        self.NIL = Node(None, "BLACK")  # Sentinel node for leaves
        self.root = self.NIL

    def insert(self, data):
        new_node = Node(data)
        new_node.left = self.NIL
        new_node.right = self.NIL
        parent = None
        current = self.root

        while current != self.NIL:
            parent = current
            if new_node.data < current.data:
                current = current.left
            else:
                current = current.right

        new_node.parent = parent
        if parent is None:
            self.root = new_node
        elif new_node.data < parent.data:
            parent.left = new_node
        else:
            parent.right = new_node

        new_node.color = "RED"
        self.fix_insert(new_node)

    def fix_insert(self, node):
        while node != self.root and node.parent.color == "RED":
            if node.parent == node.parent.parent.left:
                uncle = node.parent.parent.right
                if uncle.color == "RED":
                    node.parent.color = "BLACK"
                    uncle.color = "BLACK"
                    node.parent.parent.color = "RED"
                    node = node.parent.parent
                else:
                    if node == node.parent.right:
                        node = node.parent
                        self.left_rotate(node)
                    node.parent.color = "BLACK"
                    node.parent.parent.color = "RED"
                    self.right_rotate(node.parent.parent)
            else:
                uncle = node.parent.parent.left
                if uncle.color == "RED":
                    node.parent.color = "BLACK"
                    uncle.color = "BLACK"
                    node.parent.parent.color = "RED"
                    node = node.parent.parent
                else:
                    if node == node.parent.left:
                        node = node.parent
                        self.right_rotate(node)
                    node.parent.color = "BLACK"
                    node.parent.parent.color = "RED"
                    self.left_rotate(node.parent.parent)
        self.root.color = "BLACK"

    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 is None:
            self.root = y
        elif x == x.parent.left:
            x.parent.left = y
        else:
            x.parent.right = y
        y.left = x
        x.parent = y

    def right_rotate(self, y):
        x = y.left
        y.left = x.right
        if x.right != self.NIL:
            x.right.parent = y
        x.parent = y.parent
        if y.parent is None:
            self.root = x
        elif y == y.parent.right:
            y.parent.right = x
        else:
            y.parent.left = x
        x.right = y
        y.parent = x

    def inorder_walk(self, node):
        if node != self.NIL:
            self.inorder_walk(node.left)
            print(node.data, end=' ')
            self.inorder_walk(node.right)

# 使用红黑树
rbt = RedBlackTree()
rbt.insert(10)
rbt.insert(20)
rbt.insert(30)
rbt.insert(15)
rbt.insert(25)

rbt.inorder_walk(rbt.root)  # 应该按照排序顺序打印出数据

demo代码中只实现了insert,有兴趣的朋友可以自行实现delete和search。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值