后继指针取代父指针的二叉搜索树

(如有错漏,欢迎指正)


算法导论,第三版(Introduction to Algorithms, CLRS, 3rd edition)第十二章二叉搜索树(binary  search tree)课后有这么一道练习题:

Exercises 12.3-5

Suppose that instead of each node x keeping the attribute x.p, pointing to x's parent, it keep x.succ, pointing tox's successor. Give pseudocode for SEARCH, INSERT, and DELETE on a binary search tree T using this representation. These procedures should operate in timeO(h), where h is the height of the tree T. (Hint: You may wish to implement a subroutine that returns the parent of a node.)

中文大意:把二叉搜索树每个节点x中保存的指向其父节点的指针(x.p)替换为指向其后继节点的指针(x.succ),设计复杂度仍为O(h)(h为树的高度,即为O(lg n))的搜索节点,插入节点,删除节点算法。题目中的提示是设计一个能返回父节点的子程序。


x's successor: the node with the smallest key greater than x.key.

后继节点定义:在节点值比x大的节点中,节点值最小的节点为x的后继节点。


那么后继节点会在什么位置呢?先来看看在正常二叉搜索树中找到x的后继节点的伪代码

TREE-SUCCESSOR(x)
if x.right ≠ NIL
    return TREE-MINIMUN(x.right)
y = x.p
while y ≠ NIL and x == y.right
    x = y
    y = y.p
return y


这个程序可以分为两部分:

(1)当x的右子树存在时,x的后继是x的右子树中最小的节点(也就是最左的节点)

(2)当x的右子树不存在时,如果x的后继节点存在,则x的后继是x的祖先节点中第一个左孩子也为x的祖先的节点(如下图)


有了上面的基础,接着思考一下题目的提示:找到一个在后继节点表示的二叉搜索树中找到父节点的方法,注意到SEARCH, INSERT, DELETE中都只调用了常数次的父指针,在后继表示的二叉搜索树中,如果能找到在O(h)时间内找到父节点,就能在O(h)时间内实现上述三种操作。

下面分析如何在O(h)时间内找到父节点(假设无相等的节点):

Case1:x是其父的左孩子且x无右子树


在x.p的左子树中x最大,因此x.p = x.succ,T = O(1)


Case2x是其父的左孩子且x有右子树


在x.p的左子树中,x右子树的最大值最大,因此,令y = TREE-MAXIMUM(x.right),

x.p = y.succ, T = O(lg n)


以下两种情况较为复杂,因为x.p并不是x及其子树的后继节点

Case3x是其父的右孩子且x无右子树


令z = x.succ,若z = NIL,证明在x的祖先节点中没有左孩子也为x的祖先的节点,若z ≠ NIL,证明z是第一个左孩子也为x的祖先的节点。因此,下述伪代码可以返回x.p

if z == NIL
    m = T.root
else 
    m = z.left
while m ≠ x
    p = m
    m = m.right
return p


搜寻次数最多为树的高度,T = O(lg n)


Case4x是其父的右孩子且x有右子树


方法同Case3,区别为令y = MAXIMUM(x.right),z = y.succ


综上所述,在O(lg n)时间内找到父节点的子程序为:

PARENT(z)
if z == NIL
    m = T.root
else 
    m = z.left
while m ≠ x
    p = m
    m = m.right
return p


FIND-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)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值