与借用检查器搏斗

3

我刚接触Rust。作为一种学习练习,我正试图制作一个基本二叉树。这是我目前的进展:

fn main() {
    let data = vec![6,1,2,3,4,5];

    let mut root = Node::<i32> { value: data[0], left: None, right: None };

    for val in data {
        createAndInsert::<i32>(&root, val);
    }
    println!("Root value: {}", root.value); 
}

fn createAndInsert<T: PartialOrd>(mut root: &Node<T>, value: T) {
    let mut n = Node::<T> { value: value, left: None, right: None };
    insert::<T>(&root, &n);
}

fn insert<T: PartialOrd>(mut curr: &Node<T>, new: &Node<T>) {
    if new.value > curr.value {
        match curr.right {
            Some(ref n) => insert(n, new),
            None => curr.right = Some(Box::new(*new))
        }
    } else {
        match curr.left {
            Some(ref n) => insert(n, new),
            None => curr.left = Some(Box::new(*new))
        }
    }
}

struct Node<T: PartialOrd> {
    value: T,
    left: Option<Box<Node<T>>>,
    right: Option<Box<Node<T>>>,
}

我遇到的编译器错误:
test.rs:21:48: 21:52 error: cannot move out of borrowed content
test.rs:21             None => curr.right = Some(Box::new(*new))
                                                          ^~~~
test.rs:26:47: 26:51 error: cannot move out of borrowed content
test.rs:26             None => curr.left = Some(Box::new(*new))
                                                         ^~~~
test.rs:21:21: 21:54 error: cannot assign to immutable field `curr.right`
test.rs:21             None => curr.right = Some(Box::new(*new))
                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.rs:26:21: 26:53 error: cannot assign to immutable field `curr.left`
test.rs:26             None => curr.left = Some(Box::new(*new))
                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 4 previous errors

我陷入了所有引用、变异、&和* 的纠缠中,不确定如何摆脱。我错在哪里了?


可能是在借用泛型类型时无法移出已借用的内容的重复问题。 - oli_obk
2个回答

5
你有两个问题:
  • 无法移出借用的上下文:请参见Cannot move out of borrowed content when borrowing a generic type了解其解释。

  • 无法分配给不可变字段:你只有一个&Node<T>;要修改Node,你需要一个&mut Node<T>。模式中的mut curr仅使绑定可变,这意味着你可以将新值赋给curr。但是,你无法修改curr所指的内容。在整个代码中传播&-to-&mut转换就可以解决问题。


3

因为你是 Rust 的新手,可能会帮助你看到我如何编写:

struct Node<T> {
    value: T,
    left: Option<Box<Node<T>>>,
    right: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    fn new(x: T) -> Node<T> {
        Node { value: x, left: None, right: None }
    }
    fn boxed(x: T) -> Box<Node<T>> {
        Box::new(Node::new(x))
    }
}

fn insert<T: PartialOrd>(root: &mut Option<Box<Node<T>>>, new: Box<Node<T>>) {
    if let Some(ref mut rbx) = *root {
        if new.value < rbx.value {
            insert(&mut rbx.left, new);
        } else {
            insert(&mut rbx.right, new);
        }
    } else {
        *root = Some(new);
    }
}

fn main() {
    let data = vec![6,1,2,3,4,5];
    let mut root = None;
    for val in data {
        insert(&mut root, Node::boxed(val));
    }
    println!("Root value: {}", root.unwrap().value); 
}

我知道这只是一种练习,但请记住,这种数据结构不应该超过一定的树深度,否则在节点递归释放时可能会导致堆栈溢出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接