14.1 二叉搜索树
二叉搜索树(binaey search tree, BST)是一种二叉树,其内的每一个结点储存着搜索关键码以及相应的负载,此二叉树以如下形式构建:
- 对于每一个内结点,小于该内结点的关键码位于该结点的左子树内;
- 对于每一个内结点,大于该内结点的关键码位于该结点的右子树内。
- 删除叶结点;
- 删除只有一个子结点的内结点;
- 删除有两个子结点的内结点。
删除只有一个子结点的内结点
这种情况也相对简单,只需先将该内结点分离出二叉搜索树,然后将其子结点与其父结点相连即可。
删除有两个子结点的内结点
这种情况最复杂,二叉搜索树如果按照中序遍历,会得到一个已排序的序列。那么对于每一个结点来说,就会有逻辑前驱(logical predecessor)和逻辑后继(logical successor),即序列中排在该结点储存元素之前的元素和之后的元素。
对于要删除含两个子结点的内结点,首先是要搜索出该内结点的逻辑后继,然后将逻辑后继复制到该内结点上,再将逻辑后继结点删除即可。
搜索内结点的逻辑后继,按照搜索二叉树的定义,即逻辑后继应该就在该内结点的父结点或者右子树中。
14.1.5 二叉搜索树的效率
假设二叉搜索树有n个结点。
进行搜索操作时,从根结点出发,直到遇到目标结点或是Null,此时一条路径便形成。我们只需考虑最长路径即可,显然路径与二叉搜索树的高度与形状有关,最坏情况就是当二叉搜索树的高度是n时,所以其时间复杂度是O(n)。最大值和最小值搜索的时间复杂度也是O(n)。
由于后面的添加结点或是删除结点均需用到搜索,所以这两个操作的时间复杂度也是O(n)。
14.2 二叉搜索树的迭代器
二叉搜索树的遍历,可先将二叉搜索树中的元素组成一个数组或是栈(使用栈更好,无需额外的内存)。
#-*-coding: utf-8-*-
# 使用二叉搜索树来实现映射ADT
class BSTMap(object):
def __init__(self):
self._root = None
self._size = 0
# 键值对数目
def __len__(self):
return self._size
# 迭代器
def __iter__(self):
return _BSTMapIterator(self._root)
# 判断给定关键码是否存在映射中
def __contain__(self, key):
return self._bstSearch(self._root, key) is not None
# 返回给定关键码对应的值
def valueOf(self, key):
node = self._bstSearch(self._root, key)
assert node is not None, "Invalid map key."
return node.value
# 辅助方法,在二叉搜索树中对目标元素进行搜索
def _bstSearch(self, subtree, target):
if subtree is None: # 终止条件
return
elif target < subtree.key:
return self._bstSearch(subtree.left, target)
elif target > subtree.key:
return self._bstSearch(subtree.right, target)
else: # 终止条件
return subtree
# 最小值
def _bstMinumum(self, subtree):
if subtree is None:
return
elif subtree.left is None:
return subtree
else:
return self._bstMinumum(subtree.left)
# 最大值
def _bstMaxmum(self, subtree):
if subtree is None:
return
elif subtree.right is None:
return subtree
else:
return self._bstMaxmum(subtree.right)
# 向映射中添加新的键值对
def add(self, key, value):
node = self._bstSearch(key) # 判断键是否已存在
if node is not None: # 若存在,直接修改相应值
node.value = value
return False
else: # 若不存在,则向二叉搜索树中插入新元素
self._root = self._bstInsert(self._root, key, value)
self._size += 1
return True
# 辅助方法,向二叉搜索树中插入新元素
def _bstInsert(self, subtree, key, value):
if subtree is None:
subtree = _BSTMapNode(key, value)
elif key < subtree.key:
subtree.left = self._bstInsert(subtree.left, key, value)
elif key > subtree.key:
subtree.right = self._bstInsert(subtree.right, key, value)
return subtree
# 删除键值对
def remove(self, key):
assert key in self, "Invalid map key."
self._root = self._bstRemove(self._root, key)
self._size -= 1
# 辅助方法,从二叉搜索树中删除结点
def _bstRemove(self, subtree, target):
# 搜索目标结点
if subtree is None:
return subtree
elif target < subtree.key:
subtree.left = self._bstRemove(subtree.left, target)
return subtree
elif target > subtree.key:
subtree.right = self._bstRemove(subtree.right, target)
return subtree
else:
if subtree.left is None and subtree.right is None: # 删除的结点是叶结点
return
elif subtree.left is None or subtree.right is None: # 删除的结点是只有一个子结点的内结点
if subtree.left is not None:
return subtree.left
else:
return subtree.right
else: # 删除的结点是有两个子节点的内结点
successor = self._bstMinumum(subtree.right) # 搜索目标结点的逻辑后继
subtree.key = successor.key # 逻辑后继替代目标结点
subtree.value = successor.value
subtree.right = self._bstRemove(subtree.right, successor.key) # 删除原逻辑后继
return subtree
# 二叉搜索树的迭代器,使用数组
# class _BSTMapIterator(object):
# def __init__(self, root, size):
# self._theKeys = Array(size)
# self._curItem = 0
# self._bstTraversal(root)
# self._curItem = 0
# def __iter__(self):
# return self
# def next(self):
# if self._curItem < len(self._theKeys):
# key = self._theKeys[self._curItem]
# self._curItem += 1
# else:
# raise StopIteration
# 对二叉搜索树进行中序遍历,以构建序列数组
# def _bstTraversal(self, subtree):
# if subtree is not None:
# self._bstTraversal(subtree.left)
# self._theKeys[self._curItem] = subtree.key
# self._curItem += 1
# self._bstTraversal(subtree.right)
# 二叉搜索树的迭代器,使用栈
class _BSTMapIterator(object):
def __init__(self, root):
self._theStack = Stack()
self._traverseToMinNode(root) # 将二叉搜索树的元素压入栈中,此时不是所有元素已压入栈中
def __iter__(self):
return self
def next(self):
if self._theStack.isEmpty():
raise StopIteration
else:
node = self._theStack.pop()
key = node.key
if node.right is not None: # 将该结点的逻辑后继压入栈中
self._traverseToMinNode(node.right)
# 对二叉搜索树进行遍历,直到找到其最小值为止,期间的元素压入栈中
def _traverseToMinNode(self, subtree):
if subtree is not None:
subtree._theStack.push(subtree)
subtree._traverseToMinNode(subtree.left)
# 二叉搜索树的储存类
class _BSTMapNode(object):
def __init__(self, key, value):
self.key = key
self.value = value
self.left = None
self.right = right