Graph 结构中的可变向量
我正在尝试一种在Rust中工作的图聚类算法。代码的一部分是带有邻接列表表示的Graph 结构中的可变向量,graph,rust,Graph,Rust,我正在尝试一种在Rust中工作的图聚类算法。代码的一部分是带有邻接列表表示的WeightedGraph数据结构。核心将如下所示(用Python显示以明确我要做的事情): 类边(对象): 定义初始值(自身、目标、重量): self.target=目标 自重 类权重图(对象): 定义初始大小(自身、初始大小): self.adjancy_list=[[]表示范围内的i(初始_大小)] self.size=初始尺寸 self.edge\u计数=0 def添加_边缘(自身、源、目标、重量): self.
WeightedGraph
数据结构。核心将如下所示(用Python显示以明确我要做的事情):
类边(对象):
定义初始值(自身、目标、重量):
self.target=目标
自重
类权重图(对象):
定义初始大小(自身、初始大小):
self.adjancy_list=[[]表示范围内的i(初始_大小)]
self.size=初始尺寸
self.edge\u计数=0
def添加_边缘(自身、源、目标、重量):
self.adjacence_list[source].append(边(目标,权重))
self.edge_计数+=1
因此,邻接列表包含一个n
数组的数组:图中的每个节点对应一个数组。内部数组保存该节点的相邻节点,表示为边
(目标
节点编号和双权重
)
我试图将整件事转化为锈迹,结果如下:
struct Edge {
target: uint,
weight: f64
}
struct WeightedGraph {
adjacency_list: ~Vec<~Vec<Edge>>,
size: uint,
edge_count: int
}
impl WeightedGraph {
fn new(num_nodes: uint) -> WeightedGraph {
let mut adjacency_list: ~Vec<~Vec<Edge>> = box Vec::from_fn(num_nodes, |idx| box Vec::new());
WeightedGraph {
adjacency_list: adjacency_list,
size: num_nodes,
edge_count: 0
}
}
fn add_edge(mut self, source: uint, target: uint, weight: f64) {
self.adjacency_list.get(source).push(Edge { target: target, weight: weight });
self.edge_count += 1;
}
}
因此,有两个主要问题:
1。如何让add\u edge
方法发挥作用?
我认为WeightedGraph应该拥有它的所有内部数据(如果我错了,请纠正我)。但是为什么add_edge
不能修改图形自身的数据呢
2。~Vec
是表示在每个元素中包含动态列表的可变大小数组/列表的正确方法吗?
本教程还提到了~[int]
作为向量语法,那么它应该是:~[~[Edge]]]
?或者Vec
和~[Edge]
之间有什么区别?如果我应该使用~[~[Edge]]
,那么我将如何构造/初始化内部列表?(目前,我尝试使用Vec::from_fn
)
get
仅返回不可变引用,如果要修改数据,必须使用get_mut
Vec
,Vec是正确的使用方式,~[]
在过去是用于此目的的,但现在意味着其他东西(或将要,不确定是否已经更改)您还必须更改
add_edge
的签名以获取&mut self
,因为现在您正在将self
的所有权移动到add_edge
,这不是您想要的权重图确实拥有其所有内部数据,但即使您拥有某些内容,也必须选择对其进行变异get
为您提供了一个&
指针,要进行变异,您需要一个&mut
指针Vec::get_mut
将为您提供:self.adjacence_list.get_mut(源代码)。push(…)
关于
~Vec
和~[Edge]
:过去(直到最近,~[T]
表示一个T
的可增长向量,与其他任何类型的~.
不同,这个特殊情况被删除,~[T]
现在只是一个指向T
-切片的唯一指针,即,指向内存中一组T
s的指针,没有任何增长能力Vec
现在是可增长的向量类型
注意,它是Vec
,不是~Vec
;~
过去是向量语法的一部分,但这里它只是一个普通的唯一指针,表示完全不必要的间接寻址和分配。您需要邻接列表:Vec
。Vec
是一种成熟的具体类型(三重数据、长度、容量
,如果这对您有任何意义的话),它封装了内存分配和间接寻址,您可以将其用作值。通过box
ing它,您将一无所获,并失去清晰度和性能
您还有另一个(次要)问题:fn add_-edge(mut-self,…)
,就像fn add_-edge(self,…)
,意思是“按值获取self
”。由于邻接列表
成员是线性类型(它可以是drop
ped,它被移动而不是隐式复制),因此WeightedGraph
也是线性类型。以下代码将失败,因为第一个add_edge
调用消耗了图形
let g = WeightedGraph::new(2);
g.add_edge(1, 0, 2); // moving out of g
g.add_edge(0, 1, 3); // error: use of g after move
您想要
&mut self
:允许self
变异,但不要拥有它/不要移动它。非常感谢您的详细回答!关于~Vec
部分:我仍然有点困惑,因为本教程包含使用Cons(u32,~list)
的链表代码(在第9.1节框中)。这让我觉得在另一个结构中引用structs/enum/types需要~
。那么,链表的~
仅仅是因为递归方面吗?那么什么是不能直接用作值的“非具体”类型呢?“这个特例被删除了,~[T]现在只是一个指向T片的唯一指针”只是一个迂腐的观点:表示方式的变化还没有发生,所以它仍然表示为一个可增长的向量,但是所有的增长方法(.push
等等)已被删除。希望表示法很快就会改变。@MartinS.,是的,~
的存在只是为了允许递归。本教程详细解释了指针。目前不能直接用作值的“非具体”类型有[T]
和T
,其中T
是一个特征。也就是说,您不能使用没有指针的[T]
和trait对象,因为它们的大小未知。教程中也解释了这一点。@dbaupp我知道DST转换尚未完成。但我认为,到目前为止,大家都同意:(1)新的心理模型至少符合API;(2)将DST后的现状描述为现状只是一个暂时的谎言,有助于理解。
let g = WeightedGraph::new(2);
g.add_edge(1, 0, 2); // moving out of g
g.add_edge(0, 1, 3); // error: use of g after move