iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
自我挑戰組

用python學習資料結構與演算法 學習筆記系列 第 13

Binary Search Tree (二元搜尋樹)

  • 分享至 

  • xImage
  •  

二元搜尋樹(Binary Search Tree)是二元樹(Binary Tree)的一種,但其另外遵循以下幾個規則:
1. Left child 的值會少於等於其父節點的值
2. Right child 的值會大於等於其父節點的值
3. 任意節點的左右子樹也符合上述定義

由於有這些特別的特性,BST在插入與刪除節點方面較一般的BT快 (時間複雜度: O(logn) versus O(n))。我們直接來看程式碼:

from collections import deque

class TreeNode:
    def __init__(self, data=None):
        self.data = data
        self.leftchild = None
        self.rightchild = None
        
# 時間複雜度: O(logN),空間複雜度: O(logN)        
def insertNode(root, value):
    new_node = TreeNode(value)
    # 如果rootNode還沒有東西,那他就是rootnode惹
    if root.data == None:
        root.data = value
        return 'The value is inserted'
    # 欲插入值小於節點值,根據BST的定義,往左邊看
    elif value <= root.data:
        if root.leftchild is None:
            root.leftchild = new_node
            return 'The value is inserted'
        else:
            return insertNode(root.leftchild, value)
    # 欲插入值大於節點值,根據BST的定義,往右邊看
    else:
        if root.rightchild is None:
            root.rightchild = new_node
            return 'The value is inserted'
        else:
            return insertNode(root.rightchild, value)
            
# traversal的方法也跟binary tree,這裡我們就不再贅述,單純用leverordertraversal來看樹現在長怎樣
def levelordertraversal(root):
    customqueue = deque()
    customqueue.append(root)
    while len(customqueue) != 0:
        pop_node = customqueue.popleft()
        print(pop_node.data)
        if pop_node.leftchild is not None:
            customqueue.append(pop_node.leftchild)
        if pop_node.rightchild is not None:
            customqueue.append(pop_node.rightchild)
BST = TreeNode()
insertNode(BST, 40)
insertNode(BST, 50)
insertNode(BST, 30)
insertNode(BST, 90)
insertNode(BST, 10)
levelordertraversal(BST)
>>  40
    30
    50
    10
    90

# 搜尋值,時間複雜度: O(logN),空間複雜度: O(logN)  
def searchNode(root, value):
    if not root:
        return 'Not Found!'
    if root.data == value:
        return 'Found!'
    elif value < root.data:
        return searchNode(root.leftchild, value)
    elif value > root.data:
        return searchNode(root.rightchild, value)

print(searchNode(BST, 40))
>> Found!
print(searchNode(BST, 60))
>> Not Found!
# 由於在刪除節點的case裡,在遇到有兩個子樹的時候,需要在right subtree裡找一個local minimum的node而定義的函式
def findlocalmin(node):
    current = node
    while current.leftchild is not None:
        current = current.leftchild
    return current
   

# 時間複雜度:O(logN), 空間複雜度: O(logN)
def deleteNode(node, target):
    if not node:
        return node
    elif target < node.data:
        node.leftchild = deleteNode(node.leftchild, target)
    elif target > node.data:
        node.rightchild = deleteNode(node.rightchild, target)
    else:
        # 只有single child或是 no children的case,將下面那個節點上移
        if node.leftchild is None:
            temp = node.rightchild
            node = temp
            return temp
        elif node.rightchild is None:
            temp = node.leftchild
            node = temp
            return temp
        # 在兩個children都在的情況下,在右邊子樹找local minimum的值代替
        else:
            temp = findlocalmin(node.rightchild)
            node.data = temp.data
            node.rightchild = deleteNode(node.rightchild, temp.data)
            return temp
            
print('=== delete Node ===')
deleteNode(BST,40)
levelordertraversal(BST)
>>  50
    30
    90
    10

參考資料:
本文主要為udemy課程: The Complete Data Structures and Algorithms Course in Python的學習筆記,有興趣的人可以自己上去看看。


上一篇
Binary Tree -3 (二元樹-3)
下一篇
Binary Heap (二元堆積)
系列文
用python學習資料結構與演算法 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言