enums - 在盒装嵌套结构中访问值

标签 enums rust avl-tree ownership

我是 Rust 的新手,想实现一个 AVL 树。

我正在使用以下枚举来表示我的树:

enum AvlTree<T> {
    Leaf,
    Node {
        left: Box<AvlTree<T>>,
        right: Box<AvlTree<T>>,
        value: T
    }
}

在实现其中一项余额功能时,我遇到了一些与所有权和借用有关的问题。

我正在尝试编写一个函数,它需要一个 AvlTree<T>并返回另一个 AvlTree<T> .我的第一次尝试是这样的:

fn balance_ll(tree: AvlTree<T>) -> AvlTree<T> {
    if let AvlTree::Node {left: t, right: u, value: v} = tree {
        if let AvlTree::Node {left: ref tl, right: ref ul, value: ref vl} = *t {
            AvlTree::Leaf // Return a new AvlTree here
        } else {
            tree
        }
    } else {
        tree
    }
}

即使是这个最小的例子,编译器也会返回一个错误:

error[E0382]: use of partially moved value: `tree`             
  --> avl.rs:67:17             
   |                           
63 |         if let AvlTree::Node {left: t, right: u, value: v} = tree {                                                       
   |                                     - value moved here    
...                            
67 |                 tree      
   |                 ^^^^ value used here after move           
   |                           
   = note: move occurs because `(tree:AvlTree::Node).left` has type `std::boxed::Box<AvlTree<T>>`, which does not implement the `Copy` trait                  

我认为,我正确理解了错误消息,在解构 AvlTree::Node 时将带走树示例的所有权。我怎样才能防止这种情况发生?我已经尝试了各种方法并(取消)引用了 tree -变量只是为了面对更多的错误。

此外,我想使用一些提取的值,例如 u , tlvl在新结构中。这可能吗?您能否提供一个最小的例子来做到这一点?执行该函数后,我不需要访问旧树。

最佳答案

I think, I'm understanding the error message correctly, in that destructuring the AvlTree::Node will take away the ownership of the tree example.

是的。如果之后您仍然需要能够使用 tree,则需要复制它:

#[derive(Clone)]
enum AvlTree<T> {...}

fn balance_ll<T: Clone>(tree: AvlTree<T>) -> AvlTree<T> {
    let copy = tree.clone();

    if let AvlTree::Node { left: t, right: u, value: v } = tree {
        if let AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = *t {
            AvlTree::Leaf // Return a new AvlTree here
        } else {
            copy
        }
    } else {
        tree
    }
}

或者使用可以快速释放其所有权的辅助函数——但我认为没有盒子模式是不可能的:

#![feature(box_patterns)]

impl<T> AvlTree<T> {
    fn is_left_node(&self) -> bool {
        if let &AvlTree::Node { left: ref t, right: ref u, value: ref v } = self {
            if let &box AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = t {
                true
            } else {
                false
            }
        } else {
            false
        }
    }
}

fn balance_ll<T>(tree: AvlTree<T>) -> AvlTree<T> {
    if tree.is_left_node() {
        AvlTree::Leaf
    } else {
        tree
    }
}

由于您可能想要使用解构值,您可能更喜欢 clone 变体,但也许另一个会给您一些额外的想法。

关于enums - 在盒装嵌套结构中访问值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44904214/

相关文章:

java - 创建一个具有通用枚举字段的类。用于获取枚举值的枚举字段

multithreading - 什么时候或为什么我应该使用 Mutex 而不是 RwLock?

generics - 编写没有大量样板类型约束的通用浮点代码

rust - 当我可以使用 Cell 或 RefCell 时,我应该选择哪个?

c++ - AVL Tree - 计算 N_Nodes 按位置打印元素 c++

java - Java 函数式接口(interface)的单例作为枚举

c# - 使用枚举和 |作为字典键

swift - 在 Swift 中获取带有字符串的枚举

python - None 对象的返回值

data-structures - 给定多个节点,在AVL树中查找最小和最大高度?