第三部分 数据结构
第12章 二叉搜索树
- 二叉搜索树上的基本操作所花费的时间与这棵树的高度成正比
- 对于完全二叉树来说最坏运行时间为Θ(lgn)
- 如果这棵树是线性链,那么同样的操作就要花费Θ(n)的最坏运行时间
1. 什么是二叉搜索树
设x是二叉搜索树中的一个结点,则:
1. 若y是x的左子树中的一个结点,那么 y.key <= x.key
2. 若y是x的右子树中的一个结点,那么 y.key >= x.key
中序遍历:输出的子树根的关键字位于其左子树的关键字和右子树的关键字值之间
先序遍历:输出的根的关键字在其左右子树的关键字值之前
后序遍历:输出的根的关键字在其左右子树的关键字值之后
Inorder-Tree-Walk(x)
if x != NIL
Inorder-Tree-Walk(x.left)
print x.key
Inorder-Tree-Walk(x.right)
2. 查询二叉搜索树
查找
递归版本
Tree-Search(x, k)
if x == NIL or k = x.key
return x
if k < x.key
Tree-Search(x.left, k)
else
Tree-Search(x.right, k)
- Tree-Search的运行时间为O(h),其中h是这棵树的高
迭代版本
Iterative-Tree-Search(x, k)
while x != NIL and k != x.key
if k < x.key
x = x.left
else
x = x.right
return x
最大关键字元素和最小关键字元素
Tree-Minimum(x)
while x != NIL
x = x.left
return x
Tree-Maximum(x)
while x != NIL
x = x.right
return x
后继和前驱
- 按中序遍历的次序查找后继
- x的后继是大于x.key的最小关键字的结点
Tree-Successor(x)
if x.right != NIL
return Tree-Minimum(x)
y = x.p
while y != NIL and x == y.right
x = y
y = y.p
return y
3. 插入和删除
插入
Tree-Insert(T, z)
y = NIL
x = T.root
while x != NIL
y = x
if z.key < x.key
x = x.left
else
x = x.right
z.p = y
if y == NIL
T.root = z // tree T was empty
else if z.key < y.key
y.left = z
else
y.right = z
删除
- z没有孩子节点,将它删除,并修改它的父结点,用NIL作为孩子来替换
- z只有一个孩子,将这个孩子提升到树中z的位置,并修改z的父结点,用z的孩子来替换z
- z有两个孩子,找z的后继,并让y占据树中z的位置。如果y是z的右孩子,那么用y替换z,并仅留下y的右孩子,否则,y位于z的右子树中但并不是z的右孩子,在这种情况下,先用y的右孩子替换y,然后再用y替换z
Transplant(T, u, v)
if u.p == NIL
T.root = v
else if u == u.p.left
u.p.left = v
else
u.p.right = v
if v != NIL
v.p = u.p
Tree-Delete(T, z)
if z.left == NIL
Transplant(T, z, z.right)
else if z.right == NIL
Transplant(T, z, z.left)
else
y = Tree-Minimum(z.right)
if y.p != z
Transplant(T, y, y.right)
y.right = z.right
y.right.p = y
Transplant(T, z, y)
y.left = z.left
y.left.p = y