红黑树和平衡二叉树的区别

一、基本概念

平衡二叉树:

平衡二叉树是一种二叉搜索树,它的每个结点的左子树和右子树的高度之差不超过1。有AVL树、红黑树等类型的平衡二叉树。平衡二叉树的插入和删除操作会引起局部的旋转操作,以保证树的平衡。

红黑树:

红黑树也是一种自平衡二叉搜索树,除了满足二叉搜索树的性质之外,红黑树还满足以下5个性质,这些性质是用来保证红黑树在动态添加/删除节点时能自我平衡:

1. 每个节点非红即黑。

2. 根节点必须是黑色的。

3. 每个叶子节点(NIL节点,即空节点)都是黑色的。

4. 如果一个节点是红色的,则它的两个子节点都是黑色的。

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

二、插入删除操作

平衡二叉树的插入和删除操作会引起局部的旋转操作,以保证树的平衡。具体来说:

1. 插入操作:如果插入一个节点后打破了树的平衡,那么进行比较少的旋转操作就可以调整回平衡。

2. 删除操作:如果删除一个节点后打破了树的平衡,那么进行比较少的旋转操作就可以调整回平衡。

平衡二叉树对于插入和删除的操作都需要保证在平衡二叉树中遵守平衡约束,因此相对比较复杂。

而红黑树在插入和删除节点时的平衡策略相对简单一些,具体如下:

1. 插入操作:按照二叉搜索树的规则进行插入,并将插入的新节点标记为红色。然后对红黑树进行必要的调整,以保持红黑树的5个性质。调整过程中使用了旋转和颜色变化的策略,来保证红黑树的5个特性。

2. 删除操作:同样按照二叉搜索树的规则进行删除,如果被删除的节点是红色的,就直接删除;如果是黑色的,则reb-black性质就被打破了,这时需要通过旋转、移动、染色等方式重新调整树的结构,以保证红黑树的5个特性。

三、代码实现

以下是红黑树和平衡二叉树的Python代码实现,其中涉及了节点的定义、旋转和颜色调整等操作:

# 平衡二叉树节点定义
class AVLNode:
    def __init__(self, val):
        self.val = val
        self.height = 0
        self.left = None
        self.right = None

# 红黑树节点定义
class RBNode:
    def __init__(self, val, color=0):
        self.val = val
        self.color = color  # 0表示黑色,1表示红色
        self.left = None
        self.right = None
        self.parent = None

# AVL树中的旋转操作
def rotate_right(node: AVLNode) -> AVLNode:
    pivot = node.left
    node.left = pivot.right
    pivot.right = node
    node.height = max(get_height(node.left), get_height(node.right)) + 1
    pivot.height = max(get_height(pivot.left), get_height(pivot.right)) + 1
    return pivot

def rotate_left(node: AVLNode) -> AVLNode:
    pivot = node.right
    node.right = pivot.left
    pivot.left = node
    node.height = max(get_height(node.left), get_height(node.right)) + 1
    pivot.height = max(get_height(pivot.left), get_height(pivot.right)) + 1
    return pivot

# 红黑树中的旋转和颜色调整操作
def left_rotate(rb_node: RBNode):
    r_node = rb_node.right
    rb_node.right = r_node.left
    if r_node.left:
        r_node.left.parent = rb_node
    r_node.parent = rb_node.parent
    if rb_node.parent is None:
        root_node = r_node
    elif rb_node == rb_node.parent.left:
        rb_node.parent.left = r_node
    else:
        rb_node.parent.right = r_node
    r_node.left = rb_node
    rb_node.parent = r_node
    return root_node

def right_rotate(rb_node: RBNode):
    l_node = rb_node.left
    rb_node.left = l_node.right
    if l_node.right:
        l_node.right.parent = rb_node
    l_node.parent = rb_node.parent
    if rb_node.parent == None:
        root_node = l_node
    elif rb_node == rb_node.parent.right:
        rb_node.parent.right = l_node
    else:
        rb_node.parent.left = l_node
    l_node.right = rb_node
    rb_node.parent = l_node
    return root_node

