广度优先搜索和生命周期

时间:2016-11-03 03:21:36

标签: algorithm rust

我想编写一个在二叉树上使用广度优先搜索的函数来按顺序打印节点值:

use std::collections::VecDeque;
use std::ops::Deref;

struct BinarySearchNode<'a> {
    value: &'a str,
    key: i32,
    left: Option<Box<BinarySearchNode<'a>>>,
    right: Option<Box<BinarySearchNode<'a>>>,
}

impl<'a> BinarySearchNode<'a> {
    pub fn print(&self) -> String {
        let mut queue = VecDeque::new();
        let mut output = String::new();
        queue.push_back(&self);

        while let Some(ref current) = queue.pop_front() {
            if let Some(left_node) = current.left {
                queue.push_back(&left_node.deref());
            }
            if let Some(right_node) = current.right {
                queue.push_back(&right_node.deref());
            }

            output = output + current.value + "\n";
        }

        output
    }
}

fn main() {}

我收到错误

error: borrowed value does not live long enough
  --> src/main.rs:19:34
   |
19 |                 queue.push_back(&left_node.deref());
   |                                  ^^^^^^^^^^^^^^^^^ does not live long enough
   |
note: reference must be valid for the block suffix following statement 0 at 13:40...
  --> src/main.rs:13:41
   |
13 |         let mut queue = VecDeque::new();
   |                                         ^
note: ...but borrowed value is only valid for the statement at 19:16
  --> src/main.rs:19:17
   |
19 |                 queue.push_back(&left_node.deref());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
  --> src/main.rs:19:17
   |
19 |                 queue.push_back(&left_node.deref());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `left_node` does not live long enough
  --> src/main.rs:19:34
   |
19 |                 queue.push_back(&left_node.deref());
   |                                  ^^^^^^^^^
   |
note: reference must be valid for the block suffix following statement 0 at 13:40...
  --> src/main.rs:13:41
   |
13 |         let mut queue = VecDeque::new();
   |                                         ^
note: ...but borrowed value is only valid for the if let at 18:12
  --> src/main.rs:18:13
   |
18 |             if let Some(left_node) = current.left {
   |             ^

error: borrowed value does not live long enough
  --> src/main.rs:22:34
   |
22 |                 queue.push_back(&right_node.deref());
   |                                  ^^^^^^^^^^^^^^^^^^ does not live long enough
   |
note: reference must be valid for the block suffix following statement 0 at 13:40...
  --> src/main.rs:13:41
   |
13 |         let mut queue = VecDeque::new();
   |                                         ^
note: ...but borrowed value is only valid for the statement at 22:16
  --> src/main.rs:22:17
   |
22 |                 queue.push_back(&right_node.deref());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
  --> src/main.rs:22:17
   |
22 |                 queue.push_back(&right_node.deref());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `right_node` does not live long enough
  --> src/main.rs:22:34
   |
22 |                 queue.push_back(&right_node.deref());
   |                                  ^^^^^^^^^^
   |
note: reference must be valid for the block suffix following statement 0 at 13:40...
  --> src/main.rs:13:41
   |
13 |         let mut queue = VecDeque::new();
   |                                         ^
note: ...but borrowed value is only valid for the if let at 21:12
  --> src/main.rs:21:13
   |
21 |             if let Some(right_node) = current.right {
   |             ^

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:18:38
   |
18 |             if let Some(left_node) = current.left {
   |                         ---------    ^^^^^^^ cannot move out of borrowed content
   |                         |
   |                         hint: to prevent move, use `ref left_node` or `ref mut left_node`

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:21:39
   |
21 |             if let Some(right_node) = current.right {
   |                         ----------    ^^^^^^^ cannot move out of borrowed content
   |                         |
   |                         hint: to prevent move, use `ref right_node` or `ref mut right_node`

我需要deref()因为简单地使用运算符*导致类型不匹配,因为它预期引用而不是框。似乎那些取消引用略有不同,至少在稳定中我也无法解构它。

我知道这个值的范围是while循环,并且活不够长,不能在VecDeque中(如果这是作业的正确数据结构),但我是不确定延长寿命的最佳方式是什么,或者是否只是一种更好的方式来编写整个事情,因为它感觉有点复杂。

我的主要问题是我不知道从哪里开始重构这段代码而且我很难找到在Rust中的二叉树上执行广度优先搜索的示例以获取模式。

2 个答案:

答案 0 :(得分:1)

您的主要问题在于此行(以及right版本):

if let Some(left_node) = current.left

这会尝试将<{1}}中包含的值移动到右侧的模式中。问题是current.leftcurrent.left。当您从Option<Box<BinarySearchNode<'a>>>移出Box时,会current没有current的有效值!在将来访问该值会导致不良行为。

相反,您需要将值保留在原来的位置,而是采用引用。两种主要方法是使用left模式修饰符:

ref

或致电as_ref

if let Some(ref left_node) = current.left

这是完整的代码:

if let Some(left_node) = current.left.as_ref()

答案 1 :(得分:-1)

试试这个:

pub fn print(&self) -> String {
    let mut queue = VecDeque::new();
    let mut output = String::new();

    if let Some(ref left_node) = self.left {
        queue.push_back(left_node);
    }
    if let Some(ref right_node) = self.right {
        queue.push_back(right_node);
    }

    while let Some(ref current) = queue.pop_front() {
        if let Some(ref left_node) = current.left {
            queue.push_back(left_node);
        }
        if let Some(ref right_node) = current.right {
            queue.push_back(right_node);
        }

        output = output + current.value + "\n";
    }

    output
}