欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python代碼實(shí)現(xiàn)AVL樹和紅黑樹

 更新時(shí)間:2023年12月22日 08:41:45   作者:BigQuant量化  
專注于Python數(shù)據(jù)結(jié)構(gòu),想要深入了解AVL樹和紅黑樹的讀者們,你們的機(jī)會(huì)來了!在這篇指南中,我們將帶你探索這兩種神奇樹結(jié)構(gòu)的奧秘,緊張刺激的實(shí)戰(zhàn)代碼演示,讓你一窺這兩種樹的獨(dú)特魅力,準(zhǔn)備好了嗎?讓我們一起踏上這場(chǎng)Python樹結(jié)構(gòu)之旅!

AVL樹

AVL樹是一種自平衡二叉搜索樹。在這種樹中,任何節(jié)點(diǎn)的兩個(gè)子樹的高度差被嚴(yán)格控制在1以內(nèi)。這確保了樹的平衡,從而保證了搜索、插入和刪除操作的高效性。AVL樹是由Georgy Adelson-Velsky和Evgenii Landis在1962年發(fā)明的,因此得名(Adelson-Velsky和Landis樹)。  

平衡因子:每個(gè)節(jié)點(diǎn)的平衡因子是其左子樹的高度減去其右子樹的高度。平衡因子必須保持在-1、0或1之間。

旋轉(zhuǎn)操作:為了維持平衡,在進(jìn)行插入或刪除操作后,可能會(huì)執(zhí)行單旋轉(zhuǎn)或雙旋轉(zhuǎn)。單旋轉(zhuǎn)包括右旋(針對(duì)左重失衡)和左旋(針對(duì)右重失衡)。雙旋轉(zhuǎn)是一種更復(fù)雜的調(diào)整,包括左-右旋轉(zhuǎn)和右-左旋轉(zhuǎn)。

時(shí)間復(fù)雜度:在AVL樹中,查找、插入和刪除操作的時(shí)間復(fù)雜度均為O(log n),其中n是樹中的節(jié)點(diǎn)數(shù)。 

AVL樹節(jié)點(diǎn)定義

class AVLNode:
    def __init__(self, key):
        self.key = key
        self.height = 1
        self.left = None
        self.right = None

這里定義了一個(gè)AVL樹的節(jié)點(diǎn)。每個(gè)節(jié)點(diǎn)有一個(gè)鍵值key,一個(gè)高度屬性height,以及指向左右子節(jié)點(diǎn)的指針leftright。 

AVL樹的高度和平衡因子

AVL樹的關(guān)鍵是保持每個(gè)節(jié)點(diǎn)的平衡。平衡因子被定義為節(jié)點(diǎn)的左子樹高度減去其右子樹高度。這個(gè)因子應(yīng)該是-1、0或1。如果在任何時(shí)候,一個(gè)節(jié)點(diǎn)的平衡因子不在這個(gè)范圍內(nèi),我們需要通過旋轉(zhuǎn)來重新平衡樹。

def get_height(node):
    if not node:
        return 0
    return node.height

def get_balance(node):
    if not node:
        return 0
    return get_height(node.left) - get_height(node.right)

這兩個(gè)函數(shù)幫助我們計(jì)算任何節(jié)點(diǎn)的高度和平衡因子。

AVL樹旋轉(zhuǎn)操作

為了維持平衡,我們可能需要進(jìn)行樹的旋轉(zhuǎn)操作。主要有四種類型的旋轉(zhuǎn):右旋轉(zhuǎn)、左旋轉(zhuǎn)、左-右旋轉(zhuǎn)和右-左旋轉(zhuǎn)。

  • 右旋轉(zhuǎn):

當(dāng)一個(gè)節(jié)點(diǎn)的左子樹比右子樹高時(shí),我們進(jìn)行右旋轉(zhuǎn)。

def rotate_right(z):
    y = z.left
    T3 = y.right
    y.right = z
    z.left = T3
    z.height = 1 + max(get_height(z.left), get_height(z.right))
    y.height = 1 + max(get_height(y.left), get_height(y.right))
    return y

  • 左旋轉(zhuǎn):