def insert_fixup(rb_node: RBNode, root_node: RBNode):
    # 插入节点时,如果父节点为红色,则需要进行平衡调整
    while rb_node.parent and rb_node.parent.color == 1:
        if rb_node.parent == rb_node.parent.parent.left:
            # 父节点为祖父节点的左孩子
            uncle = rb_node.parent.parent.right
            if uncle and uncle.color == 1:
                # Case 1:叔叔节点为红色,则父节点和叔叔节点都改为黑色,祖父节点改为红色
                rb_node.parent.color = 0
                uncle.color = 0
                rb_node.parent.parent.color = 1
                rb_node = rb_node.parent.parent
            else:
                if rb_node == rb_node.parent.right:
                    # Case 2:叔叔节点为黑色,且当前节点是父节点的右孩子,则需要左旋父节点
                    rb_node = rb_node.parent
                    root_node = left_rotate(rb_node)
                # Case 3:叔叔节点为黑色,且当前节点是父节点的左孩子,则父节点变成黑色,祖父节点变成红色,然后右旋祖父节点
                rb_node.parent.color = 0
                rb_node.parent.parent.color = 1
                root_node = right_rotate(rb_node.parent.parent)
        else:
            # 父节点为祖父节点的右孩子
            uncle = rb_node.parent.parent.left
            if uncle and uncle.color == 1:
                # Case 1
                rb_node.parent.color = 0
                uncle.color = 0
                rb_node.parent.parent.color = 1
                rb_node = rb_node.parent.parent
            else:
                if rb_node == rb_node.parent.left:
                    # Case 2
                    rb_node = rb_node.parent
                    root_node = right_rotate(rb_node)
                # Case 3
                rb_node.parent.color = 0
                rb_node.parent.parent.color = 1
                root_node = left_rotate(rb_node.parent.parent)
    root_node.color = 0
    return root_node

def insert_rbt(root_node: RBNode, val):
    rb_node = RBNode(val, 1)
    node = root_node
    while node:
        if val < node.val:
            if node.left:
                node = node.left
            else:
                node.left = rb_node
                rb_node.parent = node
                break
        else:
            if node.right:
                node = node.right
            else:
                node.right = rb_node
                rb_node.parent = node
                break
    root_node = insert_fixup(rb_node, root_node)
    return root_node

四、总结

红黑树和平衡二叉树都是一种在动态添加/删除节点时能自我平衡的二叉搜索树,但是它们之间还是有不少差异的。其中,平衡二叉树对于插入和删除的操作都需要保证在平衡二叉树中遵守平衡约束,因此相对比较复杂;而红黑树在插入和删除节点时的平衡策略相对简单一些,易于实现以及调试。因此,对于动态操作较为频繁、对性能要求较高的场景,红黑树可能是更好的选择。

原创文章,作者:YOLZW,如若转载,请注明出处:https://www.506064.com/n/332813.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
YOLZWYOLZW
上一篇 2025-01-27 13:34
下一篇 2025-01-27 13:34

相关推荐

  • Python中new和init的区别

    new和init都是Python中常用的魔法方法,它们分别负责对象的创建和初始化,本文将从多个角度详细阐述它们的区别。 一、创建对象 new方法是用来创建一个对象的,它是一个类级别…

    编程 2025-04-29
  • Sublime Test与Python的区别

    Sublime Text是一款流行的文本编辑器,而Python是一种广泛使用的编程语言。虽然Sublime Text可以用于编写Python代码,但它们之间有很多不同之处。接下来从…

    编程 2025-04-29
  • Shell脚本与Python脚本的区别

    本文将从多个方面对Shell脚本与Python脚本的区别做详细的阐述。 一、语法差异 Shell脚本和Python脚本的语法存在明显差异。 Shell脚本是一种基于字符命令行的语言…

    编程 2025-04-29
  • Python中while语句和for语句的区别

    while语句和for语句是Python中两种常见的循环语句,它们都可以用于重复执行一段代码。然而,它们的语法和适用场景有所不同。本文将从多个方面详细阐述Python中while语…

    编程 2025-04-29
  • Web程序和桌面程序的区别

    Web程序和桌面程序都是进行软件开发的方式,但是它们之间存在很大的区别。本文将从多角度进行阐述。 一、运行方式 Web程序运行于互联网上,用户可以通过使用浏览器来访问它。而桌面程序…

    编程 2025-04-29
  • TensorFlow和Python的区别

    TensorFlow和Python是现如今最受欢迎的机器学习平台和编程语言。虽然两者都处于机器学习领域的主流阵营,但它们有很多区别。本文将从多个方面对TensorFlow和Pyth…

    编程 2025-04-28
  • 麦语言与Python的区别

    麦语言和Python都是非常受欢迎的编程语言。它们各自有自己的优缺点和适合的应用场景。本文将从语言特性、语法、生态系统等多个方面,对麦语言和Python进行详细比较和阐述。 一、语…

    编程 2025-04-28
  • MySQL bigint与long的区别

    本文将从数据类型定义、存储空间、数据范围、计算效率、应用场景五个方面详细阐述MySQL bigint与long的区别。 一、数据类型定义 bigint在MySQL中是一种有符号的整…

    编程 2025-04-28
  • Python与C语言的区别和联系

    Python与C语言是两种常用的编程语言,虽然两者都可以用于编写软件程序,但是它们之间有很多不同之处。本文将从多个方面对Python与C语言的区别和联系进行详细的阐述。 一、语法特…

    编程 2025-04-28
  • Python中深拷贝和浅拷贝的区别

    本文将从以下几个方面对Python中深拷贝和浅拷贝的区别做详细的阐述,包括:拷贝的含义、变量和对象的区别、浅拷贝的示例、深拷贝的示例、可变对象和不可变对象的区别、嵌套的数据结构以及…

    编程 2025-04-28

发表回复

登录后才能评论