1、二叉搜索树(BST)的定义
二叉搜索树是一种基于节点的二叉树数据结构,具有以下属性:
- 节点的左子树只包含键值小于节点键值的节点。
- 节点的右子树只包含键大于该节点键的节点。
- 左右子树也必须是二叉搜索树。
-
2、插入
简单插入:
从根开始搜索一个键,直到找到一个叶节点。一旦找到一个叶节点,新节点将作为叶节点的子节点添加。
比较插入: 从根开始。
- 将插入元素与根元素进行比较,如果小于根元素,则递归向左,否则递归向右。
到达末尾后,只需在左边(如果小于当前节点)插入该节点,否则在右边插入该节点。
3、删除
删除有以下几种情况:
删除的结点是叶结点,直接从树中删除
- 删除的结点有一个叶结点;将叶结点复制到结点并删除叶结点
- 删除的结点有两个叶结点:具体有两种方式(中序遍历):
- 将当前结点的右结点的左子树的最小值复制到当前结点,并删除最小值结点
- 将当前结点的左结点的右子树的最大值复制到当前结点,并删除最大值结点
4、平衡二叉树
一棵空树是平衡二叉树;若 T 是一棵非空二叉树,其左、右子树为和
,令
和
分别为左、右子树的深度。当且仅当:
和
都是平衡二叉树;
-
≤ 1;
时,则 T 是平衡二叉树。
相应地定义-
为二叉平衡树的平衡因子 (balance factor) 。因此,平衡二叉树上所有结点的平衡因子可能是 -1 , 0 , 1 。
换言之,若一棵二叉树上任一结点的平衡因子的绝对值都不大于 1 ,则该树是就平衡二叉树。
为什么有平衡二叉树?
二叉树的理想时间复杂度是,最坏情况是
。如下图所示:

