如何旋转 treap 或 AVL 树

How to rotate a treap or AVL-tree?

本文关键字:treap AVL 旋转 何旋转      更新时间:2023-10-16

很抱歉再次打扰你们,但我有一个问题,我已经好几天没有自己弄清楚了。它是关于 treap 的旋转,例如,在 pos 处向右旋转 treap。问题是如何将pos->left链接(或连接)到pos的原始父级?我在网上找到了这段代码,它有效,但我没有看到它如何解决我的问题,是因为使用了*&吗?如果是这样,你能帮我解释一下吗?这段代码pos=b的功能是什么?

void Treap::right_rotate(Node *&pos) {
    Node *b   = pos->left; 
    pos->left = b->right;
    b->right  = pos;
    pos       = b;
}

提前感谢!!

棘手的部分确实是*&部分。这将它声明为对指针的引用(这里有一两个指向一些类似示例代码的链接,但我担心它们可能更令人困惑而不是有用)。

通过更改指针指向的节点 pos = b ,您可以将内容交换到不同的节点,而无需知道父节点。原始参照将更新为新的旋转节点。

这是一个图表,以防你需要对旋转的外观进行一些矫枉过正(尽管听起来你理解了那部分)。

初始条件:

Node *&pos; 
         |
        [P]
      /     
     L       R
    /      /  
   w   x   y   z

然后存储左子项,因为就 P 而言,您将要覆盖它。

Node *b = pos->left;
pos->left = b->right;
           |
    L     [P]
  /     /   
 w     x      R
             /  
            y   z

现在我们完成旋转,因为 L 漂浮在空间中,破坏了正确的树结构:

b->right = pos;
        L     
      /   |
     w    [P]
         /   
        x     R
             /  
            y   z

然后,我们将对节点指针的引用更新为替换内存中该位置内容的新节点来完成维护:

pos = b;
       |
      [L]     
     /   
    w      P
         /   
        x     R
             /  
            y   z

以前指向pospos的原始父级)的人现在指向内存中的同一位置,但该值现在已替换为已旋转的子项。