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

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

证明:反证法,假设我们可以使用小于 Ω ( n lg ⁡ n ) \Omega(n\lg n) Ω(nlgn)的时间,因为遍历二叉搜索树只需要 Θ ( n ) \Theta(n) Θ(n),我们就可以得到小于 Ω ( n lg ⁡ 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

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

12.2-7

证明(来自参考答案):
Note that a call to TREE-MINIMUM \text{TREE-MINIMUM} TREE-MINIMUM followed by n − 1 n - 1 n1 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 − 1 n - 1 n1 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 u u u and either of its children, node v v v. By starting at the root, we must traverse ( u , v ) (u, v) (u,v) downward from u u u to v v v, before traversing it upward from v v v to u u u. 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 u u u's left child.

Before printing u u u, we must print all the nodes in its left subtree, which is rooted at v v v, guaranteeing the downward traversal of edge ( u , v ) (u, v) (u,v).
After all nodes in u u u's left subtree are printed, u u u must be printed next. Procedure TREE-SUCCESSOR \text{TREE-SUCCESSOR} TREE-SUCCESSOR traverses an upward path to u u u 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 u u u's left subtree are printed, edge ( u , v ) (u, v) (u,v) is never traversed again.

Now suppose that v v v is u u u's right child.

After u u u is printed, TREE-SUCCESSOR ( u ) \text{TREE-SUCCESSOR}(u) TREE-SUCCESSOR(u) is called. To get to the minimum element in u u u's right subtree (whose root is v v v), the edge ( u , v ) (u, v) (u,v) must be traversed downward.
After all values in u u u'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 v v v. TREE-SUCCESSOR \text{TREE-SUCCESSOR} TREE-SUCCESSOR traverses a path up the tree to an element after u u u, since u u u was already printed. Edge ( u , v ) (u, v) (u,v) must be traversed upward on this path, and since all nodes in u u u'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

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

12.2-9

证明:
假设 x x x y y y的左孩子,那么 y . k e y &gt; x . k e y y.key&gt;x.key y.key>x.key,以及 y y y可能有的右子树的关键字都大于 y . k e y y.key y.key,且 x x x是叶结点没有右孩子,所以 y . k e y y.key y.key T T T树中大于 x . k e y x.key x.key的最小关键字;
假设 x x x y y y的右孩子,那么 y . k e y &lt; x . k e y y.key&lt;x.key y.key<x.key,以及 y y y可能有的左子树的关键字都小于 y . k e y y.key y.key,且 x x x是叶结点没有左孩子,所以 y . k e y y.key y.key T T T树中小于 x . k e y x.key x.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)

最坏情况: Θ ( n 2 ) \Theta(n^2) Θ(n2) - 当重复的 TREE-INSERT \text {TREE-INSERT} TREE-INSERT操作产生一个线性结点链时。
最好情况: Θ ( n lg ⁡ 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 = 0 n − 1 ( i + 3 3 ) = ∑ i = 0 n − 1 ( i + 3 ) ( i + 2 ) ( i + 1 ) 6 = 1 6 ∑ i = 0 n − 1 i 3 + 6 i 2 + 11 i + 6 = 1 6 ( ( n − 1 ) 2 n 2 4 + 6 ( n − 1 ) n ( 2 n − 1 ) 6 + 11 n ( n − 1 ) 2 + 6 n ) = n ( n + 1 ) ( n + 2 ) ( n + 3 ) 24 = ( n + 3 4 ) . \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 ( n lg ⁡ 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 Θ ( n lg ⁡ n ) = ω ( lg ⁡ n ) \Theta(\sqrt{n\lg n}) = \omega(\lg n) Θ(nlgn )=ω(lgn).
Lemma
If the average depth of p a node in an n n n-node binary search tree is Θ ( lg ⁡ n ) \Theta(\lg n) Θ(lgn), then the height of the tree is O ( n lg ⁡ n ) O(\sqrt{n\lg n}) O(nlgn

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值