【发布时间】:2016-06-30 04:57:34
【问题描述】:
我正在尝试构建和遍历 DAG。似乎有两种可行的方法:将Rc<RefCell<Node>> 用于边缘,或者使用竞技场分配器和一些unsafe 代码。 (See details here.)
我选择前者,但难以将图遍历到其边缘,因为子节点的任何借用都依赖于其父节点的借用:
use std::cell::RefCell;
use std::rc::Rc;
// See: https://aminb.gitbooks.io/rust-for-c/content/graphs/index.html,
// https://github.com/nrc/r4cppp/blob/master/graphs/src/ref_graph.rs
pub type Link<T> = Rc<RefCell<T>>;
pub struct DagNode {
/// Each node can have several edges flowing *into* it, i.e. several owners,
/// hence the use of Rc. RefCell is used so we can have mutability
/// while building the graph.
pub edge: Option<Link<DagNode>>,
// Other data here
}
// Attempt to walk down the DAG until we reach a leaf.
fn walk_to_end(node: &Link<DagNode>) -> &Link<DagNode> {
let nb = node.borrow();
match nb.edge {
Some(ref prev) => walk_to_end(prev),
// Here be dragons: the borrow relies on all previous borrows,
// so this fails to compile.
None => node
}
}
我可以修改引用计数,即
fn walk_to_end(node: Link<HistoryNode>) -> Link<HistoryNode> {
let nb = node.borrow();
match nb.previous {
Some(ref prev) => walk_to_end(prev.clone()),
None => node.clone()
}
}
但是每次遍历一个节点时增加引用计数似乎是相当的 hack。这里的惯用方法是什么?
【问题讨论】:
-
你读过这个cglab.ca/~abeinges/blah/too-many-lists/book/… 吗?虽然是关于
Rc队列,但是真的可以帮到你。 -
...如果我正确阅读了该部分,那么作者首先遇到了我遇到的同样问题并放弃了。也就是说,“Rc
真的真的让我们失望了。” -
@MattKline:这实际上是“无论如何,那是我放弃了 Iter 和 IterMut。我们可以做到,但是呃。”,所以 Gankro 认为这是可能的,但可能并不优雅。
-
是啊,看来
Rc<RefCell>没有办法
标签: rust lifetime directed-acyclic-graphs graph-traversal