最简单的 boost::adjacency_list
使用 std::size_t
作为底层 vertex_descriptor(索引)。
boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::directedS,
boost::no_property,
boost::no_property
> graph;
一旦我知道了顶点描述符,我就可以快速访问所需的顶点。
auto vertex = graph[idx]; // idx is the veretx descriptor
但是,当图发生变异时,无法保证 vertex_descriptor
保持稳定。
auto v0 = boost::add_vertex(graph);
auto v1 = boost::add_vertex(graph);
auto v2 = boost::add_vertex(graph);
boost::remove_vertex(v0, graph); // v1 and v2 are no longer valid
我希望能够快速找到特定的顶点 - 这意味着我希望避免遍历图结构来搜索我知道存在的顶点。
我的想法是,我可以使用 VertexListS 模板参数的不同选择器以某种方式调整 boost::adjacency_list
,这将允许我使用我自己提供的 vertex_descripor (索引)。
我探索了使用关联容器选择器(例如内置 boost::hash_mapS
)的可能性,但似乎我无法控制它在调用 add_vertex
时返回的确切 id。
我希望能够为每个顶点使用我自己的 id (vertex_descriptor)。
我会尝试用我希望能够工作的代码更清楚一点:
// the following type will serve as the vertex_descriptor:
using my_id_type = std::size_t;
struct MyVertex
{
my_id_type id;
// some other fields
}
// add vertices with unique identifiers that will also serve as the vertex_descriptors
boost::add_vertex(MyVertex{1111}, graph); // I expect this to return 1111
boost::add_vertex(MyVertex{2222}, graph);
boost::add_vertex(MyVertex{1234}, graph);
boost::remove_vertex(1111, graph); // I expect this to remove the first vertex
// access a specific vertex using its unique, stable descriptor:
auto vertex = graph[1234];
Can this be returned using boost::graph?
The simplest boost::adjacency_list
uses std::size_t
as the underlying vertex_descriptor (index).
boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::directedS,
boost::no_property,
boost::no_property
> graph;
Once I know the vertex descriptor, I can quickly access the desired vertex.
auto vertex = graph[idx]; // idx is the veretx descriptor
However, when the graph is mutated, there is no guarantee that the vertex_decriptor
will be stable.
auto v0 = boost::add_vertex(graph);
auto v1 = boost::add_vertex(graph);
auto v2 = boost::add_vertex(graph);
boost::remove_vertex(v0, graph); // v1 and v2 are no longer valid
I would like to be able to find a specific vertex quickly - meaning I wish to avoid traversing the graph structure in search of a vertex I know exists.
My thinking is that I can somehow tweak boost::adjacency_list
with a different selector to the VertexListS template parameter, that will allow me to use my own provided vertex_descripor (index).
I explored the possibility of using an associative container selector such as the builtin boost::hash_mapS
but it seems I can't control the exact id it returns when calling add_vertex
.
I would like to be able to use my own id (vertex_descriptor) for each vertex.
I'll try to be a bit more clear, with the code I wish would work:
// the following type will serve as the vertex_descriptor:
using my_id_type = std::size_t;
struct MyVertex
{
my_id_type id;
// some other fields
}
// add vertices with unique identifiers that will also serve as the vertex_descriptors
boost::add_vertex(MyVertex{1111}, graph); // I expect this to return 1111
boost::add_vertex(MyVertex{2222}, graph);
boost::add_vertex(MyVertex{1234}, graph);
boost::remove_vertex(1111, graph); // I expect this to remove the first vertex
// access a specific vertex using its unique, stable descriptor:
auto vertex = graph[1234];
Can this be achieved using boost::graph?
发布评论
评论(1)
对于 BGL,答案几乎总是“是”。它是现存最深刻的通用图书馆设计之一。
令我惊讶的是,
adjacency_list
的类型层次结构中出现了一些新内容。显然,现在有一个named_graph
mixin(实际上是maybe_name_graph
),它使用顶点束上的特征来检测“内部名称”。这意味着你可以接近。尽管顶点描述符不会成为您的 ID,但您可以进行 O(1) 查找。并且该接口有一些便利,因此您可以编写:
注意:
id
类型与vertex_descriptor
类型相同(或者如果您的参数具有同样“远”的转换,则add_edge
的不明确重载)到任一)。vertex_index_t
或vertex_name_t
属性。步骤#1:图表
到目前为止,没有什么意外。我
other
只是为了显示它何时/如何获得默认构造的listS
因为它vertex_descriptor
(void*
),它与重载决策中的 id 类型 (size_t
) 不冲突步骤#2:名称特征
接下来我们向 BGL 教授内部顶点名称。
注意
我们当然可以硬-对第二个专业化中的已知进行编码:
通过引用返回 id非常 很重要。如果不这样做,会导致 UB 没有来自库/编译器的诊断
步骤#3 添加/查找顶点
现在您可以添加顶点。通过“名称”(您的
id
):或者您在问题中预期的老式方式:
重复添加没有效果:
存在不同的查找。
vertex_by_property
返回给定顶点束的可选
。它通过从传递的包中提取“内部名称”来实现这一点,因此包不需要包含 id 之外的任何其他状态:
虽然它感觉像一个实现细节,但实际的< code>multi_index_container 实现名称 ->描述符索引也公开了:
步骤#4添加边
这借用了上一个问题的一页:)
显然,您仍然可以通过顶点描述符添加边。
步骤#5其他操作
从之前的答案中借用更多页面:
完整演示
Live On Coliru< /a>
打印
旁注:
hash_mapS
会导致unordered_set, equal_to, allocator>
作为m_vertices
类型。The answer is nearly always "yes" with BGL. It's one of the most profoundly generic library designs in existence.
To my surprise, something new appeared in the type-hierarchy for
adjacency_list
. Apparently these days there's anamed_graph
mixin (actuallymaybe_name_graph
) which uses traits on the vertex bundle to detect an "internal name".This means you can get close. Though the vertex descriptor will not become your id, you can have O(1) lookup. And the interface has some conveniences, so you can write:
Notes:
add_edge
) if you make theid
type accidentally the same as thevertex_descriptor
type (or if your argument have equally "far" conversions to either).vertex_index_t
norvertex_name_t
property.Step #1: The Graph
So far no surprises. I
other
just to show when/how it gets default constructedlistS
because itvertex_descriptor
(void*
) which does not conflict with the id type (size_t
) in overload resolutionStep #2: Name Traits
Next we teach BGL about our Internal Vertex Name.
Note
We could of course hard-code the knowns in the second specialization:
It is very important to return the id by reference. Failing to do so leads to UB with no diagnostics from the library/compiler
Step #3 Adding/Finding Vertices
Now you can add vertices. Either by "name" (your
id
):Or the old-fashioned way you anticipated in the question:
Duplicate additions have no effect:
Different lookups exist. The
vertex_by_property
returns aoptional<vertex_descriptor>
given a vertex bundle.It does so by extracting the "internal name" from the bundle passed, so there is no need for the bundle to contain any other state outside the id:
Although it feels like an implementation detail, the actual
multi_index_container
implementing the name -> descriptor index is also exposed:Step #4 Adding Edges
That borrows a page from your previous question :)
Obviously, you can still add edges by vertex descriptors.
Step #5 Other Operations
Borrowing more pages from that previous answer:
Full Demo
Live On Coliru
Prints
Sidenote:
hash_mapS
leads tounordered_set<void*, hash<void*>, equal_to<void*>, allocator<void*>>
as them_vertices
type.