【发布时间】:2017-10-22 22:57:01
【问题描述】:
我正在尝试在 Rust 中实现平衡 (AVL) 版本的二叉搜索树的轮换代码,但在声明要重组的节点的所有权时遇到问题。
我的结构:
struct Tree<T> {
root: Box<TreeNode<T>>,
depth: usize,
}
enum TreeNode<T> {
Empty,
Node {
val: T,
left: Tree<T>,
right: Tree<T>,
},
}
我知道我只能使用一种类型,即Options。这似乎更好一些。
当我想实现旋转时:
T1, T2, T3 and T4 are subtrees.
z y
/ \ / \
y T4 Right Rotate (z) x z
/ \ - - - - - - - - -> / \ / \
x T3 T1 T2 T3 T4
/ \
T1 T2
我找不到重新分配节点的方法。我有一个在z 节点(Tree<T> 节点)上调用的rotate(&mut self, ...) 方法,但我需要使用match *self.root {} 将根TreeNode 转换为其Node 版本以获取组件。这行得通,但我不能使用这些提取的值来创建一个新节点。
如果我试试这个:
fn insert(&mut self, ...) {
...
// need to rotate
rotate(self, ...);
}
fn rotate(&mut ztree, ...) {
ztree.root = match *ztree.root {
// just re assign same tree to test...
TreeNode::Node {val, left, right} =>
Box::new(TreeNode::Node {val: val, left: left, right: right}),
_ => panic!("meh"),
} ...
我收到此错误。
|
171 | ztree.root = match *ztree.root {
| ^^^^^ cannot move out of borrowed content
172 | TreeNode::Node {val, left, right} =>
| --- ---- ----- ...and here (use `ref right` or `ref mut right`)
| | |
| | ...and here (use `ref left` or `ref mut left`)
| hint: to prevent move, use `ref val` or `ref mut val`
我知道我不喜欢获得盒装 TreeNode 的所有权,但我不知道如何告诉 Rust 我将分配一个新的盒装 TreeNode 和旧的 @987654337 @ 可以在本地声明。
如果我尝试 self.root = Box::new(TreeNode::Empty) 效果很好,因为它知道我正在将 self.root 重新分配给一个新盒子,并且应该释放前一个盒子和引用的堆结构。
【问题讨论】:
-
看看这段代码:Rust playground link。也许您会发现它对您的情况很有用。
-
我明白了,@red75prime,您正在使用 Option 并采取分离值。太完美了,我完全忽略了这一点。我认为那会奏效!我的分支是不同的:我没有左/右选项,而是空节点和“有价值”节点。但是我仍然可以使用 Option 来获取值并将其放置在其他地方。非常感谢,考虑创建一个答案,我会完全接受。
-
正如stackoverflow.com/questions/16504643/… 中解释的那样,Option 不会为指针增加额外的大小,因此 Option
> 与 Box 一样小。根本不是多余的东西。很高兴知道!这样我就可以在需要“典型”指针时使用 Option > ,并且可以获取该值并移动它。 -
另外,在我的代码中,我可以添加一个类似
take的方法来返回 val、left、right 值并将自身转换为 None。那也行。我想我会实现它只是为了确认......然后采用标准的 Option 方式。 -
请务必注意,
Option并没有什么神奇之处。不向指针添加额外大小(AFAIK)的优化也适用于等效布局的其他枚举。同样,take方法可以是 implemented 使用安全代码。
标签: data-structures struct tree rust