二叉查找樹(Binary Search Tree)
, 簡稱BST
,必須具備如下性質:node
小於
它的根結點的值大於
它的根結點的值在二叉查找樹中查找節點時, 平均運行時間爲O(logn)
(平衡狀況), 最壞爲O(n)
(極度不平衡), 平均深度是O(logn)
python
在有序數組中使用二分查找時最壞的時間複雜度是O(logn)
, 可是二叉搜索樹的插入
和刪除
的性能更優git
二叉搜索樹和數組對比github
- | 數組 | 二叉搜索樹 |
---|---|---|
查找 | O(logn)(二分查找) | O(logn) |
插入 | O(n) | O(logn) |
刪除 | O(n) | O(logn) |
插入/查找/刪除
最大/最小
節點# coding:utf-8 class TreeNode(object): def __init__(self, key, value, parent=None, left=None, right=None): self.key = key self.value = value self.parent = parent self.left = left self.right = right def isLeftChild(self): return self.parent and self.parent.left == self def isRightChild(self): return self.parent and self.parent.right == self def childrenNums(self): num = 0 if self.left: num += 1 if self.right: num += 1 return num class BinarySearchTree(object): def __init__(self): self.root = None self.size = 0 def put(self, key, value): if self.root: self._put(key, value, self.root) else: self.root = TreeNode(key, value) self.size += 1 def _put(self, key, value, current): if key < current.key: if current.left: self._put(key, value, current.left) else: current.left = TreeNode(key, value, parent=current) elif key > current.key: if current.right: self._put(key, value, current.right) else: current.right = TreeNode(key, value, parent=current) def get(self, key): if self.root: res = self._get(key, self.root) else: return None return res def _get(self, key, current): if not current: return None if key < current.key: return self._get(key, current.left) elif key > current.key: return self._get(key, current.right) else: return current def delete(self, key): if self.size > 1: # 要先找到該節點 node2remove = self.get(key) if node2remove: self.remove(node2remove) self.size -= 1 else: raise Exception('no element') elif self.size == 1 and self.root.key == key: self.root = None self.size -= 1 else: raise Exception('no element') def remove(self, current): childrens = current.childrenNums() if 0 == childrens: if current.isLeftChild(): current.parent.left = None else: current.parent.right = None elif 1 == childrens: # 若是該節點有左子樹 if current.left: if current.isLeftChild(): current.left.parent = current.parent current.parent.left = current.left elif current.isRightChild(): current.left.parent = current.parent current.parent.right = current.left else: self.root = current.left # 若是是右子樹 elif current.right: if current.isLeftChild(): current.right.parent = current.parent current.parent.left = current.right elif current.isRightChild(): current.right.parent = current.parent current.parent.right = current.right else: self.root = current.right # 若是有兩個子節點 else: parent = current minChild = current.right while minChild.left != None: parent = minChild minChild = minChild.left current.key = minChild.key current.value = minChild.value # 注意如下狀況判斷, 由於有的沒有左子節點 if parent.left == minChild: parent.left = minChild.right if minChild.right: minChild.right.parent = parent else: parent.right = minChild.right if minChild.right: minChild.right.parent = parent def length(self): return self.size def __setitem__(self, key, value): self.put(key, value) def __getitem__(self, key): return self.get(key) def __delitem__(self, key): self.delete(key) def mid(self, root): if not root: return self.mid(root.left) print(root.value) self.mid(root.right) if __name__ == '__main__': mytree = BinarySearchTree() mytree[7] = "7" mytree[2] = "2" mytree[11] = "11" mytree[8] = "8" mytree[19] = "19" mytree[5] = "5" mytree[1] = "1" # 中序遍歷 mytree.mid(mytree.root) print('------') # 刪除葉子節點1 del mytree[1] mytree.mid(mytree.root) print('------') # 刪除有一個子節點的2 del mytree[2] mytree.mid(mytree.root) print('------') # 刪除有兩個子節點的11 del mytree[11] mytree.mid(mytree.root)
散列表更加高效, 爲何還有二叉查找樹?算法