DAGを作成してトラバースしようとしています。 2つの実現可能なアプローチがあるように思われる:エッジには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()
}
}
を参照してください。ただし、ノードを通過するたびに参照カウントが大幅に増加します。ここでの慣用的なアプローチは何ですか?
このhttp://cglab.ca/~abeinges/blah/too-many-lists/book/fourth-iteration.html#iterをお読みください。それは 'Rc'キューに関するものですが、実際にあなたを助けることができます。 – aSpex
...私が正しくセクションを読んでいるのであれば、著者は私が抱えていると同じ問題に直面していた。 「Rcは本当に本当に本当に最後に失敗しました。 –
@MattKline:それは実際には "とにかく、私はIterとIterMutをあきらめている。私たちはそれらをやることはできるが、うーん。"そう、Gankroの考え方は可能だが、それほどエレガントではないかもしれない。 –