紅黑樹和平衡二叉樹的區別

一、基本概念

平衡二叉樹:

平衡二叉樹是一種二叉搜索樹,它的每個結點的左子樹和右子樹的高度之差不超過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/zh-hk/n/332813.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
YOLZW的頭像YOLZW
上一篇 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
  • MySQL bigint與long的區別

    本文將從數據類型定義、存儲空間、數據範圍、計算效率、應用場景五個方面詳細闡述MySQL bigint與long的區別。 一、數據類型定義 bigint在MySQL中是一種有符號的整…

    編程 2025-04-28
  • 麥語言與Python的區別

    麥語言和Python都是非常受歡迎的編程語言。它們各自有自己的優缺點和適合的應用場景。本文將從語言特性、語法、生態系統等多個方面,對麥語言和Python進行詳細比較和闡述。 一、語…

    編程 2025-04-28
  • Python與C語言的區別和聯繫

    Python與C語言是兩種常用的編程語言,雖然兩者都可以用於編寫軟件程序,但是它們之間有很多不同之處。本文將從多個方面對Python與C語言的區別和聯繫進行詳細的闡述。 一、語法特…

    編程 2025-04-28
  • 二叉樹非遞歸先序遍歷c語言

    本文將為您詳細介紹二叉樹的非遞歸先序遍歷算法,同時提供完整的C語言代碼示例。通過本文,您將了解到二叉樹的先序遍歷算法,以及非遞歸實現的方式。 一、二叉樹的先序遍歷算法介紹 在介紹二…

    編程 2025-04-28

發表回復

登錄後才能評論