rust - 添加到基于 RefCell 构建的二叉树时,借用的值不会存在足够长的时间

标签 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

next 存在于 add 函数的整个范围内,在我看来,包含对它的引用的其他变量在 next 之前被删除下降了。

编译器说“作用域中的值按照它们创建的相反顺序被删除”,这表明还有另一种方法来声明变量并解决这个问题,但我不知识。

最佳答案

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

也就是说,Rust 不能在循环中做到这一点,但它可以在递归函数中做到这一点,树最好用递归函数实现。

自然地,您的递归结构是 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 中将工作转交给这一个。

如果像其他人指出的那样,您摆脱了 Tree vs NodeRefCell,代码可能会稍微简化。 ..

关于rust - 添加到基于 RefCell 构建的二叉树时,借用的值不会存在足够长的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51701393/

相关文章:

html - 是否有 html5ever 的替代库接受一个字符串并返回一个可查询的对象?

rust - 临时u8切片的Rust字符串

c - 插入二叉树

rust - 错误 : `line` does not live long enough but it's ok in playground

rust - 编译 rust-src 时未知功能 `llvm_asm`

rust - 返回生命周期受参数生命周期限制的迭代器的特征

java - Java 中的二叉搜索树

结构中的字符串切片(在 Rust 中)

rust - 在循环中发生变异时,可变借用时间过长