Rust中二叉树的左旋转失败了

时间:2017-01-02 17:49:54

标签: tree rust move-semantics lifetime tree-rotation

我尝试实现自平衡二进制搜索树并编写了一个用左旋转替换树的函数:

struct BST<'a> {
    l: Option<&'a BST<'a>>,
    r: Option<&'a BST<'a>>
}

impl<'a> BST<'a> {
    fn left_rotate(self) -> BST<'a> {
        /*
         *   (x)                 (y)
         *  /   \               /   \
         * a     (y)    =>   (x)     c
         *      /   \       /  \
         *     b     c     a    b
         */
        match self.r {
            None => self,
            Some(y) => BST {
                l: Some(& BST {l: self.l, r: y.l}),
                r: y.r
            } 
        }
    }
}

尝试使用rustc bst.rs编译此示例会导致以下错误:

error: borrowed value does not live long enough
  --> bst.rs:18:27
   |
18 |                 l: Some(& BST {l: self.l, r: y.l}),
   |                           ^^^^^^^^^^^^^^^^^^^^^^^ temporary value created here
19 |                 r: y.r
20 |             }
   |             - temporary value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the block at 7:36...
  --> bst.rs:7:37
   |
7  |     fn left_rotate(self) -> BST<'a> {
   |                                     ^

据我所知,因为原始树在函数返回时被销毁,所以由于lifetime parameter contravariance,它的左旋转不能超过它。我的目的是让函数使用原始树并以这样的方式返回左旋转,即左旋转将继承原始树在未调用函数时的生命周期。这可能在Rust吗?如果没有,那么最简单的设计是什么来实现我支持树木替换的目标?我的偏好是避免依赖Rust标准库并学会自己管理生命周期。

请原谅我在Rust生活中缺乏经验。我的背景知识主要是C ++和ML风格的语言。

1 个答案:

答案 0 :(得分:4)

您滥用参考资料。

就像C ++一样,Rust有指针和引用:指针拥有,引用借用。

如果您有&'a BST<'b>

  • 是对内存中某处的BST<'b>的引用,其存在时间至少与'a
  • 一样长
  • 包含的内容至少与'b
  • 一样长

然而,这里:

  • 您不想引用BST,您想拥有它们
  • 您的BST不包含任何需要参考的内容。顺便说一句,没有有效载荷,它们毫无意义。

你真正想要的是:

struct BST {
    l: Option<Box<BST>>,
    r: Option<Box<BST>>
}

impl BST {
    fn left_rotate(self) -> BST {
        match self.r {
            None => self,
            Some(mut y) => {
                BST {
                    l: Some(Box::new(BST {l: self.l, r: y.l.take()})),
                    r: y.r.take()
                } 
            }
        }
    }
}