【笔记】
旋转:保持二叉查找树性质的查找树局部操作。
左旋:
void leftRotate(NODE *x) { NODE *y = x->r; x->r = y->l; if (y->l != nil) { y->l->p = x; } y->p = x->p; if (x->p == nil) { root = y; } else { if (x == x->p->l) { x->p->l = y; } else { x->p->r = y; } } y->l = x; x->p = y; }
右旋:
void rightRotate(NODE *x) { NODE *y = x->l; x->l = y->r; if (y->r != nil) { y->r->p = x; } y->p = x->p; if (x->p == nil) { root = y; } else { if (x == x->p->l) { x->p->l = y; } else { x->p->r = y; } } y->r = x; x->p = y; }
【练习】
13.2-1 写出RIGHT-ROTATE的伪代码。
见笔记。
13.2-2 证明:在一棵有n个结点的二叉查找树中,刚好有n-1种可能的旋转。
除根结点外,每个结点都能有父结点做旋转。
n=1时,只有根结点,0种可能的旋转。
假设n=k-1时,有k-2种旋转。
当n=k时,添加了一个结点,则此结点为叶子结点,该结点可与其父亲旋转。刚好有k-1种可能的旋转。
因此有n个结点的二叉查找树刚好有n-1种可能的旋转。
13.2-3 设在图中左边一棵树中,a,b和c分别为子树α,β和γ中的任意结点。如果将结点x左旋,则a,b和c的深度会如何变化?
a-=1 b+=1 c+=1
13.2-4 证明:任何一棵含n个结点的二叉查找树,可以通过O(n)次旋转,转变为另一棵含n个结点的二叉查找树。
可以通过右旋所有有左孩子的节点将一颗二叉树变成一个单链的仅有右孩子的二叉树。
也可以通过这个过程的反向操作将一个单链的二叉树变成任意形态的二叉树。
*13.2-5 如果能够使用一系列的RIGHT-ROTATE调用来把一个二叉查找树T1变为二叉查找树T2,则说T1可以右转成T2。请给出一棵两棵树的例子,其中T1不能右转成T2。然后证明如果T1可以右转成T2,则它可以使用O(n^2)次RIGHT-ROTATE调用来右转。