我正在研究二叉搜索树实现中的插入函数。这是我的代码:
pub struct Node {
data: i32,
left: Option<Box<Node>>,
right: Option<Box<Node>>
}
fn insert_at_root(mut root_node: Node, new_node: Node) -> Node { //not reference because root_node will be mutated
if root_node.data > new_node.data { // value less than root
if let Some(left) = root_node.left {
insert_node(*left, new_node); // *left is a way to downcast box, i.e. *left = T from Box<T>
}
else {
root_node.set_left(Some(Box::new(new_node)));
}
}
else if root_node.data < new_node.data {
if let Some(right) = root_node.right {
insert_node(*right, new_node);
}
else {
root_node.set_right(Some(Box::new(new_node)));
}
}
root_node
}
fn insert_node(mut exist_node: Node, new_node: Node) -> () {
if exist_node.data > new_node.data {
if let Some(left) = exist_node.left {
insert_node(*left, new_node);
}
else {
exist_node.set_left(Some(Box::new(new_node)));
}
}
else if exist_node.data < new_node.data {
if let Some(right) = exist_node.right {
insert_node(*right, new_node);
}
else {
exist_node.set_right(Some(Box::new(new_node)));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我有两个插入函数,因此当我调用 insert_at_node 时,我可以保留根节点的变量。
我当前的问题是函数中的行if let Some(left) = root_node.left {(和行if let Some(right) = root_node.right {)insert_at_root显然会导致移动。结果,我无法root_node在结束时返回insert_at_node:
error[E0382]: use of moved value: `root_node`
--> src/lib.rs:34:5
|
19 | if let Some(left) = root_node.left {
| ---- value moved here
...
34 | root_node
| ^^^^^^^^^ value used here after partial move
|
= note: move occurs because value has type `std::boxed::Box<Node>`, which does not implement the `Copy` trait
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)
基本上,这些行的目的是检查left(或right)子节点是否不存在。有什么办法可以在不引起移动的情况下实现这一目标吗?也许带有或符号的东西。Noneroot_node.left != None!===
你的问题不在于你测试left/right是Some还是None。顺便说一句,这可以通过测试.is_some()和来完成.is_none()。
您遇到的问题是您将变量绑定left到. 这样您就可以将 的内容的所有权转移给变量。NodeOptionOptionleft
一般来说,如果您不想移动所有权,则必须使用引用。当变量位于 an 内部Option并且您需要将其内部作为引用查看时,您必须将其类型从 转换Option<T>为Option<&T>。当您查看选项内部时,它只是一个参考,因此不会移动所有权。
有两个函数可以Option执行此转换:.as_ref()转换为不可变引用,以及.as_mut()转换为可变引用。因为你要修改的内容left你需要一个可变的引用,所以.as_mut()就如你所愿。
通过使用.as_mut()您left得到的是引用而不是变量本身,因此没有转移所有权。
您遇到的下一个问题是您无法传递引用,insert_node因为该函数的类型签名需要获取变量而不是引用。这样就要求您在这个辅助函数中传递所有权,因此它也不起作用。因此我们将 的签名转换insert_node为 take&mut Box<Node>而不是Node。因此,我们再次只获取引用,而不获取所有权。
pub fn insert_at_root(mut root_node: Node, new_node: Node) -> Node {
//not reference because root_node will be mutated
if root_node.data > new_node.data {
// value less than root
if let Some(left) = root_node.left.as_mut() {
insert_node(&mut *left, new_node);
} else {
root_node.set_left(Some(Box::new(new_node)));
}
} else if root_node.data < new_node.data {
if let Some(right) = root_node.right.as_mut() {
insert_node(&mut *right, new_node);
} else {
root_node.set_right(Some(Box::new(new_node)));
}
}
root_node
}
pub fn insert_node(exist_node: &mut Box<Node>, new_node: Node) -> () {
if exist_node.data > new_node.data {
if let Some(left) = exist_node.left.as_mut() {
insert_node(&mut *left, new_node);
} else {
exist_node.set_left(Some(Box::new(new_node)));
}
} else if exist_node.data < new_node.data {
if let Some(right) = exist_node.right.as_mut() {
insert_node(&mut *right, new_node);
} else {
exist_node.set_right(Some(Box::new(new_node)));
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2706 次 |
| 最近记录: |