2017-07-04 49 views
3

我对Rust很新,想要实现一个AVL树。盒装嵌套结构的访问值

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

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

在实现的平衡功能之一,我面临着一些问题,所有权和借贷。

我想写一个函数,它需要一个AvlTree<T>并返回另一个AvlTree<T>。我第一次尝试这样的:正确

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     

我想,我是理解的错误消息,在解构:

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 
    } 
} 

即使这个小例子,编译器返回错误AvlTree::Node将取消树示例的所有权。我怎样才能防止这种情况发生?我已经尝试了各种各样的东西,并且(de-)引用了tree-变量只是为了面对更多的错误。

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

回答

3

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变种,但也许其他人会给予你一些额外的想法。

+0

这就像一个魅力,谢谢你! – lschuermann