平衡树树旋转
代码
inline void left_rotate(int &node)
{
int r=tree[node].r;
tree[node].r=tree[r].l;
tree[r].l=node;
node=r;
}
inline void right_rotate(int &node)
{
int l=tree[node].l;
tree[node].l=tree[l].r;
tree[l].r=node;
node=l;
}
分析
先上一张树旋转的示意图
图片来自《算法导论》 $ ext{P176 13.2}$ 旋转
树旋转的作用
树旋转是平衡树上用于维护平衡树平衡的基本操作,有左旋和右旋两种操作
旋转过程分析
在进行树旋转时需要维护好二叉搜索树的性质,即
对于每棵子树,都有:
左 < 根 < 右
再看《算法导论》中描述旋转的图片。
以右旋为例,旋转后$ ext{x}$代替$ ext{y}$作为子树的根节点,由于原来$ ext{x}$在$ ext{y}$的左子树上,所以旋转最后$ ext{y}$在$ ext{x}$的右子树上;
而旋转前$ ext{x}$的左子树$alpha$的根节点则一定小于$ ext{x}$和$ ext{y}$,所以旋转后$alpha$仍在$ ext{x}$的左子树上;
而$ ext{x}$的右子树$eta$的根节点则可以看出来是$ ext{x} < eta < ext{y}$的一种关系,所以旋转后在$ ext{y}$的左子树上;
至于$ ext{y}$的右子树$gamma$则与$ ext{x}$的左子树$alpha$类似,这里不再阐述。
代码分析
以左旋为例:
int r=tree[node].r;
先将node
节点的右子树另外保存,同swap
函数的t
变量类似。
tree[node].r=tree[r].l;
将图中$ ext{x}$节点的右子树$ ext{y}$节点改为$ ext{y}$节点的左子树$eta$
tree[r].l=node;
将图中$ ext{y}$节点的左子树改为$ ext{x}$节点
node=r;
最后把正在旋转的子树的根节点改为$ ext{y}$
参考文献
-
《算法导论》 $ ext{P176 13.2}$ 旋转