【问题标题】:C++ graph with removable nodes, accessible properties and reliable IDs具有可移动节点、可访问属性和可靠 ID 的 C++ 图
【发布时间】:2015-03-17 20:27:44
【问题描述】:

我正在尝试从专有图库迁移开源图库。

编辑:由于似乎很少有人知道 Boost Graph 的实际工作原理,如果您可以使用 LEMON Graph Library 提供解决方案,那也很好。

目前,我的顶点类型为Graph_Vertex*,并且可以有一个关联的void* 指针来存储相关信息。对于类型为Graph_Edge* 的边使用了类似的逻辑。我使用void*指针来存储我自己的结构Node_State,就是这样的

struct Node_State {
    std::string name;
    int id;
    // other stuff
};

根据我迄今为止对 BGL 的了解,我可以使用 adjacency_list 结构和 bundled properties 创建一个图形来指向我的 Node_State。然后,我将使用整数 顶点索引,而不是使用 顶点指针

我一直在查看tutorial 和一些questions here,这似乎是可能的。我正在考虑类似的事情

typedef adjacency_list < listS, vecS, bidirectionalS, Node_State> gr;

我会不时删除顶点的所有边。不太频繁,我也可以删除一个节点。这就是为什么我会选择listS, vecS

我想让为无向边创建此结构的第二个版本变得容易。我不确定bidirectionalS 是否是我的最佳选择。感谢您在这方面的意见。

还有另一个问题。现在,我可以使用外部 ma​​p 通过 name 或使用唯一整数 id 来查找每个顶点。

std::map<int, Graph_Vertex*> nodes_by_id;
std::map<std::string, Graph_Vertex*> nodes_by_name();

如果我删除了一个顶点,我只需要删除地图中的相应条目,一切都会继续进行。

据我了解,使用 BGL 实现这一点并不容易,因为删除一个顶点会触发所有具有更高 ID 的顶点的重新编号,并且还可能导致内部重新分配结构。所以再见 ids 和再见指针。

主要问题。 是否有可能创建一个 map&lt;name, node&gt;map&lt;index, node&gt; 以最小的调整(例如仅删除无效键)在节点删除中存活?如果不是,将节点映射到某个唯一标识符的最佳方法是什么?

一个选项可以使用internal properties。教程example在这里。

struct vertex_index_t { };
struct edge_index_t { };

struct vertex_name_t { };
struct edge_name_t { };

并保留一些外部结构

std::map<vertex_index_t, Graph_Vertex*> nodes_by_id;
std::map<vertex_name_t, Graph_Vertex*> nodes_by_name;
std::map<edge_index_t, Graph_Edge*> edges_by_id;
std::map<edge_name_t, Graph_Edge*> edges_by_name;

这将与我现在拥有的更加相似,并且需要对当前代码进行更少的更改。

我还没有真正理解vertex_index_t 是如何受到顶点移除的影响的,以及如何分配vertex_name_t。不过,如果这可行,类似的逻辑也可以使用 edge_index_tedge_name_t 应用于边缘。

结束。我需要一段工作代码来展示如何:

  • 添加顶点(带属性)
  • 添加弧(带属性)
  • 删除顶点
  • 移除圆弧

具备这些重要条件:

  • 能够按 id(int 或 string)索引顶点,以便轻松检索它们并访问它们的属性
  • 如果顶点被移除,ids 不能改变
  • 添加索引和属性不应使“查找连通分量”和“Dijkstra 搜索”等算法的运行更加困难

如果我能实现类似的目标,我会很高兴

Vertex* vertex0 = Graph.get_vertex_by_name("v0");
Vertex_Data* v0_data = vertex0.get_data();

Edge* edge4 = Graph.get_edge_by_id(4);
Edge_Data* e4_data = edge4.get_data();

这可能看起来像很多问题,但实际上只是我启动和运行这个库所需的基础。少了一点,对我需要做的事情完全没用。

请点击所有要点。

将此视为教程,我希望提供赏金也能帮助其他人。

【问题讨论】:

    标签: c++ boost graph boost-graph lemon-graph-library


    【解决方案1】:

    然后,我将使用整数顶点索引,而不是使用顶点指针。

    事实上,我认为你会使用顶点描述符。在 vecS 容器选择的情况下,这将是不可或缺的,是的

    据我了解,使用 BGL 实现这一点并不容易,因为删除一个顶点会触发所有具有更高 ID 的顶点重新编号,并且还可能导致内部结构的重新分配。

    严格来说,情况并非总是如此。 vecS 的情况,但不是例如listS(列表有稳定的迭代器)。

    总而言之,我建议将listS 视为容器选择,并放弃vertex_descriptor 是整数类型的假设(它将变得不透明)。

    作为迭代器稳定性的回报,您需要为某些算法提供顶点索引映射。

    【讨论】:

    • 当使用 listS 时,提供一个 vertex_index_t 映射有点棘手。您必须决定存储映射的位置:顶点 --> 整数,其中整数应该在区间 [0,num_vertices(g)) 中。这里stackoverflow.com/questions/11336723/… 是使用顶点属性完成的。您还可以使用一些单独的 std::map。在任何情况下,关键元素是添加模板专业化namespace boost { template&lt;&gt; struct property_map&lt;MyGraph, vertex_index_t &gt; {... }; }
    • @MichaelSimbirsky 大多数算法都有一个可选的 vertex_index(命名)参数,使用专业化的附加值是什么?
    • 完全没问题。我记得我们在聊天about Learning Boost Graph (among other things) 中的约 1 小时对话。 Re:“什么例子?”:特别是this comment。其余的,搜索:how provide a vertex_index property for my graph 可以帮助,这个shows how pass an index_map when using vecS;
    • 谢谢,您对 StackOverflow 尤其是 boost-graph 的贡献着迷。永远喜欢你们。我经常编写将现有结构转换为 Boost.Graph 接口的适配器。例如,对于 Boost.Polygon Voronoi 图的原始图和对偶图。在所有这些情况下,我认为 vertex_index 是适配器的自然部分。在定义图的那一刻,通常存在一个自然的顶点编号。我更喜欢明确这个编号,以免我的代码用户免于定义他或她自己的顶点索引图的麻烦。
    猜你喜欢
    • 1970-01-01
    • 2021-03-07
    • 2018-07-27
    • 2016-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 2012-08-13
    相关资源
    最近更新 更多