题目
解答:
a) 不管是插入还是删除,需要改变的节点包括从根节点开始到要插入或者删除位置的路径上的所有节点。
b) 其中key[x] == k;
PERSISTENT-TREE-INSERT(T, x)
{
curr <- root[T];
T' <-NULL, p <-NULL;//T'为新根,p记录查找过程中当前节点的父亲
while (curr != NULL)
{
tmp <- copy(curr);//复制当前节点,返回指针
if (T' == NULL)//第一个节点时
T' <- tmp;
if (p == NULL)
p <- tmp;
else if (key[tmp] < key[p])//若当前新建节点较小,则成为上一个新建节点的左孩子
left[p] <- tmp;
else right[p] <- tmp;
p <- tmp;
if (key[x] < key[curr])
{//若插入关键较小
//则说明当前节点的右子树不会被遍历,即不会修改,那么将成为p的右子树
right[p] <- right[curr];
curr <- left[curr];
}
else
{//否则
left[p] <- left[curr];
curr <- right[curr];
}
}
if (key[x] < key[p])//将x放到适当位置
left[p] <- x;
else right[p] <- x;
return T';
}
c) 时间和空间均为O(h)
d) 在没有父指针域的时候,对于不会被遍历的子树,比如上述b)图中关键字为3的包含两个节点的子树,我们是不会改变它们任一个域的,对于关键字为3的节点也只是新节点4的左孩子指针指向它;但是,如果添加了父指针域,那么就要改变关键字3节点的父指针域,为了保存旧版本,此时就要新建一个关键字为3的新节点,同理,也必须新建关键字为2的节点,其他依次类推。因此,对于一棵有n个节点的树,要复制所有的节点,时空要求为Ω(n)。
e) 在本章中,红黑树的删除和插入时间为O(lgn);但是对于本题,该树并不含有父指针域,那么调整过程就会很麻烦,必须每次去查找所需节点,最坏情况下运行时间为O(lg^2n),因为调整过程都是自下而上且只涉及该路径上的有关节点,节点数为O(lgn),每次查找需要O(lgn)时间。因此有必要保存该路径上的相关节点,根据自底向上的调整策略,很容易想到需要用栈,在每次调整时,控制好出栈时机就能在O(lgn)时间内正确的进行插入和删除了。