重平衡二叉搜索树的主要操作称为旋转。
假设存在x、y和z的三叉树重组(对应于单或双旋转)后的树T ,从左到右的叶子结点分别为,存在以下几种情况:
5、实现
LinkedBinaryTree、 MapBase
import LinkedBinaryTree, MapBaseclass TreeMap(LinkedBinaryTree, MapBase):"""sorted map implementation using a binary search tree"""# ---------------override position class-------------class Position(LinkedBinaryTree.Position):def key(self):"""return key of map's key-value pair"""return self.element()._keydef value(self):return self.element()._value# --------------------- nonpublic utilities ------------------def _subtree_search(self, p, k):"""return Position of p's subtree having key k, or last node searched"""if k == p.key():return pelif k < p.key():if self.left(p) is not None:return self._subtree_search(self.left(p), k)elif self.right(p) is not None:return self._subtree_search(self.right(p), k)return pdef _subtree_first_position(self, p):"""return position of first item in subtree rooted at p."""walk = pwhile self.left(walk) is not None: # keep walking leftwalk = self.left(walk)return walkdef _subtree_last_position(self, p):"""return position of last item in subtree rooted at p"""walk = pwhile self.right(walk) is not None:walk = self.right(walk)return walkdef first(self):"""return the first postion in the tree, 最小值 """return self._subtree_first_position(self.root()) if len(self) > 0 else Nonedef last(self):"""return the last position in the tree, 最大值"""return self._subtree_last_position(self.root()) if len(self) > 0 else Nonedef before(self, p):"""return the position just before p in the natural order.return None if p is the first position."""self._validate(p) # inherited from LinkedBinaryTreeif self.left(p):# 查找p结点左子树的最大值return self._subtree_last_position(self.left(p))else:# 如果p结点没有左子树,则找其父节点# walk upwardwalk = pabove = self.parent(walk)while above is not None and walk == self.left(above):walk = aboveabove = self.parent(walk)return abovedef after(self, p):"""return the position just after p in the natural order.return None if p is the last position."""self._validate(p) # inherited from LinkedBinaryTreeif self.right(p):return self._subtree_first_position(self.right(p))else:# walk upwardwalk = pabove = self.parent(walk)while above is not None and walk == self.right(above):walk = aboveabove = self.parent(walk)return abovedef find_position(self, k):"""return position with key k, or else neighbor """if self.is_empty():return Noneelse:p = self._subtree_search(self.root(), k)self._rebalance_access(p) # hook for balanced tree subclassesreturn pdef find_min(self):"""return (key,value) pair with minimum key"""if self.is_empty():return Noneelse:p = self.first()return (p.key(), p.value())def find_ge(self, k):"""return (key,value) pair with least key greater than or equal to k.return None if there does not exist such a key"""if self.is_empty():return Noneelse:p = self.find_position(k)if p.key() < k: # may not find exact matchp = self.after(p) # p’s key is too smallreturn (p.key(), p.value()) if p is not None else Nonedef find_range(self, start, stop):"""iterate all (key,value) pairs such that start<=key<stop.if start is None, iteration begins with minimum key of map.if stop is None,iteration continues through the maximum key of map"""if not self.is_empty():if start is None:p = self.first()else:# initialize p with logic similar to find_gep = self.find_position(start)if p.key() < start:p = self.after(p)while p is not None and (stop is None or p.key() < stop):yield (p.key(), p.value())p = self.after(p)def __getitem__(self, k):"""return value associated with key k (raise KeyError if not found)"""if self.is_empty():raise KeyError('Key Error: ' + repr(k))else:p = self._subtree_search(self.root(), k)self._rebalance_access(p) # hook for balanced tree subclassesif k != p.key():raise KeyError('Key Error: ' + repr(k))return p.value()def __setitem__(self, k, v):"""assign value v to key k, overwriting existing value if present"""if self.is_empty():leaf = self._add_root(self._Item(k, v)) # from LinkedBinaryTreeelse:p = self._subtree_search(self.root(), k)if p.key() == k:p.element()._value = v # replace existing item's valueself._rebalance_access(p) # hook for balanced tree subclassesreturnelse:item = self._Item(k, v)if p.key() < k:leaf = self._add_right(p, item) # inherited from LinkedBinaryTreeelse:leaf = self._add_left(p, item) # inherited from LinkedBinaryTreeself._rebalance_insert(leaf) # hook for balanced tree subclassesdef __iter__(self):"""generate an iteration of all keys in the map in order"""p = self.first()while p is not None:yield p.key()p = self.after(p)def delete(self, p):"""remove the item at given position"""self._validate(p)if self.left(p) and self.right(p):replacement = self._subtree_last_position(self.left(p))self._replace(p, replacement.element())p = replacement# now p has at most one childparent = self.parent(p)self._delete(p)self._rebalance_delete(parent) # if root deleted, parent is Nonedef __delitem__(self, k):"""remove the item at given position"""if not self.is_empty():p = self._subtree_search(self.root(), k)if k == p.ley():self.delete(p) # rely on positional versionreturnself._rebalance_access(p) # hook for balanced tree subclassesraise KeyError('KeyError: ' + repr(k))def _rebalance_insert(self, p):passdef _rebalance_delete(self, p):passdef _rebalance_access(self, p):passdef _relink(self, parent, child, make_left_child):"""relink parent node with child node (we allow child to be None)"""if make_left_child:parent._left = childelse:parent._right = childif child is not None:child._parent = parentdef _rotate(self, p):"""rotate position p above its parent"""# z-->y-->xx = p._nodey = x._parent # we assume this existsz = y._parent # grandparent (possibly None)if z is None:self._root = x # x becomes rootx._parent = Noneelse:self._relink(z, x, y == z._left) # x becomes a direct child of z# Now rotate x and y , including transfer of middle subtreeif x == y._left:self._relink(y, x._right, True) # x. right becomes left child of yself._relink(x, y, False) # y becomes right child of xelse:self._relink(y, x._left, False) # x. left becomes right child of yself._relink(x, y, True) # y becomes left child of xdef _restructure(self, x):"""perform trinode restructure of position x with parent/grandparent"""y = self.parent(x)z = self.parent(y)if (x == self.right(y)) == (y == self.right(z)): # matching alignmentsself._rotate(y) # single rotation (of y)return y # y is new subtree rootelse: # opposite alignmentsself._rotate(x) # double rotation (of x)self._rotate(x)return x # x is new subtree rootif __name__ == '__main__':#--------------------T = TreeMap()T['b'] = 4T['a'] = 5T['c'] = 6p = T.first()print(p.key())print(T.parent(p).key())print(T.find_position('a').value(),T.find_position('b').value(),T.find_position('c').value())last = T.last()print(T.left(p),T.right(p))print(last.key())print([*T])print(T['a'])T.delete(p)print([*T])
