1. 程式人生 > 其它 >Binary Search Tree (BST) 的增刪查 -1

Binary Search Tree (BST) 的增刪查 -1

技術標籤:演算法python

Binary Search Tree (BST) 的增刪查

Binary Search Tree (BST)的目的是方便搜尋,特點是一個節點(node)左邊的value比節點的值小,右邊的value比節點的值大或者等於。

首先需要定義一個單獨的節點類

class BST:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None	

這裡一個節點包含三個部分: 本身的value 左邊的child 右邊的child

child可以是單獨的節點、一個子樹, 也可以為空。

以下增刪查的部分按照難易程度排列:

增:插入 insert(self, value)

要插入一個值,首先要比較他和根節點的大小,然後根據“一個節點(node)左邊的value比節點的值小,右邊的value比節點的值大或者等於” 的規律進行左右搜尋,見“空”,新建節點並插入。

    def insert(self, value):
       
		if value<self.value:
            if self.left is None:
                self.left = BST(value)
            else:
                self.left.insert(value)
        else:
            if self.right is None:
                self.right = BST(value)
            else:
                self.right.insert(value)
        return self

查:檢查是否包含 contains(self, value)

輸入一個值,返回當前BST中是否包含這個值,包含則返回True,否則返回False。

檢查是否包含一個值,依然是根據“一個節點(node)左邊的value比節點的值小,右邊的value比節點的值大或者等於” 的規律進行左右搜尋。

如果待查證的value小於當前節點值,向左繼續搜,如果此時左邊為空,返回False。

如果大於當前節點的值向右繼續搜,如果此時右邊為空,返回False。

如果待查證的value等於當前節點的值,返回True。

    def contains(self, value):
        # Write your code here.
        if value<self.value:
            if self.left is None:
                return False
            else:
                self.left.contains(value)
        elif value>self.value:
            if self.right is None:
                return False
            else:
                self.left.contains(value)
        return True

刪:移除特定元素remove(self, value, parent = None)

刪除的操作比較複雜,因為要考慮很多的邊界條件。

在函式的引數表(self, value, parent = None)中給出了一個parent = None,意思是預設情況下該節點沒有父節點。

父節點十分重要,這涉及到如果移除當前節點,BST的值應當如何重新整理的問題。

假設有一棵樹:需要移除節點10(parent = None)

				10
       /   \
      5   	15
		/  \  	/  \
		2   5 	13  22
   /      	/ \ 
   1       12  14

移除之後的結果是

				12
       /   \
      5   	15
		/  \  	/  \
		2   5 	13  22
   /      	  \ 
   1           14

此時節點右側的最小值,也就是將右側的子樹一直向右搜尋出來的值將會取代當前節點的值,並且這個搜出來的右側最小值是大於左側所有值的最小值。因為左邊的值只能是越來越小,右邊即使最小的值也應該比左邊任意一個值大。

此時給出另一種刪除的情形,不是刪除根節點(parent is not None)

刪除15,parent = 10(此時這個節點有parent父節點):

結果是:

				10
       /   \
      5   	14
		/  \  	/  \
		2   5 	13  22
   /      	/ \ 
   1       12  

此時要將當前節點中左側子樹,也就是比當前節點都要小的值中,最大的值拿出來。原因是必須保證這個用來替換的值大於左邊的任何一個值,還要小於等於右邊的任何一個值。

接著,當前節點的parent的右邊的節點就是當前節點(值被替換後)

    def remove(self,value,parent = None):
        if value<self.value:
            #比當前值小,左邊非空,迭代演算法
            if self.left is not None:
                #注意此時的self是當前節點,也就是下一個節點的parent
                self.left.remove(value,parent = self)
            
        if value>self.value:
            #比當前值大,右邊非空,迭代演算法
            if self.left is not None:
                self.left.remove(value,parent = self)
                #注意此時的self是當前節點,也就是下一個節點的parent

        else: #考慮此時當前值相等的情況
            #如果兩邊都有東西,當前值是右側子樹的最小值,並移除該值對應的節點。
            #此時已經考慮節點的兩邊都有子樹的情況
            if self.left is not None and self.right is not None:
                self.value = self.right.getMin(self)
                self.right.remove(self.value)
            #如果當前節點沒有父節點,意味著當前節點是根節點。
            #考慮此時根節點只有一邊有子樹的情況
            elif parent is None:
                # 如果左邊不是空的
                if self.left is not None:
                    self.value = self.left.value
                    self.right = self.left.right
                    self.left = self.left.left
                # 如果右邊不是空的
                elif self.right is not None:
                    self.value = self.right.value
                    self.left = self.right.left
                    self.right = self.right.right
                else:
                    pass
            elif  parent.left == self:
                parent.left = self.left if self.left is not None else self.right
            elif parent.right == self:
                parent.right = self.left if self.left is not None else self.right
        return self
  • 獲取當前BST最小值 getMin(self)

獲取最小值的方法比較簡單,就是一直向左迭代搜尋,直到搜尋到當前節點的左側沒有節點位置(也就是沒有值比當前節點的值更小了)。

def getMin(self):
        if self.left is None:
            return self.value
        else:
            self.left.getMin(value)