当两个顶点具有相似的属性(内部或捆绑)时,它们是同一个顶点,并且 add_vertex 不应该将它与新索引一起添加,不应该只是将索引返回到现有的索引吗? – Bruce 11 mins ago
如果您有两个具有“相似属性”的顶点,您决定是否要添加另一个具有这些属性的顶点。
如果我们有一个带有一些 bundled_properties 的顶点,然后我们将它添加到图中,然后将一条边连接到它,如果有相似的顶点,这个顶点会重复吗?
您通过引用vertex_descriptors 添加边。没有办法“将边连接到顶点属性”。因此,add_edge 不能意外地使用某些属性创建新顶点。
注意:可能会造成混淆,因为使用vectorS² 作为顶点容器选择器可以让您通过引用可能不存在的顶点描述符来添加边。确实,这并没有“添加顶点”,而是“扩展了顶点 ID/描述符的有效域”。例如:
adjacency_list<> g;
add_edge(10, 11, g);
实际上并没有添加 12 个顶点。它扩展了顶点 id 域以包含值 11。 Live On Coliru
我们来看看add_vertex:
调用是add_vertex,它添加了一个顶点。事实上,您通常不会为它们插入属性,这只是为了方便。
两者之间没有根本区别:
vertex_descriptor v = add_vertex(g);
g[v] = vertexProperties;
还有
vertex_descriptor v = add_vertex(vertexProperties, g);
在这两种情况下,您都将始终获得一个新的、唯一的顶点描述符,并将其属性设置为特定值。
那为什么和add_edge有区别呢?
add_edge 真的不一样吗?与add_vertex 一样,两者没有区别:
vertex_descriptor from {/*...*/}, to {/*...*/};
edge_descriptor e = add_edge(from, to, g).first;
g[e] = edgeProperties;
还有
edge_descriptor e = add_edge(from, to, edgeProperties, g).first;
您会注意到两者(可能)都添加了一条边,返回其描述符,并且都将属性设置为特定值。
这里的重点是adjacency_list不知道或关心这些属性。它们为您添加信息,或对某些算法有用,但它们与adjacency_list 建模的图概念无关。
为什么add_edge有条件地加?
这是因为adjacency_list 使用的策略意味着需要检查的不变量:
- 如果您的边缘容器选择恰好是例如
setS,它的插入方式可能插入也可能不插入新边; adjacency_lists<> 只是将行为¹ 转发给 add_edge
- 如果您的
adjacency_list 也使用undirected 或bidirectional,这会在边上施加额外的约束(例如,防止在使用setS 的双向图中添加(a->b) 和(b->a) 作为边缘容器选择器)。
总结:
¹ 例如优雅地避免双刃
² 或可能的其他随机访问顶点容器选择器,它们具有作为隐式顶点id
的完整顶点描述符