如何高效使用Boost Graph并优化自定义封装代码的冗余问题
问题1 替换vecS为setS后的编译错误解决
错误的根本原因是:vecS作为顶点容器选择器时,顶点描述符是连续整数类型,你之前用数组指针构造的make_label_writer依赖整数索引访问。而setS的顶点描述符是迭代器类型,无法作为数组下标,导致内部类型推导失败抛出void引用相关错误。
解决方法:
- 将顶点标签存储从
std::vector<std::string>改成关联式容器std::map<VertexDesc, std::string> - 调用
write_graphviz时,顶点标签也用make_label_writer(make_assoc_property_map(顶点标签map))传入,不再用数组指针
额外说明:如果同时把边的容器也改成setS,add_edge会自动判断重复边,你自己维护的edgeSet_可以直接删掉。
问题2 通过挂载的自定义对象查询顶点描述符
有两种简便实现:
- 结构体加字段:在
Vertex结构体中新增VertexDesc desc成员,add_vertex成功后将返回的描述符赋值给该成员,后续要查询直接读取对象的desc字段即可 - 维护反向映射:新增成员
std::unordered_map<std::shared_ptr<Vertex>, VertexDesc> ptr2vertex_,addNode时同步写入映射,后续传入shared_ptr<Vertex>即可直接查询到对应的描述符。如果你的Vertex的name全局唯一,直接用现有vertexMap_通过name查询也可以,不需要额外新增存储。
问题3 用Boost内置property机制消除冗余存储
完全可以,调整adjacency_list的属性定义即可:
// 定义顶点属性:内置名称属性 + 自定义shared_ptr<Vertex> using VertexProp = property<vertex_name_t, std::string, std::shared_ptr<Vertex>>; // 定义边属性:内置名称属性 + 自定义shared_ptr<Edge> using EdgeProp = property<edge_name_t, std::string, std::shared_ptr<Edge>>; // 定义图类型,边容器用setS自动去重 using Graph = adjacency_list<vecS, vecS, bidirectionalS, VertexProp, EdgeProp>;
调整后可以直接省掉以下外部存储:
- 不需要
vertexLabelArray_、edgeLabelMap_:内置的vertex_name_t、edge_name_t可以直接被write_graphviz识别,不需要自定义标签写入器 - 不需要
edgeSet_:边容器选setS即可自动去重 - 甚至如果你的
Vertex和Edge只需要存name字段,连shared_ptr层都可以去掉,直接用内置属性存名称,完全消除冗余的外部映射存储。
内容的提问来源于stack exchange,提问作者katetsu
相关产品推荐
相关产品推荐

