《算法导论》第三版第12章 二叉搜索树 练习&思考题 个人答案

这篇博客详细解答了《算法导论》第三版第12章关于二叉搜索树的各项练习,涵盖二叉搜索树的概念、查询、插入和删除等方面,深入探讨了树的性质和操作。博主通过反证法和具体例子解释了二叉搜索树的特性,并提供了多项证明和解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

12.1 什么是二叉搜索树

12.1-1

高度为 2:高度为2
高度为3:
高度为3
高度为4:
高度为4
高度为5:
高度为5
高度为6:
高度为6

12.1-2

解:最小堆的结点值总不大于孩子结点的值,而二叉搜索树的结点值不小于左子树元素结点的值,不大于右子树元素结点的值;最小堆性质无法在O(n)时间内按序输出一棵有n个结点树的关键字,因为堆(以最小堆为例)无法告知大于当前结点的最小元素是在左子树还是在右子树。
换一个角度考虑,如果真的有这种方法,意味着存在O(n)时间的比较排序算法,而这被证明是不存在的。

12.1-3

解:

INORDER-TREE-WALK(T)
let S be an empty stack
current = T.root
done = 0
while !done
    if current != NIL
        PUSH(S, current)
        current = current.left
    else
        if !S.EMPTY()
            current = POP(S)
            print current
            current = current.right
        else done = 1

12.1-4

解:

PREORDER-TREE-WALK(x)
if x != NIL
    print x.key
    PREORDER-TREE-WALK(x.left)
    PREORDER-TREE-WALK(x.right)
POSTORDER-TREE-WALK(x)
if x != NIL
    POSTORDER-TREE-WALK(x.left)
    POSTORDER-TREE-WALK(x.right)
    print x.key

递归真的好用。

12.1-5

证明:反证法,假设我们可以使用小于Ω(nlg⁡n)\Omega(n\lg n)Ω(nlgn)的时间,因为遍历二叉搜索树只需要Θ(n)\Theta(n)Θ(n),我们就可以得到小于Ω(nlg⁡n)\Omega(n\lg n)Ω(nlgn)的比较排序算法,这与第8章的证明相矛盾。(也就类似于12.1-3的思路了)

12.2 查询二叉搜索树

12.2-1

解:c(先找到911后找到912不可能)和e(先找到347后找到299不可能)。

12.2-2

解:

TREE-MINIMUM(x)
while x.left != NIL
    return TREE-MINIMUM(x.left)
return x
TREE-MAXIMUM(x)
while x.right != NIL
    return TREE-MAXIMUM(x.right)
return x

12.2-3

解:

TREE-PREDECESSOR(x)
if x.left != NIL
    return TREE-MAXIMUM(x.left)
y = x.p
while y != NIL and x == y.left
    x = y
    y = y.p
return y

12.2-4

思路:例如在查找过程中某一结点x的右孩子的两个孩子结点选择了右边,x的右孩子的左孩子就归到A集合,但该数还是比B集合中的x大。

12.2-5

证明:结点x的后继s一定位于x的右子树,而后继s如果有左孩子,该左孩子肯定还是位于x的右子树,那么该左孩子的值就介于x和s之间,那么s就不是x的后继了,矛盾;对称地可证明前驱没有右孩子。

12.2-6

证明:首先,我们确定yyy必须是xxx的祖先。如果yyy不是xxx的祖先,那么让zzz表示xxxyyy的第一个共同祖先。根据二叉搜索树属性,x&lt;z&lt;yx&lt;z&lt;yx<z<y,因此yyy不能是xxx的后继。接下来注意y.lefty.lefty.left必须是xxx的祖先,因为如果不是,那么y.righty.righty.right将是xxx的祖先,暗示x&gt;yx&gt; yx>y。最后,假设yyy不是xxx的最底层祖先,其左孩子也是xxx的祖先。让zzz表示这个最底层祖先。那么zzz必须在yyy的左子树中,这意味着z&lt;yz &lt;yz<y,这与yyyxxx的后继相矛盾。

12.2-7

