如何建模复杂的递归数据结构(图形)?

时间:2015-02-19 14:24:51

标签: rust

我对Rust很感兴趣,现在我开始用这种语言开展我的第一个非平凡的项目。我仍然在完全理解借贷和终身概念方面遇到一些麻烦。

该应用程序是一个逻辑门模拟器,其中组件是递归定义的(就其他组件及其互连而言)。

我目前的计划是通过让Component组件拥有一个Components(它的子组件)的向量和一个描述这些组件之间的内部连接的Nets向量来实现这个,就像在C ++中一样:

pub struct Pin {
    name: String
}

pub struct Net<'a> {
    nodes: Vec<(&'a Component<'a>,&'a Pin)>
}

pub struct Component<'a> {
    sub_components: Vec<Box<Component<'a>>>,
    in_pins: Vec<Pin>,
    out_pins: Vec<Pin>,
    netlist: Vec<Net<'a>>
}

impl<'a> Component<'a> {
    pub fn new() -> Component<'a> {
        ...
    }

    pub fn add_subcomponent( & mut self, comp: Component<'a> ) {
        // -> &Box<Component<'a>> ??
        ....
    }
}

在C ++中,Net很容易实现为指向组件的指针数组,但我不确定在Rust中执行此操作的最佳方法,我想我应该使用借来的指针?或者有更好的方法吗?

考虑以下主要内容:

fn main() {
    let sub1 = Component::new();
    let sub2 = Component::new();
    let circuit = Component::new();

    circuit.add_subcomponent( sub1 );
    circuit.add_subcomponent( sub2 );
    // sub1 and sub2 are now empty...
}

如何配置电路以在sub1和sub2之间创建网络?我有add_subcomponent返回一个借用指向添加的组件的指针吗?还是盒子?

如果有人能指出我正确的方向,那就太好了。

非常感谢。

1 个答案:

答案 0 :(得分:8)

您不能代表安全生锈中的任意图形结构。

实现此模式的最佳方法是使用不安全的代码和原始指针,或者将此功能包装在安全API中的现有抽象,例如http://static.rust-lang.org/doc/master/std/cell/struct.RefCell.html

例如,典型的双向链表是:

struct Node {
  next: Option<Node>, // Each node 'owns' the next one
  prev: *mut Node     // Backrefs are unsafe
}

有很多“安全”的实现,你有类似的东西:

struct Node {
    id: u32,
    next: u32,
    prev: u32
}
struct Nodes {
  all:Vec<Node>,
  root:Option<Node>
}

这在技术上是'安全',但这是一种可怕的模式;它通过手动实现原始指针来打破所有安全规则。我强烈建议不要这样做。

您可以尝试使用引用,例如:

struct Container<'a> {
  edges:Vec<Edge<'a>>,
  pub root: Node
}

struct Node {
  children:Vec<Node>  
}

struct Edge<'a> {
  n1: &'a Node,
  n2: &'a Node
}

......但是你几乎会立刻绊倒到借用检查器的地狱。例如,当您删除节点时,借用检查器如何知道“边缘”中的关联链接不再有效?

虽然你可能能够定义结构,但填充它们会非常麻烦。

我知道这可能是一个非常不满意的答案;你可能会发现搜索github的'rust graph'和'rust tree'很有用,看看其他人做过的实现。

通常,它们会将子树的单一所有权强制实施为父对象。