13.2-1
算法的伪代码由 RIGHT-ROTATE 给出,其和 LEFT-ROTATE 非常类似。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 RIGHT-ROTATE(T, y) x = y.left y.left = x.right if x.right != T.nil x.right.p = y x.p = y.p if y.p == T.nil T.root = x else if y == y.p.left y.p.left = x else y.p.right = x x.right = y y.p = x
13.2-2
对于任意一个节点 ,如果它有右子节点 ,那么可以进行左旋,从而将 旋转到 的位置;如果它有左子节点 ,那么可以进行右旋,将 旋转到 的位置。
可见,如果当前节点 能够进行旋转,关键在于看它是否包含左 / 右子节点。只要包含一个子节点就能进行一次旋转。如果 拥有一个子节点,那么 恰好就需要一条边连接着它,这恰好对应了某一个旋转方案。
由于 中一共有 条边,因此 中有 种不同的旋转方式。
13.2-3
由图可以得知, 的深度增加了 ; 的深度保持不变; 的深度减少了 。
13.2-4
对于任意一棵树 ,考虑按照如下策略将其旋转成一条向右伸展的链 :从根节点出发,一直访问右子节点,直到最右侧的节点,得到一条路径 。如果这条路径上存在一个节点 ,其左子节点非空,那么对 进行一次右旋,那么路径 将会增加一个节点。
当路径 包含了全部节点时,上述右旋过程结束。由于进行一次右旋操作, 就会增加一个节点,并且 中最多只有 个节点,因此最多 次右旋操作就可以将 旋转成 。
此外,由于右旋的操作是可逆的(对应一次左旋),因此从 旋转成任意一棵树同样至多只需要 次左旋操作。
那么,假设现在需要从 通过旋转操作变成 ,那么从 变换到 需要 次操作,从 变换到 需要 次操作。那么总操作次数 满足 。因此 ,原结论成立。
13.2-5
如下如所示,左边的 无法通过右旋操作转化为 。
如果 能够只通过右旋操作转换成 ,那么考虑进行递归操作。 的根节点必定在 中最左的路径上(即从根节点出发,一直访问左子节点,直到最左侧的叶节点,得到一条路径 )。因此,使用 次的操作可以将这个根节点旋转到根的位置。那么接下来对这棵树的子树递归进行这种旋转操作。由于这棵树一共有 个节点,因此所需要的操作次数最多为 。