二插查詢樹是這樣一種二叉樹結構,它的每乙個結點包含乙個key和它附帶的資料,對每乙個結點v:
所有的key小於v都被儲存在v的左子樹
所有key大於v的都存在v的右子樹
class
bstnode
(object):
def__init__
(self, key, value, left=
none
, right=
none):
self.key, self.value, self.left, self.right = key, value, left, right
class
bst(
object):
def__init__
(self, root =
none):
self.root = root
defbuild_from
(self, nodelist)
: req =
for i in nodelist:
key = i.get(
'key'
) node = bstnode(key, value = key)
req[key]
= node
for i in nodelist:
key = i[
'key'
] node = req.get(key)
node.left = req.get(i[
'left'])
node.right = req.get(i[
'right'])
if i[
'is_root']:
self.root = node
return self.root
def__contains__
(self, key)
:return self._bst__search(self.root,key)
isnot
none
查詢:
根據定義從跟結點開始如果值大於該節點就訪問右子樹,否則訪問左子樹,直到結點的值為none。
def
_bst_search
(self, subtree, key)
:if subtree is
none
:return
none
elif key < subtree.key:
return self._bst_search(subtree.left, key)
elif key > subtree.key:
return self._bst_search(subtree.right, key)
else
:return subtree
defget(self, key, default=
none):
node = self._bst_search(self.root, key)
if node is
none
:return default
else
:return node.value
插入:
def
_bst_insert
(self, subtree, key, value)
:#插入一定會插入葉節點
""" 插入並且返回根節點
:param subtree:
:param key:
:param value:
"""if subtree is
none
:# 插入的節點一定是根節點,包括 root 為空的情況
subtree = bstnode(key, value)
elif key < subtree.key:
subtree.left = self._bst_insert(subtree.left, key, value)
elif key > subtree.key:
subtree.right = self._bst_insert(subtree.right, key, value)
return subtree
defadd(self, key, value)
: node = self._bst_search(self.root, key)
if node is
notnone
:# 更新已經存在的 key
node.value = value
return
false
else
: self.root = self._bst_insert(self.root, key, value)
#細節 self.size +=
1return
true
刪除操作作用比上邊的操作要麻煩的很多,首先需要定位乙個結點,刪除節點後,我們需要始終保持bst的性子。刪除節點涉及到三種情況。
節點是葉節點
節點有乙個孩子
節點有孩子
這是最簡單的一種情況,只需要將它的父親指向它的指標設定為none就好。
刪除有乙個孩子的節點時,我們拿掉需要刪除的節點,之後把它的父親指向它的父親指向它的孩子就行,因為根據bst左子樹都小於節點,右子樹都大於節點的特性,刪除它之後這個條件依舊滿足。(節點的右子樹)的全部節點都是大於該節點的。因為在構建二叉樹的時候,只有大於右子樹的節點才會往子樹上新增。
找到待刪除節點n的後繼節點s。
複製節點s到節點n。
從n的右子樹刪除節點s,並更新其後繼節點後的右子樹。
現在關鍵就是找到後繼節點。
**如下:
def
_bst_remove
(self, subtree, key)
:#刪除節點並返回根節點
if subtree is
none
:return
none
elif key < subtree.key:
subtree.left = self._bst_remove(subtree.left, key)
return subtree
elif key > subtree.key:
subtree.right = self._bst_remove(subtree.right, key)
return subtree
else
:#找到了需要刪除的節點
if subtree.left is
none
and subtree.right is
none
:#葉節點,返回none把其父親指向它的指標置為none
return
none
elif subtree.left is
none
or subtree.right is
none
:#只有乙個孩子
if subtree.left is
notnone
:return subtree.left#返回它的孩子並它的父親指過去
else
:return subtree.right
else
:#兩孩子,尋找後繼節點替換,並從待節點的右子樹中刪除後繼節點
successor_node = self._bst_min_node(subtree.right)
#找到右子樹的最小值
subtree.key, subtree.value = successor_node.key, successor_node.value
subtree.right =self._bst_remove(subtree.right, successor_node.key)
#刪除右結點的最小值並且返回右結點
return subtree
defremove()
:assert key in self
self.size -=
1return self._bst_remove(self.root, key)
上邊介紹的操作時間複雜複雜度和二叉樹形狀有關,平均來說時間複雜度是和樹的高度成正比的,樹的高度h是log(n),但最壞情況以上操作的時間複雜度都是o(n),
其實還按照其定義,最小值就一直向右子樹找,最大值一直向右子樹找:
def
_bst_min_node
(self, subtree)
:if subtree is
none
: reuturn none
elif surtree.left is
none
:#找到左子樹的頭
return subtree
else
:return self._bst_min_node(subtree.left)
defbst_min
(self)
: node = self._bst_min_node(self.root)
return node.value if node else
none
二叉查詢樹(BST) 樹
目錄1,定義 二叉查詢樹 binary search tree 又名二叉搜尋樹或二叉排序樹。可以是一顆空樹,或者是具有下列性質的二叉樹 1 若它的左子樹不空,則左子樹上所有結點的指均小於它的根結點的值 2 若它的右子樹不空,則右子樹上所有結點的指均大於它的根結點的值 2,c 實現二叉樹的基本操作 i...
二分查詢樹(BST)
這個出現頻率比較高,為了防止忘了,寫一下好了 二分查詢樹的性質 來自維基百科 若任意節點的左子樹不空,則左子樹上所有結點的值均小於或等於它的根結點的值 任意節點的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值 任意節點的左 右子樹也分別為二叉查詢樹。沒有鍵值相等的節點 英語 no dupli...
二叉查詢樹 BST
當所有的靜態查詢結構新增和刪除乙個資料的時候,整個結構都需要重建。這對於常常需要在查詢過程中動態改變資料而言,是災難性的。因此人們就必須去尋找高效的動態查詢結構,我們在這討論乙個非常常用的動態查詢樹 二叉查詢樹。二叉查詢樹的特點 下面的圖就是兩棵二叉查詢樹,我們可以總結一下他的特點 1 若它的左子樹...