让我们在Rust中使用RefCell结构实现一个简单的Tree数据结构。特别是,我们将编写traverse()方法来收集树中包含的所有项。
代码如下:
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
pub struct TreeNode {
pub val: i32,
pub left: Option<Rc<RefCell<TreeNode>>>,
pub right: Option<Rc<RefCell<TreeNode>>>,
}
pub fn traverse(root: &Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut result = Vec::new();
let mut queue = VecDeque::new();
queue.push_back(root.as_ref());
while let Some(opt) = queue.pop_front() {
if let Some(node) = opt {
let borrowed = node.borrow();
result.push(borrowed.val);
queue.push_back(borrowed.left.as_ref());
queue.push_back(borrowed.right.as_ref());
}
}
result
}
为了理解错误消息,记录一下与编译器错误相关的变量类型:
error[E0597]: `borrowed` does not live long enough
--> src/lib.rs:19:29
|
17 | let borrowed = node.borrow();
| -------- binding `borrowed` declared here
18 | result.push(borrowed.val);
19 | queue.push_back(borrowed.left.as_ref());
| ^^^^^^^^ borrowed value does not live long enough
20 | queue.push_back(borrowed.right.as_ref());
21 | }
| -
| |
| `borrowed` dropped here while still borrowed
| borrow might be used here, when `borrowed` is dropped and runs the destructor for type `Ref<'_, TreeNode>`
了解了这些类型之后,让我们来检查一下错误消息。编译器抱怨借用的变量生命周期不够长,在第21行被drop了。根源在于node,注意,node变量的类型是&Rc<RefCell
好,那我们怎么修改代码呢?查看我们的类型,我们观察到&Rc<…>类型源自队列变量,当前类型为VecDeque<Option<&Rc<RefCell
pub fn traverse(root: &Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut result = Vec::new();
let mut queue = VecDeque::new();
// queue.push_back(root.as_ref());
queue.push_back(root.as_ref().map(|rc| Rc::clone(rc)));
while let Some(opt) = queue.pop_front() {
if let Some(node) = opt {
let borrowed = node.borrow();
result.push(borrowed.val);
// queue.push_back(borrowed.left.as_ref());
// queue.push_back(borrowed.right.as_ref());
queue.push_back(borrowed.left.as_ref().map(|rc| Rc::clone(rc)));
queue.push_back(borrowed.right.as_ref().map(|rc| Rc::clone(rc)));
}
}
result
}
注意,为了克隆Rc,必须使用Rc::clone(Rc)而不是Rc .clone()来调用它。修复后,以下是变量的新类型:
queue: VecDeque<Option<Rc<RefCell<TreeNode>>>>
opt: Option<Rc<RefCell<TreeNode>>>
node: Rc<RefCell<TreeNode>>
borrowed: Ref<TreeNode>
编译器不再报错!
虽然我们修复了编译器错误,但这个修复似乎使我们的代码变得有点冗长。有更简单的方法吗?本质上,我们要做的是取&Option
pub fn traverse(root: &Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut result = Vec::new();
let mut queue = VecDeque::new();
// queue.push_back(root.as_ref());
// queue.push_back(root.as_ref().map(|rc| Rc::clone(rc)));
queue.push_back(root.clone());
while let Some(opt) = queue.pop_front() {
if let Some(node) = opt {
let borrowed = node.borrow();
result.push(borrowed.val);
// queue.push_back(borrowed.left.as_ref());
// queue.push_back(borrowed.right.as_ref());
// queue.push_back(borrowed.left.as_ref().map(|rc| Rc::clone(rc)));
// queue.push_back(borrowed.right.as_ref().map(|rc| Rc::clone(rc)));
queue.push_back(borrowed.left.clone());
queue.push_back(borrowed.right.clone());
}
}
result
}
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8