對於二叉查找樹的每個節點Node,它的左子樹中所有的關鍵字都小於Node的關鍵字,而右子樹中的所有關鍵字都大於Node的關鍵字。
二叉查找樹的平均深度是O(log N)。
1.初始化
class BinarySearchTree(object):
def __init__(self,key):
self.key=key
self.left=None
self.right=None
2.Find
def find(self,x):
if x==self.key:
return self
elif x<self.key and self.left:
return self.left.find(x)
elif x>self.key and self.right:
return self.right.find(x)
else:
return None
3.FindMin和FindMax
分別返回樹中的最小元素與最大元素的位置。FindMin,從根開始並且只要有左兒子就向左進行查找,終止點是最小元素。FindMax則向右進行。
def findMin(self):
if self.left:
return self.left.findMin()
else:
return self
def findMax(self):
tree=self
if tree:
while tree.right:
tree=tree.right
return tree
4.Insert
為了將x插入到樹Tree中,先用find查找,如果找到x,則什么也不做。否則,將x插入到遍歷路徑的最后一點。
來自《Problem Solving with Algorithms and Data Structures》的圖片:

def insert(self,x):
if x<self.key:
if self.left:
self.left.insert(x)
else:
tree=BinarySearchTree(x)
self.left=tree
elif x>self.key:
if self.right:
self.right.insert(x)
else:
tree=BinarySearchTree(x)
self.right=tree
5.Delete
刪除某節點有3種情況:
5.1 如果節點是一片樹葉,那么可以立即被刪除。
來自《Problem Solving with Algorithms and Data Structures》的圖片:

5.2 如果節點只有一個兒子,則將此節點parent的指針指向此節點的兒子,然后刪除。
來自《Problem Solving with Algorithms and Data Structures》的圖片:
5.3 如果節點有兩個兒子,則將其右子樹的最小數據代替此節點的數據,並將其右子樹的最小數據(不可能有左兒子,只有一個右兒子)刪除。
來自《Problem Solving with Algorithms and Data Structures》的圖片:

def delete(self,x):
if self.find(x):
if x<self.key:
self.left=self.left.delete(x)
return self
elif x>self.key:
self.right=self.right.delete(x)
return self
elif self.left and self.right:
key=self.right.findMin().key
self.key=key
self.right=self.right.delete(key)
return self
else:
if self.left:
return self.left
else:
return self.right
else:
return self
全部代碼
class BinarySearchTree(object):
def __init__(self,key):
self.key=key
self.left=None
self.right=None
def find(self,x):
if x==self.key:
return self
elif x<self.key and self.left:
return self.left.find(x)
elif x>self.key and self.right:
return self.right.find(x)
else:
return None
def findMin(self):
if self.left:
return self.left.findMin()
else:
return self
def findMax(self):
tree=self
if tree:
while tree.right:
tree=tree.right
return tree
def insert(self,x):
if x<self.key:
if self.left:
self.left.insert(x)
else:
tree=BinarySearchTree(x)
self.left=tree
elif x>self.key:
if self.right:
self.right.insert(x)
else:
tree=BinarySearchTree(x)
self.right=tree
def delete(self,x):
if self.find(x):
if x<self.key:
self.left=self.left.delete(x)
return self
elif x>self.key:
self.right=self.right.delete(x)
return self
elif self.left and self.right:
key=self.right.findMin().key
self.key=key
self.right=self.right.delete(key)
return self
else:
if self.left:
return self.left
else:
return self.right
else:
return self
上述寫法的缺點是很難處理空樹的情況。
另一種類似於鏈表的寫法
class TreeNode(object):
def __init__(self,key,left=None,right=None,parent=None):
self.key=key
self.left=left
self.right=right
self.parent=parent
def hasLeftChild(self):
return self.left
def hasRightChild(self):
return self.right
def isLeftChild(self):
return self.parent and self.parent.left==self
def isRightChild(self):
return self.parent and self.parent.right==self
class BSTree(object):
def __init__(self):
self.root=None
self.size=0
def length(self):
return self.size
def insert(self,x):
node=TreeNode(x)
if not self.root:
self.root=node
self.size+=1
else:
currentNode=self.root
while True:
if x<currentNode.key:
if currentNode.left:
currentNode=currentNode.left
else:
currentNode.left=node
node.parent=currentNode
self.size+=1
break
elif x>currentNode.key:
if currentNode.right:
currentNode=currentNode.right
else:
currentNode.right=node
node.parent=currentNode
self.size+=1
break
else:
break
def find(self,key):
if self.root:
res=self._find(key,self.root)
if res:
return res
else:
return None
else:
return None
def _find(self,key,node):
if not node:
return None
elif node.key==key:
return node
elif key<node.key:
return self._find(key,node.left)
else:
return self._find(key,node.right)
def findMin(self):
if self.root:
current=self.root
while current.left:
current=current.left
return current
else:
return None
def _findMin(self,node):
if node:
current=node
while current.left:
current=current.left
return current
def findMax(self):
if self.root:
current=self.root
while current.right:
current=current.right
return current
else:
return None
def delete(self,key):
if self.size>1:
nodeToRemove=self.find(key)
if nodeToRemove:
self.remove(nodeToRemove)
self.size-=1
else:
raise KeyError,'Error, key not in tree'
elif self.size==1 and self.root.key==key:
self.root=None
self.size-=1
else:
raise KeyError('Error, key not in tree')
def remove(self,node):
if not node.left and not node.right: #node為樹葉
if node==node.parent.left:
node.parent.left=None
else:
node.parent.right=None
elif node.left and node.right: #有兩個兒子
minNode=self._findMin(node.right)
node.key=minNode.key
self.remove(minNode)
else: #有一個兒子
if node.hasLeftChild():
if node.isLeftChild():
node.left.parent=node.parent
node.parent.left=node.left
elif node.isRightChild():
node.left.parent=node.parent
node.parent.right=node.left
else: #node為根
self.root=node.left
node.left.parent=None
node.left=None
else:
if node.isLeftChild():
node.right.parent=node.parent
node.parent.left=node.right
elif node.isRightChild():
node.right.parent=node.parent
node.parent.right=node.right
else: #node為根
self.root=node.right
node.right.parent=None
node.right=None