证明(来自参考答案):
Note that a call to TREE-MINIMUM\text{TREE-MINIMUM}TREE-MINIMUM followed by n−1n - 1n1 calls to TREE-SUCCESSOR\text{TREE-SUCCESSOR}TREE-SUCCESSOR performs exactly the same inorder walk of the tree as does the procedure INORDER-TREE-WALK\text{INORDER-TREE-WALK}INORDER-TREE-WALK. INORDER-TREE-WALK\text{INORDER-TREE-WALK}INORDER-TREE-WALK prints the TREE-MINIMUM\text{TREE-MINIMUM}TREE-MINIMUM first, and by
definition, the TREE-SUCCESSOR\text{TREE-SUCCESSOR}TREE-SUCCESSOR of a node is the next node in the sorted order determined by an inorder tree walk.
This algorithm runs in Θ(n)\Theta(n)Θ(n) time because:

It requires O(n)O(n)O(n) time to do the n procedure calls.
It traverses each of the n−1n - 1n1 tree edges at most twice, which takes O(n)O(n)O(n) time.

To see that each edge is traversed at most twice (once going down the tree and once going up), consider the edge between any node uuu and either of its children, node vvv. By starting at the root, we must traverse (u,v)(u, v)(u,v) downward from uuu to vvv, before traversing it upward from vvv to uuu. The only time the tree is traversed downward is in code of TREE-MINIMUM\text{TREE-MINIMUM}TREE-MINIMUM, and the only time the tree is traversed upward is in code of TREE-SUCCESSOR\text{TREE-SUCCESSOR}TREE-SUCCESSOR when we look for the successor of a node that has no right subtree.
Suppose that is uuu's left child.

Before printing uuu, we must print all the nodes in its left subtree, which is rooted at vvv, guaranteeing the downward traversal of edge (u,v)(u, v)(u,v).
After all nodes in uuu's left subtree are printed, uuu must be printed next. Procedure TREE-SUCCESSOR\text{TREE-SUCCESSOR}TREE-SUCCESSOR traverses an upward path to uuu from the maximum element (which has no right subtree) in the subtree rooted at . This path clearly includes edge (u,v)(u, v)(u,v), and since all nodes in uuu's left subtree are printed, edge (u,v)(u, v)(u,v) is never traversed again.

Now suppose that vvv is uuu's right child.

After uuu is printed, TREE-SUCCESSOR(u)\text{TREE-SUCCESSOR}(u)TREE-SUCCESSOR(u) is called. To get to the minimum element in uuu's right subtree (whose root is vvv), the edge (u,v)(u, v)(u,v) must be traversed downward.
After all values in uuu's right subtree are printed, TREE-SUCCESSOR\text{TREE-SUCCESSOR}TREE-SUCCESSOR is called on the maximum element (again, which has no right subtree) in the subtree rooted at vvv. TREE-SUCCESSOR\text{TREE-SUCCESSOR}TREE-SUCCESSOR traverses a path up the tree to an element after uuu, since uuu was already printed. Edge (u,v)(u, v)(u,v) must be traversed upward on this path, and since all nodes in uuu's right subtree have been printed, edge (u,v)(u, v)(u,v) is never traversed again.

Hence, no edge is traversed twice in the same direction.
Therefore, this algorithm runs in Θ(n)\Theta(n)Θ(n) time.

12.2-8

证明:假设xxx是起始节点,yyy是结束节点。xxxyyy之间的距离最多为2h2h2h,连接kkk节点的所有边都被访问两次,因此需要O(k+h)O(k + h)O(k+h)时间。

12.2-9

证明:
假设xxxyyy的左孩子,那么y.key&gt;x.keyy.key&gt;x.keyy.key>x.key,以及yyy可能有的右子树的关键字都大于y.keyy.keyy.key,且xxx是叶结点没有右孩子,所以y.keyy.keyy.keyTTT树中大于x.keyx.keyx.key的最小关键字;
假设xxxyyy的右孩子,那么y.key&lt;x.keyy.key&lt;x.keyy.key<x.key,以及yyy可能有的左子树的关键字都小于y.keyy.keyy.key,且xxx是叶结点没有左孩子,所以y.keyy.keyy.keyTTT树中小于x.keyx.keyx.key的最大关键字。

12.3 插入和删除

12.3-1

解:

RECURSIVE-TREE-INSERT(T, z)
if T.root = NIL
    T.root = z
else INSERT(NIL, T.root, z)
INSERT(p, x, z)
if x == NIL
    z.p = p
    if z.key < p.key
        p.left = z
    else 
        p.right = z
