2017-07-04 167 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