12.3-1
struct BinTree
{
int key;
BinTree *parent;
BinTree *left;
BinTree *right;
};
void TREE_INSERT(BinTree **root,int key)
{
if(*root == NULL) //插入根节点
{
BinTree *z = new BinTree;
z->key = key;
z->left = z->right = NULL;
*root = z;
z->parent = NULL;
return;
}
BinTree *x = *root;
if(x->key > key) //左子树
{
if(x->left == NULL) //左子树为空
{
BinTree *z = new BinTree;
z->key = key;
z->left = z->right = NULL;
z->parent = x;
x->left = z;
}
else TREE_INSERT(&(x->left),key);//以左子树为根递归插入
}
else //右子树
{
if(x->right == NULL)
{
BinTree *z = new BinTree;
z->key = key;
z->left = z->right = NULL;
z->parent = x;
x->right = z;
}
else TREE_INSERT(&(x->right),key);
}
}
12.3-2
插入之后查找关键字
x
,需要检查是否和关键字
12.3-3
最坏情况是所有关键字已经排序好,运行时间是
12.3-4
不可以,如下图,删除关键字
3,4
会变成不一样的树。
12.3-5
这道题的中文翻译有问题,原书是用x.succ
来 代替x.p
。即有左子树、右子树和后继节点三个指针。然后其他的和中文版翻译的一样。
返回一个结点的父结点,采用类似TREE-SEARCH
即可在
O(h)
时间找到。
struct BinTree
{
int key;
BinTree *succ;
BinTree *left;
BinTree *right;
};
BinTree *PARENT(BinTree *root,int key)
{
if(key == root->key) //关键字是根节点
return NULL;
BinTree *t = root; //从根节点开始查找关键字的父节点
BinTree *parent;
while(t->key != key)
{
parent = t;
if(t->key > key)
t = t->left;
else t = t->right;
}
return parent;
}
TREE-SEARCH
不用改。
以下两点还未解决
TREE-INSERT
和虽然可以只用left,right
指针,但是要维护succ
指针,在此过程中有可能用到插入结点父结点前驱,如果新结点
z
插入到结点 z.suc=x
,若插入到右边,那么z.suc=x.suc; x.suc=z
。
同样TREE-DELETE
也可能用到删除结点父结点前驱
12.3-6
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-MAXIMUM(T,y,y.left)
if y.p ≠ z
TRANSPLANT(T,y,y.left)
y.left = z.left
y.left.p = y
TRANSPLANT(T,z,y)
y.right = z.right
y.right.p = y
公平策略就是用一个flag交替使用两种方法。