>, left: Opti-6ren">
gpt4 book ai didi

rust - 搜索BST节点的Successor, "clone to satisfy borrow checker"灾难

转载 作者:行者123 更新时间:2023-11-29 08:12:35 27 4
gpt4 key购买 nike

我正在尝试用 Rust 实现 BST。我的结构看起来像这样:

pub struct Node<T> {  
key: T,
parent: Option<Box<Node<T>>>,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}

我正在研究一种寻找当前节点后继者的方法。在与借用检查器进行了长时间的斗争之后,我成功了,但现在看起来像这样:

//If right node exists - successor is a min node in it.
//Else - go up a parent node. If parent is None, no successor.
//If origin was parent's left node - parent is a successor.
//Else - go up another level.
pub fn succ(&self) -> Option<Box<Node<T>>> {

match self.right {
Some(ref node) => Some(node.min()),
None => {
let mut origin = Box::new(self.clone()); //To match types
let mut parent = origin.parent.clone(); //`Node<T>` not a copy type

loop {
let parent_node = match parent.clone() {
Some(node) => node,
None => break,
};
let right_of_parent = match parent_node.clone().right {
Some(node) => node,
None => break,
};
if *origin != *right_of_parent {
break;
}

origin = parent_node;
parent = origin.parent.clone();
}
parent
}
}
}

如果我删除所有 .clone(),编译器将开始报错“部分移动值”和“无法分配因为借用”错误。有没有办法让这段代码更加地道,而不是克隆 hell ?

更新:
想发布我最终得到的解决方案。
首先,上面的代码不起作用,因为父字段包含的不是引用,而是父节点的副本。所以最后问题变成了“如何实现对父节点的引用”。
我考虑了下面的答案,一些booksrelevant answers最后我得出结论,对于一个我什至不打算在线发布的玩具项目来说,它不值得。我发现不是最有效但绝对更简单的解决方案 - 根本不使用父引用。
我从上面的结构中删除了父字段并创建了另一个结构:

pub struct Tree<T> {
root: Option<Box<Node<T>>>,
}

现在我从树的根部搜索父节点。我的 succ 函数现在看起来像这样:

fn succ<'a>(&'a self, node: &'a Node<T>) -> Option<&Node<T>> {
match node.right {
Some(ref rnode) => rnode.min(),
None => {
let mut succ = None;
let mut root = self.root.as_ref();
loop {
root = match root {
Some(ref rootnode) => {
match node.key.cmp(&rootnode.key) {
Ordering::Less => {
succ = Some(&***rootnode);
rootnode.left.as_ref()
}
Ordering::Greater => rootnode.right.as_ref(),
Ordering::Equal => break,
}
}
None => break,
}
}
succ
}
}
}

最佳答案

欢迎使用 Rust 和 Stack Overflow!

这里的主要问题是 Node定义:

pub struct Node<T> {  
key: T,
parent: Option<Box<Node<T>>>,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}

在 Rust 中,Box<T> 拥有 值而不是可以别名的指针。您将无法创建任何非平凡的树。

而不是 Box ,你可以试试引用计数 Rc<T> .您可以使用 Weak父链接的指针,以避免让它们保持事件状态:

use std::rc::{Rc,Weak};
pub struct Node<T> {
key: T,
parent: Option<Weak<Node<T>>>,
left: Option<Rc<Node<T>>>,
right: Option<Rc<Node<T>>>,
}

排序后,您就不会使用引用。每次你做这样的事情:

let mut parent = origin.parent; //.clone();

在你的版本中 origin.parent类型为 Option<Box<Node<T>>> ,您正在尝试移动 Option场外origin - 因此你必须添加 clone() (它克隆了 Box 中的节点,而不仅仅是指针!)。但是,您并不是真的想搬出去;您只需要对它的引用,例如:

let parent = &origin.parent;

或者执行 None同时检查:

match origin.parent {
Some(ref parent_ptr) => { ... },
None => { ... }
}

希望对您有所帮助!

关于rust - 搜索BST节点的Successor, "clone to satisfy borrow checker"灾难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39072257/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com