else if z.key < x.key
    INSERT(x, x.left, z)
else 
    INSERT(x, x.right, z)

12.3-2

证明:易证路径是一样的,又因为搜索时检查的节点数也包括搜索到的节点,所以……

12.3-3

解:

TREE-SORT(A)
let T be an empty binary search tree
for i = 1 to A.length
    TREE-INSERT(A[i])
INORDER-TREE-WALK(T.root)

最坏情况:Θ(n2)\Theta(n^2)Θ(n2) - 当重复的TREE-INSERT\text {TREE-INSERT}TREE-INSERT操作产生一个线性结点链时。
最好情况:Θ(nlg⁡n)\Theta(n\lg n)Θ(nlgn) - 当重复的TREE-INSERT\text {TREE-INSERT}TREE-INSERT操作产生高度为Θ(lg⁡n)\Theta(\lg n)Θ(lgn)的二叉树时。

12.3-4

解:不一样

先删除A,再删除B:

  A        C        C
 / \      / \        \
B   D    B   D        D
   /
  C
先删除B,再删除A:
  A        A        D
 / \        \      /
B   D        D    C
   /        /
  C        C

12.3-5

解:

PARENT(z)
if z == NIL
    m = T.root
else 
    m = z.left
while m != x
    p = m
    m = m.right
return p
GET-PARENT(T, x)
if x.right == NIL
    if x == x.succ.left
        x.p = x.succ
    else
        z = x.succ
        x.p = PARENT(z)
else
    y = TREE-MAXIMUM(x.right)
    if x == y.succ.left
        x.p = y.succ
    else
        z = y.succ
        x.p = PARENT(z)

12.3-6

思路:可以在原函数第5行添加一个RANDOM(0,1),返回0选择前驱,返回1选择后继即可。

12.4 随机构建二叉搜索树

12.4-1

证明:
∑i=0n−1(i+33)=∑i=0n−1(i+3)(i+2)(i+1)6=16∑i=0n−1i3+6i2+11i+6=16((n−1)2n24+6(n−1)n(2n−1)6+11n(n−1)2+6n)=n(n+1)(n+2)(n+3)24=(n+34). \begin{aligned} \sum_{i = 0}^{n - 1} \binom{i + 3}{3} &amp; = \sum_{i = 0}^{n - 1} \frac{(i + 3)(i + 2)(i + 1)}{6} \\ &amp; = \frac{1}{6} \sum_{i = 0}^{n - 1} i^3 + 6i^2 + 11i + 6 \\ &amp; = \frac{1}{6} (\frac{(n - 1)^2 n^2}{4} + \frac{6(n - 1)n(2n - 1)}{6} + \frac{11n(n - 1)}{2} + 6n) \\ &amp; = \frac{n(n + 1)(n + 2)(n + 3)}{24} \\ &amp; = \binom{n + 3}{4}. \end{aligned} i=0n1(3i+3)=i=0n16(i+3)(i+2)(i+1)=61i=0n1i3+6i2+11i+6=61(4(n1)2n2+66(n1)n(2n1)+211n(n1)+6n)=24n(n+1)(n+2)(n+3)=(4n+3).

12.4-2

证明(来自参考答案):
We will answer the second part first. We shall show that if the average depth of a p node is Θ(lg⁡n)\Theta(\lg n)Θ(lgn), then the height of the tree is O(nlg⁡n)O(n\lg n)O(nlgn). Then we will answer the first part by exhibiting that this bound is tight: there is a binary search tree with p average node depth Θ(lg⁡n)\Theta(\lg n)Θ(lgn) and height Θ(nlg⁡n)=ω(lg⁡n)\Theta(\sqrt{n\lg n}) = \omega(\lg n)Θ(nlgn )=ω(lgn).
Lemma
If the average depth of p a node in an nnn-node binary search tree is Θ(lg⁡n)\Theta(\lg n)Θ(lgn), then the height of the tree is O(nlg⁡n)O(\sqrt{n\lg n})O(nlgn ).
Proof
Suppose that an nnn-node binary search tree has average depth Θ(lg⁡n)\Theta(\lg n)Θ(lgn) and height hhh. Then there exists a path from the root to a node at depth hhh, and the depths of

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值