参考路径在树结构

时间:2016-06-10 14:30:16

标签: rust

我试图在遍历树时构建树结构并维护路径。

这里有一些代码:

use std::collections::VecDeque;

struct Node {
    children: VecDeque<Node>,
}

struct Cursor<'a> {
    path: VecDeque<&'a mut Node>,
}

impl<'a> Cursor<'a> {
    fn new(n: &mut Node) -> Cursor {
        let mut v = VecDeque::new();
        v.push_front(n);
        Cursor { path: v }
    }

    fn go_down(&'a mut self, idx: usize) -> bool {
        let n = match self.path[0].children.get_mut(idx) {
            None => return false,
            Some(x) => x
        };
        self.path.push_front(n);
        true
    }
}

我有两个问题。首先,编译器建议go_down() self参数中的生命周期说明符,但我不确定为什么它会修复报告的问题。

但是,即使进行了此更改,上述代码也无法编译,因为self.path被借用了两次。有没有办法保持树节点的路径而不写'#34;不安全&#34;码?

1 个答案:

答案 0 :(得分:1)

我最终遵循从this answerRecursive Data Structures in Rust的方法。我们的想法是你使用拥有的对象而不是引用来操作,并在遍历它时解构和重构树。

这是我最终得到的代码:

use std::collections::VecDeque;

enum Child { Placeholder, Node(Node) }

struct Node {
    children: Vec<Child>,
}

impl Node {
    fn swap_child(&mut self, idx: usize, c: Child) -> Option<Child> {
        match self.children.get(idx) {
            None => None,
            Some(_) => {
                self.children.push(c);
                Some(self.children.swap_remove(idx))
            }
        }
    }
}

struct Cursor {
    node: Node,
    parents: VecDeque<(Node, usize /* index in parent */)>,
}

enum DescendRes { OK(Cursor), Fail(Cursor) }
enum AscendRes  { Done(Node), Cursor(Cursor) }

impl Cursor {
    fn new(n: Node) -> Cursor {
        Cursor { node: n, parents: VecDeque::new() }
    }

    fn descent(mut self, idx: usize) -> DescendRes {
        match self.node.swap_child(idx, Child::Placeholder) {
            None => DescendRes::Fail(self),
            Some(Child::Placeholder) => panic!("This should not happen"),
            Some(Child::Node(child)) => {
                let mut v = self.parents;
                v.push_front((self.node, idx));
                DescendRes::OK(
                    Cursor { node: child, parents: v }
                )
            }
        }
    }

    fn ascend(mut self) -> AscendRes {
        match self.parents.pop_front() {
            None => AscendRes::Done(self.node),
            Some((mut parent, parent_idx)) => {
                match parent.swap_child(parent_idx, Child::Node(self.node)) {
                    Some(Child::Placeholder) => {
                        AscendRes::Cursor(
                            Cursor { node: parent, parents: self.parents }
                        )
                    },
                    _ => panic!("This should not happen")
                }
            }
        }
    }
}