當(dāng)一個(gè)節(jié)點(diǎn)的右子樹比左子樹高時(shí),我們進(jìn)行左旋轉(zhuǎn)。

def rotate_left(z):
    y = z.right
    T2 = y.left
    y.left = z
    z.right = T2
    z.height = 1 + max(get_height(z.left), get_height(z.right))
    y.height = 1 + max(get_height(y.left), get_height(y.right))
    return y
  • 左-右旋轉(zhuǎn)和右-左旋轉(zhuǎn):

這些是雙旋轉(zhuǎn)操作,先進(jìn)行一次旋轉(zhuǎn)使其成為第一種或第二種情況,然后再進(jìn)行相應(yīng)的旋轉(zhuǎn)。

AVL樹插入操作

插入操作類似于普通的二叉搜索樹插入,但是在插入后,我們需要更新祖先節(jié)點(diǎn)的高度,并檢查每個(gè)節(jié)點(diǎn)的平衡因子,以確保樹保持平衡。

def insert(node, key):
    if not node:
        return AVLNode(key)
    elif key < node.key:
        node.left = insert(node.left, key)
    else:
        node.right = insert(node.right, key)

    node.height = 1 + max(get_height(node.left), get_height(node.right))
    balance = get_balance(node)

    if balance > 1 and key < node.left.key:
        return rotate_right(node)
    if balance < -1 and key > node.right.key:
        return rotate_left(node)
    if balance > 1 and key > node.left.key:
        node.left = rotate_left(node.left)
        return rotate_right(node)
    if balance < -1 and key < node.right.key:
        node.right = rotate_right(node.right)
        return rotate_left(node)

    return node

AVL樹刪除操作

刪除操作也與普通的二叉搜索樹類似,但在刪除節(jié)點(diǎn)后,我們需要更新祖先節(jié)點(diǎn)的高度,并檢查每個(gè)節(jié)點(diǎn)的平衡因子以重新平衡樹。

def min_value_node(node):
    current = node
    while current.left is not None:
        current = current.left
    return current

def delete(node, key):
    if not node:
        return node

    if key < node.key:
        node.left = delete(node.left, key)
    elif key > node.key:
        node.right = delete(node.right, key)
    else:
        if node.left is None:
            temp = node.right
            node = None
            return temp
        elif node.right is None:
            temp = node.left
            node = None
            return temp

        temp = min_value_node(node.right)
        node.key = temp.key
        node.right = delete(node.right, temp.key)

    if node is None:
        return node

    node.height = 1 + max(get_height(node.left), get_height(node.right))
    balance = get_balance(node)

    if balance > 1 and get_balance(node.left) >= 0:
        return rotate_right(node)
    if balance < -1 and get_balance(node.right) <= 0:
        return rotate_left(node)
    if balance > 1 and get_balance(node.left) < 0:
        node.left = rotate_left(node.left)
        return rotate_right(node)
    if balance < -1 and get_balance(node.right) > 0:
        node.right = rotate_right(node.right)
        return rotate_left(node)

    return node

這個(gè)刪除函數(shù)處理了三種情況:要?jiǎng)h除的節(jié)點(diǎn)有兩個(gè)子節(jié)點(diǎn)、一個(gè)子節(jié)點(diǎn)或沒有子節(jié)點(diǎn)。在刪除節(jié)點(diǎn)后,它會(huì)通過旋轉(zhuǎn)操作確保樹保持平衡。

使用AVL樹

現(xiàn)在我們可以創(chuàng)建一個(gè)AVL樹的實(shí)例,并進(jìn)行插入和刪除操作:

avl_tree = None

keys = [20, 4, 15, 70, 50, 80, 100]
for key in keys:
    avl_tree = insert(avl_tree, key)

avl_tree = delete(avl_tree, 70)

在這個(gè)例子中,我們插入了一些數(shù)字,然后刪除了一個(gè)。

紅黑樹

紅黑樹是另一種自平衡二叉搜索樹,它通過確保樹從根到葉子的最長(zhǎng)可能路徑不超過最短可能路徑的兩倍來維持大致的平衡。

紅黑樹的節(jié)點(diǎn)有兩種顏色:紅色或黑色。這種樹遵循以下重要屬性:

