Rust二叉树插入实现难度

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust二叉树插入实现难度相关的知识,希望对你有一定的参考价值。

我已经查看了很多主题,但是我找不到任何关于为什么我的代码不能编译的线索(除了当然的所有权问题),希望有人在这里可以帮助我。

我正在进行二叉树实现,其中一个函数是insert函数。这是我第一次在Rust编写代码,虽然我已多次查看文档,但我无法弄清楚以下代码中的所有权有什么问题(我只发布了,我希望所有相关的代码):

#[derive(Debug)]
struct Data {
    name: String,
    age: i32,
}

#[derive(Debug)]
struct Node {
    value: Data,
    left: Option<Box<Node>>,
    right: Option<Box<Node>>,
}

pub struct SortedContainer {
    root: Option<Box<Node>>,
}

impl SortedContainer {
    pub fn insert(&mut self, name: String, age: i32) {
        let d = Data {
            name: name,
            age: age,
        };
        let n = Node {
            value: d,
            left: None,
            right: None,
        };
        match self.root {
            Some(ref rootnode) => SortedContainer::node_insert(n, *rootnode),
            None => self.root = Some(Box::new(n)),
        }
    }
    fn node_insert(n: Node, mut n2: Box<Node>) {
        let i = SortedContainer::data_compare(&n.value, &n2.value);
        if i < 0 {
            match n2.right {
                Some(ref rightnode) => SortedContainer::node_insert(n, *rightnode),
                None => n2.right = Some(Box::new(n)),
            }
        } else if i > 0 {
            match n2.left {
                Some(ref leftnode) => SortedContainer::node_insert(n, *leftnode),
                None => n2.left = Some(Box::new(n)),
            }
        }
    }
    fn data_compare(d: &Data, d2: &Data) -> i32 {
        if d.age < d2.age {
            return -1;
        } else if d.age > d2.age {
            return 1;
        } else if d.name == d2.name {
            return 0;
        } else if d.name > d2.name {
            return 1;
        } else if d.name < d2.name {
            return -1;
        } else {
            return 0;
        }
    }
}

终端提供的错误是:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:31:67
   |
31 |             Some(ref rootnode) => SortedContainer::node_insert(n, *rootnode),
   |                                                                   ^^^^^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:39:72
   |
39 |                 Some(ref rightnode) => SortedContainer::node_insert(n, *rightnode),
   |                                                                        ^^^^^^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:44:71
   |
44 |                 Some(ref leftnode) => SortedContainer::node_insert(n, *leftnode),
   |                                                                       ^^^^^^^^^ cannot move out of borrowed content

它是否与Box或左/右分配有关?

答案

您正试图将您的盒装节点移出其封闭选项。这是不允许的,因为之后选项仍将由相应的父节点拥有。理论上你可以在选项上调用take来移动节点。 take将值移出选项并用None替换它,而不是让它“空”(不允许)。

但是,这将有效地将子节点与其各自的父节点分离。从插入新节点返回后,您必须重新连接它们:

fn node_insert(n: Node, mut n2: Box<Node>) -> Box<Node>{
    let i = SortedContainer::data_compare(&n.value, &n2.value);
    if i < 0 {
        n2.right = match n2.right.take() {
            Some(rightnode) => Some(SortedContainer::node_insert(n, rightnode)),
            None => Some(Box::new(n)),
        }
    } else if i > 0 {
        n2.left = match n2.left.take() {
            Some(leftnode) => Some(SortedContainer::node_insert(n, leftnode)),
            None => Some(Box::new(n)),
        }
    }
    n2
}

对于根节点也是如此:

self.root = match self.root.take() {
    Some(rootnode) => Some(SortedContainer::node_insert(n, rootnode)),
    None => Some(Box::new(n)),
}

另一种解决方案涉及将可变引用传递给节点而不是移动它们。这是有效的,因为实际上只需要沿着从根节点到应该插入新节点的叶节点的路径改变节点:

fn node_insert(n: Node, n2: &mut Node) {
    let i = SortedContainer::data_compare(&n.value, &n2.value);
    if i < 0 {
        match n2.right {
            Some(ref mut rightnode) => SortedContainer::node_insert(n, rightnode),
            None => n2.right = Some(Box::new(n)),
        }
    } else if i > 0 {
        match n2.left {
            Some(ref mut leftnode) => SortedContainer::node_insert(n, leftnode),
            None => n2.left = Some(Box::new(n)),
        }
    }
}

对于根节点也是如此:

match self.root {
    Some(ref mut rootnode) => SortedContainer::node_insert(n, rootnode),
    None => self.root = Some(Box::new(n)),
}

以上是关于Rust二叉树插入实现难度的主要内容,如果未能解决你的问题,请参考以下文章

二叉平衡树的实现(c语言编程)

二叉搜索树 Rust实现

平衡二叉树的定义及基本操作(查找插入删除)及代码实现

算法leetcode|剑指 Offer 27. 二叉树的镜像|226. 翻转二叉树(rust很强)

算法leetcode|剑指 Offer 27. 二叉树的镜像|226. 翻转二叉树(rust很强)

算法leetcode|剑指 Offer 27. 二叉树的镜像|226. 翻转二叉树(rust很强)