将借入的值添加到基于RefCell构建的二叉树时寿命不足

时间:2018-08-06 06:03:42

标签: rust binary-tree lifetime borrowing

我试图在二叉树中实现add操作:

use std::cell::RefCell;
use std::cmp::PartialOrd;

type Link<T> = RefCell<Option<Box<Node<T>>>>;

struct Node<T> {
    key: T,
    left: Link<T>,
    right: Link<T>,
}

struct Tree<T> {
    root: Link<T>,
}

impl<T> Node<T> {
    fn new(val: T) -> Self {
        Node {
            key: val,
            left: RefCell::new(None),
            right: RefCell::new(None),
        }
    }
}

impl<T: PartialOrd> Tree<T> {
    fn new() -> Self {
        Tree {
            root: RefCell::new(None),
        }
    }

    fn add(&self, val: T) {
        let mut next = self.root.borrow();
        let node = Box::new(Node::new(val));
        match next.as_ref() {
            None => {
                self.root.replace(Some(node));
                ()
            }
            Some(root_ref) => {
                let mut prev = root_ref;
                let mut cur: Option<&Box<Node<T>>> = Some(root_ref);
                while let Some(node_ref) = cur {
                    prev = node_ref;
                    if node.key < node_ref.key {
                        next = node_ref.left.borrow();
                    } else {
                        next = node_ref.right.borrow();
                    }
                    cur = next.as_ref();
                }
                if node.key < prev.key {
                    prev.left.replace(Some(node));
                } else {
                    prev.right.replace(Some(node));
                }
            }
        }
    }
}

fn main() {}

我不明白为什么next变量的寿命不足:

error[E0597]: `next` does not live long enough
  --> src/main.rs:36:15
   |
36 |         match next.as_ref() {
   |               ^^^^ borrowed value does not live long enough
...
60 |     }
   |     - `next` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

error[E0597]: `next` does not live long enough
  --> src/main.rs:51:27
   |
51 |                     cur = next.as_ref();
   |                           ^^^^ borrowed value does not live long enough
...
60 |     }
   |     - `next` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

nextadd函数的整个范围内有效,并且我认为在删除next之前,删除包含对其引用的其他变量。

编译器说"values in a scope are dropped in the opposite order they are created",表明存在另一种声明变量和解决此问题的方法,但我不知道如何。

1 个答案:

答案 0 :(得分:1)

我看到的问题是,为了更新树的叶节点,您不仅需要保留对每个中间步骤的引用,还必须保留对每个中间步骤的引用,因为到根节点的所有链接都必须保持活动状态。正在更新值。而Rust的一生都无法做到这一点。

也就是说,Rust无法在循环中做到这一点,但可以在递归函数中做到这一点,并且最好使用递归函数来实现树。

自然地,您的递归结构是<script type="text/javascript"> result = "helloworld" document.getElementById('<%= Label1.ClientID %>').innerHTML = result.substring(0,5); </script> ,而不是Node,但是这样的方法可以工作(有很多方法可以使借用工作):

Tree

然后,在impl<T: PartialOrd> Node<T> { fn add(&self, val: T) { let mut branch = if val < self.key { self.left.borrow_mut() } else { self.right.borrow_mut() }; if let Some(next) = &*branch { next.add(val); return; } //Separated from the if let so that branch is not borrowed. *branch = Some(Box::new(Node::new(val))); } } 中将工作转发给该工作。

如其他人所述,如果您摆脱了impl Tree vs TreeNode ...

,可以稍微简化一下代码。