如何在展开树中旋转节点?

时间:2012-11-30 05:17:26

标签: java tree splay-tree

我的代码是

private Node rotateLeftChild(Node n)
{
    Node o = n.left;
    n.left = o.right;
    o.right = n;
    return o;
}

当我打电话给它时,在根处旋转这样的树:

             7
            / \
           4   8
          / \   
         1   5

它删除了4和1,并将5作为7的左根。我尝试将该方法设为无效方法,但这似乎也不起作用。我是以完全错误的方式去做的吗?

1 个答案:

答案 0 :(得分:2)

首先,抱歉我的英语。

回答问题 - 为什么节点4消失很简单。 7有父节点(或7是root)。当你调用rotateLeftChild时,7的父母仍在“思考”他的孩子是7岁,而不是4岁:

Real picture

所以,有树解决方案:

  1. 建立父节点的链接并进行更新。在leftRotation的末尾,分别进行赋值,n.Parent.Left = o或n.Parent.Right = o(if(n.Parent.Left == n)或(n.Parent.Right == n))。当然,当您旋转root的子级时,必须更新树根的链接。

  2. 当您添加|时插入|查找节点,保存堆栈中的所有先前(父)节点,然后在轮换后,您必须更新其子节点的链接。或者像这样使用递归:

    private Splay(Node parent, Node cur, Node n, bool canMoveUpTwice = false) {
        if (cur.Value > n.Value)
            Splay(cur, cur.Left, n, !canMoveUpTwice);
        else
            Splay(cur, cur.Right, n, !canMoveUpTwice);
    
        if (canMoveUpTwice)
            MoveUpTwice();
        else
            MoveUpOnce();
    
        if (parent.Left == cur)
            parent.Left = n;
        else
            parent.Right = n;
    
        if (Parent == null)
            tree.Root = n;
    }
    

    如何使用。添加节点后,必须运行Splay(root,newNode)。确定,你会发现堆栈溢出。

  3. 您必须交换节点的值,然后才能认为节点已被交换。在标准的旋转实现中我们有这样的图片: Simple rotations 在使用交换轮换时,我们得到这个(= x表示“节点具有值X”): Rotations by swap 所以,我们有这个代码

    private rotateLeftChild(Node q) {
        Node p = q.Left;
    
        Swap(q.Value, p.Value); 
    
        A = p.Left;
        B = p.Right;
        C = q.Right;
    
        q.Left  = A;
        q.Right = p;
    
        p.Left  = B;
        p.Right = C;
    }
    
  4. 小心:代码尚未经过测试。