rust 如何在不移动根节点的情况下对函数中的二叉树进行预排序?

3mpgtkmj  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(116)

我是Rust的新手,在阅读了官方Rust Book的一些章节后,我开始编写一些数据结构的东西。我选择创建一个简单的二叉树并执行两次简单的预排序。所以我写了一个简单的程序:

struct TreeNode {
    val: i32,
    left: Option<Box<TreeNode>>,
    right: Option<Box<TreeNode>>,
}
impl TreeNode {
    fn new(val: i32, left: Option<Box<TreeNode>>, right: Option<Box<TreeNode>>) -> TreeNode {
        TreeNode { val, left, right }
    }
}
fn main() {
    let root = TreeNode::new(
        120,
        Some(Box::new(TreeNode::new(
            150,
            Some(Box::new(TreeNode::new(180, None, None))),
            Some(Box::new(TreeNode::new(40, None, None))),
        ))),
        Some(Box::new(TreeNode::new(
            110,
            Some(Box::new(TreeNode::new(144, None, None))),
            None,
        ))),
    );
    pre_order(Some(Box::new(root)));
    pre_order(Some(Box::new(root)));
}
fn pre_order(root: Option<Box<TreeNode>>) {
    match root {
        None => {
            return;
        }
        Some(root_node) => {
            println!("{} ", root_node.val);
            pre_order(root_node.left);
            pre_order(root_node.right);
        }
    }
}

这个程序无法编译,因为第一个前序函数已经移动了根节点,所以第二个函数什么也没有得到。这是不对的。前序函数不应该吃它的根节点。我知道通过引用传递参数可以防止函数发生这种情况。所以我添加了一个引用...在什么之前?选项?盒子?树节点?我决定把它们都添加进去。所以我修改了函数如下:

fn pre_order(root: &Option<&Box<&TreeNode>>) {
    match root {
        None => {
            return;
        }
        Some(root_node) => {
            println!("{} ", root_node.val);
            pre_order(&&&root_node.left);
            pre_order(&&&root_node.right);
        }
    }
}

并改变了我称呼它的方式:

pre_order(&Some(&Box::new(&root)));
pre_order(&Some(&Box::new(&root)));

但是,检查工具警告我:

error[E0308]: mismatched types
  --> src/main.rs:35:23
   |
35 |             pre_order(&&&root_node.left);
   |             --------- ^^^^^^^^^^^^^^^^^ expected enum `Option`, found reference
   |             |
   |             arguments to this function are incorrect
   |
   = note: expected reference `&Option<&Box<&TreeNode>>`
              found reference `&&&Option<Box<TreeNode>>`
note: function defined here
  --> src/main.rs:28:4
   |
28 | fn pre_order(root: &Option<&Box<&TreeNode>>) {
   |    ^^^^^^^^^ ------------------------------

error[E0308]: mismatched types
  --> src/main.rs:36:23
   |
36 |             pre_order(&&&root_node.right);
   |             --------- ^^^^^^^^^^^^^^^^^^ expected enum `Option`, found reference
   |             |
   |             arguments to this function are incorrect
   |
   = note: expected reference `&Option<&Box<&TreeNode>>`
              found reference `&&&Option<Box<TreeNode>>`
note: function defined here
  --> src/main.rs:28:4
   |
28 | fn pre_order(root: &Option<&Box<&TreeNode>>) {
   |    ^^^^^^^^^ ------------------------------

For more information about this error, try `rustc --explain E0308`.

我很困惑.我怎么可能改变类型&&&Option<Box<TreeNode>>&Option<&Box<&TreeNode>>?我不认为我这样做是正确的.我应该添加引用的哪一部分?选项,框或TreeNode?如何设计的pre_order函数,这样我就可以传递树节点的引用递归而不实际消耗它?我需要Rc,Refcell,寿命说明符或任何高级功能来做到这一点?

wwtsj6pe

wwtsj6pe1#

要解决这个问题,你需要理解装箱一个值也会将它移动到一个盒子中,也就是说,你不能两次装箱或 Package 一个选项相同的值(在这种情况下是root)。快速的解决方案是在创建时立即 Package 根:

let root = Some(Box::new(TreeNode::new(/*...*/)));
pre_order(&root);
pre_order(&root);

并将引用传递给函数:

fn pre_order(root: &Option<Box<TreeNode>>) {
    match root {
        None => {
            return;
        }
        Some(root_node) => {
            println!("{} ", root_node.val);
            pre_order(&root_node.left);
            pre_order(&root_node.right);
        }
    }
}

Playground

相关问题