顏色屬性:每個(gè)節(jié)點(diǎn)要么是紅色,要么是黑色。

根屬性:樹的根總是黑色。

葉子屬性:所有葉子(NIL節(jié)點(diǎn))都是黑色。

紅色節(jié)點(diǎn)屬性:如果一個(gè)節(jié)點(diǎn)是紅色的,那么它的兩個(gè)子節(jié)點(diǎn)都是黑色的。

路徑屬性:從任一節(jié)點(diǎn)到其每個(gè)葉子的所有路徑都包含相同數(shù)量的黑色節(jié)點(diǎn)。

紅黑樹通過旋轉(zhuǎn)和重新著色來維持這些屬性。雖然紅黑樹的平衡性不如AVL樹,但它在插入和刪除操作中需要更少的旋轉(zhuǎn),這使得它在某些類型的應(yīng)用中更高效。

紅黑樹節(jié)點(diǎn)定義:

class RedBlackNode:
    def __init__(self, key, color="red"):
        self.key = key
        self.color = color
        self.left = None
        self.right = None
        self.parent = None

這里定義了一個(gè)紅黑樹的節(jié)點(diǎn)。除了常規(guī)的key外,節(jié)點(diǎn)還包含一個(gè)color屬性以及指向父節(jié)點(diǎn)和子節(jié)點(diǎn)的鏈接。

紅黑樹旋轉(zhuǎn)操作:

為了維持紅黑樹的特性,在插入和刪除節(jié)點(diǎn)時(shí)可能需要進(jìn)行樹的旋轉(zhuǎn)操作。主要有兩種類型的旋轉(zhuǎn):左旋和右旋。

  • 左旋:

當(dāng)一個(gè)節(jié)點(diǎn)的右子節(jié)點(diǎn)是紅色而左子節(jié)點(diǎn)是黑色時(shí)進(jìn)行。

def rotate_left(self, x):
    y = x.right
    x.right = y.left
    if y.left != self.TNULL:
        y.left.parent = x

    y.parent = x.parent
    if x.parent == None:
        self.root = y
    elif x == x.parent.left:
        x.parent.left = y
    else:
        x.parent.right = y
    y.left = x
    x.parent = y
  • 右旋:

當(dāng)一個(gè)節(jié)點(diǎn)的左子節(jié)點(diǎn)是紅色而左子節(jié)點(diǎn)的左子節(jié)點(diǎn)也是紅色時(shí)進(jìn)行。

def rotate_right(self, x):
    y = x.left
    x.left = y.right
    if y.right != self.TNULL:
        y.right.parent = x

    y.parent = x.parent
    if x.parent == None:
        self.root = y
    elif x == x.parent.right:
        x.parent.right = y
    else:
        x.parent.left = y
    y.right = x
    x.parent = y

紅黑樹插入操作:

插入操作首先類似于普通的二叉搜索樹插入。但在插入一個(gè)節(jié)點(diǎn)后,可能需要進(jìn)行多次顏色更改和旋轉(zhuǎn)來修復(fù)可能違反的紅黑樹性質(zhì)。

def insert(self, key):
    node = RedBlackNode(key)
    node.parent = None
    node.key = key
    node.left = self.TNULL
    node.right = self.TNULL
    node.color = 1  # 新節(jié)點(diǎn)必須是紅色

    y = None
    x = self.root

    while x != self.TNULL:
        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)

在插入節(jié)點(diǎn)后,fix_insert函數(shù)被調(diào)用以重新平衡樹,確保樹仍然是一個(gè)有效的紅黑樹。

紅黑樹刪除操作:

刪除操作比插入操作更復(fù)雜。刪除節(jié)點(diǎn)后,可能需要進(jìn)行多次顏色更改和旋轉(zhuǎn)來修復(fù)可能違反的紅黑樹性質(zhì)。

def delete_node(self, node, key):
    # 省略具體刪除邏輯
    self.fix_delete(x)

在刪除節(jié)點(diǎn)后,fix_delete函數(shù)被調(diào)用以重新平衡樹。

使用紅黑樹:

現(xiàn)在我們可以創(chuàng)建一個(gè)紅黑樹的實(shí)例,并進(jìn)行插入和刪除操作:

