Graph 自有竞技场数据结构

Graph 自有竞技场数据结构,graph,rust,lifetime,ownership,Graph,Rust,Lifetime,Ownership,我想建模一个非常大(节点数量)的图,它由许多非常大(内存方面)的节点组成。由于节点非常大,我只想存储它们一次,并将借用的内容传递给它们,因此概念上类似于这样: struct Graph<'a> { nodes: Vec<Node<'a>>, } struct Node<'a> { edges: HashMap<String, &'a Node>, // ...lots of other data...

我想建模一个非常大(节点数量)的图,它由许多非常大(内存方面)的节点组成。由于节点非常大,我只想存储它们一次,并将借用的内容传递给它们,因此概念上类似于这样:

struct Graph<'a> {
    nodes: Vec<Node<'a>>,
}

struct Node<'a> {
    edges: HashMap<String, &'a Node>,
    // ...lots of other data...
}

这在语义上可以用Rust来表示吗?

一个简单的解决方案是使用板条箱。它包含一个带有
fn alloc(&self,T)->&mut T T
方法的
Arena
类型

另一个简单的解决方案是使用索引而不是引用(并且永远不要从
Vec
中删除,因为这会使索引无效)。在64位平台上,使用32位索引可以减少一些字节


但是,这两种解决方案都无法删除节点。您可以停止引用它们,但它们仍然存在于内存中,因此将它们用于动态图(节点来来去去去的地方)需要更多的工作。在这种情况下,我的建议是定期从一个新的竞技场创建一个新的图克隆(不要复制未使用的节点),这类似于使用移动垃圾收集器,如果自动化程度较低的话。

一个简单的解决方案是使用板条箱。它包含一个带有
fn alloc(&self,T)->&mut T T
方法的
Arena
类型

另一个简单的解决方案是使用索引而不是引用(并且永远不要从
Vec
中删除,因为这会使索引无效)。在64位平台上,使用32位索引可以减少一些字节


但是,这两种解决方案都无法删除节点。您可以停止引用它们,但它们仍然存在于内存中,因此将它们用于动态图(节点来来去去去的地方)需要更多的工作。在这种情况下,我的建议是定期从一个新的竞技场创建一个新的图克隆(不要复制未使用的节点),这类似于使用一个移动垃圾收集器,如果自动化程度较低的话。

搜索“竞技场”会提供许多结果。一个这样的板条箱是。我也不能使用类似于
Rc
的东西,因为图形有循环。-不完全正确;当您有循环数据时,可以引入引用。有一个例子。@Shepmaster
类型化竞技场
实现允许我获得借用,但这些借用绑定到一个
&mut
生存期,我无法连接到竞技场的生存期。不过,我会尝试使用弱引用。搜索“竞技场”会得到很多结果。一个这样的板条箱是。我也不能使用类似于
Rc
的东西,因为图形有循环。-不完全正确;当您有循环数据时,可以引入引用。有一个例子。@Shepmaster
类型化竞技场
实现允许我获得借用,但这些借用绑定到一个
&mut
生存期,我无法连接到竞技场的生存期。不过,我会尝试使用弱引用。在64位平台上,使用32位索引可以减少一些字节。-这是否需要在
u32
usize
之间进行多次强制转换?@Shepmaster:嗯,在硬件层面上,当然需要强制转换;但是,在软件级别,如果向量正确地封装了访问函数,使用的是
u32
,那么您应该只获得一个或两个
,作为usize
@MatthieuM。你能演示一下
typed arena
如何让我构建一个图形,让我将该图形封装在
struct
中吗?@MatthieuM。(我以前使用过
类型化竞技场
,但我只让它在一个堆栈框架中工作)@dflemstr:我建议
类型化竞技场
,因为你说的是竞技场,但是竞技场创建的物品借用了上述竞技场(因为你不能在竞技场死亡后参考该物品)在Rust中,兄弟姐妹间的借用关系是不允许的,因此竞技场本身也不会成为图表的一部分。我不认为这是一个很大的问题(只要你对生命有一个上限)。如果必须成为图形的一部分,那么
Vec
+索引解决方案更容易。在64位平台上,使用32位索引可以减少一些字节。-这是否需要在
u32
usize
之间进行多次强制转换?@Shepmaster:嗯,在硬件层面上,当然需要强制转换;但是,在软件级别,如果向量正确地封装了访问函数,使用的是
u32
,那么您应该只获得一个或两个
,作为usize
@MatthieuM。你能演示一下
typed arena
如何让我构建一个图形,让我将该图形封装在
struct
中吗?@MatthieuM。(我以前使用过
类型化竞技场
,但我只让它在一个堆栈框架中工作)@dflemstr:我建议
类型化竞技场
,因为你说的是竞技场,但是竞技场创建的物品借用了上述竞技场(因为你不能在竞技场死亡后参考该物品)在Rust中,兄弟姐妹间的借用关系是不允许的,因此竞技场本身也不会成为图表的一部分。我不认为这是一个很大的问题(只要你对生命有一个上限)。如果必须成为图形的一部分,则
Vec
+索引解决方案更容易。
struct Graph<'a> {
    nodes: Arena<'a, Node<'a>>,
}

struct Node<'a> {
    edges: HashMap<String, &'a Node>,
}

impl<'a, A> Arena<'a, A> {
    fn own(&self, a: A) -> &'a A {
        // magic
    }
}

impl<'a, A> Drop for Arena<'a, A> {
    fn drop(&'a mut self) {
        // magic
    }
}