如何用Boost在循环中将向量元素作为图顶点添加?报错求助
问题分析与解决方法
首先咱们先拆解你代码里的几个核心问题:
- 你混淆了Boost图**内部顶点描述符(vertex_descriptor)**和你自定义的顶点ID(也就是向量里的3、2、1这些值)。当用
boost::vecS作为顶点容器时,顶点描述符是从0开始的连续整数,和你想设置的自定义ID不是一回事。 - 你先通过
Graph g(Group4.size());创建了对应数量的顶点,之后又调用add_vertex,这会导致顶点数量翻倍,完全不符合你的预期。 boost::add_vertex(Group4[i], g)这行代码存在类型错误:你的Vertex结构体只有float foo字段,无法直接用整数(Group4的元素)来构造Vertex对象。
接下来,咱们一步步解决你的需求:把向量[3,2,1,8,7]的元素作为顶点的自定义标识,同时正确使用Boost图的API。
最优实现思路
要实现用自定义数值作为顶点标识,我们需要:
- 在
Vertex结构体中添加一个字段来存储自定义ID; - 建立一个映射表,把自定义ID和Boost内部的顶点描述符关联起来,方便后续通过ID查找顶点;
- 循环遍历向量,逐个添加顶点并完成初始化。
修正后的完整代码
#include <boost/graph/adjacency_list.hpp> #include <unordered_map> #include <vector> // 自定义顶点结构体,添加id字段存储我们的自定义顶点标识 struct Vertex { float foo; int id; }; // 定义图类型:vecS顶点容器(连续整数描述符)、vecS边容器、有向图、自定义Vertex结构体 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Vertex> Graph; typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t; int main() { std::vector<int> Group4 = {3, 2, 1, 8, 7}; Graph g; // 建立自定义ID到顶点描述符的映射 std::unordered_map<int, vertex_t> id_to_vertex; // 循环遍历向量,添加顶点并初始化 for (int id : Group4) { // 添加一个顶点,获取其描述符 vertex_t v = boost::add_vertex(g); // 设置顶点的自定义ID和foo字段 g[v].id = id; // 把ID和描述符存入映射表 id_to_vertex[id] = v; } // 通过自定义ID找到顶点,设置foo值 g[id_to_vertex[3]].foo = 3.4; // 通过映射表获取顶点描述符,添加边 boost::add_edge(id_to_vertex[3], id_to_vertex[1], g); boost::add_edge(id_to_vertex[2], id_to_vertex[1], g); return 0; }
关键细节解释
- 映射表的作用:
id_to_vertex解决了自定义ID和Boost内部描述符的关联问题,让你可以用熟悉的3、2等数值来操作顶点,而不用关心内部的0、1等描述符。 - 顶点添加方式:循环中直接调用
boost::add_vertex(g)添加顶点,之后再设置顶点的自定义属性,这样避免了构造参数不匹配的问题。 - 边的添加:必须通过映射表把自定义ID转换成Boost的顶点描述符,再传入
add_edge,否则会因为描述符不存在或不匹配导致错误。
额外说明
如果你坚持想让Boost图的顶点描述符直接等于你的自定义ID(比如描述符就是3、2、1),可以把顶点容器换成boost::mapS,这样顶点描述符可以是任意整数类型,但这种方式会带来一定的性能开销,因为map容器的访问速度比vecS慢。一般来说,用vecS加映射表的方式是更高效的最优解。
内容的提问来源于stack exchange,提问作者spnsp