rbt = RedBlackTree()
numbers = [20, 15, 25, 10, 30, 5, 35]
for number in numbers:
    rbt.insert(number)

rbt.delete_node(rbt.root, 15)

在這個(gè)例子中,我們插入了一些數(shù)字,然后刪除了一個(gè)。

紅黑樹是一種復(fù)雜的數(shù)據(jù)結(jié)構(gòu),它通過一系列精心設(shè)計(jì)的規(guī)則和操作來確保樹的平衡。盡管它的實(shí)現(xiàn)比普通的二叉搜索樹復(fù)雜得多,但它在插入、刪除和查找操作上提供了良好的最壞情況性能。這種平衡是通過確保任何路徑上的黑色節(jié)點(diǎn)數(shù)目大致相同來實(shí)現(xiàn)的。紅黑樹廣泛應(yīng)用于計(jì)算機(jī)科學(xué)的許多領(lǐng)域,尤其是在那些需要快速查找操作的場(chǎng)景中,如數(shù)據(jù)庫和文件系統(tǒng)。

實(shí)現(xiàn)紅黑樹要求對(duì)它的性質(zhì)和操作有深入的理解。上述代碼提供了一個(gè)基本的框架,但它并不完整。在實(shí)際應(yīng)用中,您可能還需要處理更多的邊界情況和優(yōu)化。每個(gè)操作背后都有復(fù)雜的邏輯和數(shù)學(xué)原理,這是理解和實(shí)現(xiàn)紅黑樹的關(guān)鍵部分。

到此這篇關(guān)于python代碼實(shí)現(xiàn)AVL樹和紅黑樹的文章就介紹到這了,更多相關(guān)AVL樹和紅黑樹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python數(shù)據(jù)結(jié)構(gòu)之圖的應(yīng)用示例

    Python數(shù)據(jù)結(jié)構(gòu)之圖的應(yīng)用示例

    這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)之圖的應(yīng)用,結(jié)合實(shí)例形式分析了Python數(shù)據(jù)結(jié)構(gòu)中圖的定義與遍歷算法相關(guān)操作技巧,需要的朋友可以參考下
    2018-05-05
  • pygame游戲之旅 計(jì)算游戲中躲過的障礙數(shù)量

    pygame游戲之旅 計(jì)算游戲中躲過的障礙數(shù)量

    這篇文章主要為大家詳細(xì)介紹了pygame游戲之旅的第8篇,教大家實(shí)現(xiàn)游戲中躲過障礙數(shù)量的計(jì)算,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • 如何在Django項(xiàng)目中引入靜態(tài)文件

    如何在Django項(xiàng)目中引入靜態(tài)文件

    這篇文章主要介紹了如何在Django項(xiàng)目中引入靜態(tài)文件,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • keras .h5轉(zhuǎn)移動(dòng)端的.tflite文件實(shí)現(xiàn)方式

    keras .h5轉(zhuǎn)移動(dòng)端的.tflite文件實(shí)現(xiàn)方式

    這篇文章主要介紹了keras .h5轉(zhuǎn)移動(dòng)端的.tflite文件實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • python爬蟲之爬取百度音樂的實(shí)現(xiàn)方法

    python爬蟲之爬取百度音樂的實(shí)現(xiàn)方法

    今天小編就為大家分享一篇python爬蟲之爬取百度音樂的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • 在python tkinter中Canvas實(shí)現(xiàn)進(jìn)度條顯示的方法

    在python tkinter中Canvas實(shí)現(xiàn)進(jìn)度條顯示的方法

    今天小編就為大家分享一篇在python tkinter中Canvas實(shí)現(xiàn)進(jìn)度條顯示的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-06-06
  • Boston數(shù)據(jù)集預(yù)測(cè)放假及應(yīng)用優(yōu)缺點(diǎn)評(píng)估

    Boston數(shù)據(jù)集預(yù)測(cè)放假及應(yīng)用優(yōu)缺點(diǎn)評(píng)估

    這篇文章主要為大家介紹了Boston數(shù)據(jù)集預(yù)測(cè)放假及應(yīng)用優(yōu)缺點(diǎn)評(píng)估,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 最新評(píng)論