基于Boost库:XML项向量读写及邻接表动态属性读写学生信息
嘿,这就帮你搞定这两个Boost图库的问题,直接上代码和清晰的解释,这样你能快速上手:
1. 使用boost::write_graphml读写XML中的项向量
GraphML本身支持存储复杂类型,但Boost默认的属性映射不会直接处理向量,所以我们需要给向量类型自定义序列化/反序列化逻辑,再通过dynamic_properties注册进去。下面是完整的实现示例:
第一步:定义图和属性结构
#include <boost/graph/adjacency_list.hpp> #include <boost/graph/graphml.hpp> #include <vector> #include <fstream> #include <sstream> // 顶点属性:包含一个向量字段 struct VertexProps { std::vector<int> items; }; // 定义图类型 using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, VertexProps>;
第二步:实现向量的读写转换函数
我们需要把向量转换成字符串才能存入GraphML,读取时再把字符串还原成向量:
// 把向量转成空格分隔的字符串(用于写入) std::string vector_to_str(const std::vector<int>& vec) { std::ostringstream oss; for (size_t i = 0; i < vec.size(); ++i) { if (i != 0) oss << " "; oss << vec[i]; } return oss.str(); } // 把字符串转成向量(用于读取) void str_to_vector(std::vector<int>& vec, const std::string& str) { vec.clear(); std::istringstream iss(str); int val; while (iss >> val) { vec.push_back(val); } }
第三步:读写GraphML文件
通过make_transform_value_property_map把转换函数和属性映射绑定,再注册到dynamic_properties中:
int main() { // 构建测试图,给顶点设置向量属性 Graph g; auto v1 = boost::add_vertex(VertexProps{{1,2,3}}, g); auto v2 = boost::add_vertex(VertexProps{{4,5,6}}, g); boost::add_edge(v1, v2, g); // 写入GraphML std::ofstream out_file("vector_graph.graphml"); boost::dynamic_properties dp_write; dp_write.property("vertex_items", boost::make_transform_value_property_map( vector_to_str, get(&VertexProps::items, g), str_to_vector)); boost::write_graphml(out_file, g, dp_write, true); // true表示写入顶点ID out_file.close(); // 读取GraphML Graph g_read; std::ifstream in_file("vector_graph.graphml"); boost::dynamic_properties dp_read; dp_read.property("vertex_items", boost::make_transform_value_property_map( vector_to_str, get(&VertexProps::items, g_read), str_to_vector)); boost::read_graphml(in_file, g_read, dp_read); in_file.close(); // 验证读取结果 auto& items = g_read[*boost::vertices(g_read).first].items; for (int num : items) { std::cout << num << " "; // 输出:1 2 3 } std::cout << std::endl; return 0; }
2. 使用dynamic property读写带name字段的GraphData结构体
这里分两种常见场景:GraphData是图的全局属性,或者是每个顶点的属性,两种情况的实现略有不同,我都给你列出来:
场景1:GraphData是图的全局属性
如果GraphData是整个图的元信息(比如图的名称),代码如下:
#include <boost/graph/adjacency_list.hpp> #include <boost/graph/graphml.hpp> #include <fstream> #include <string> // 图的全局属性结构体 struct GraphData { std::string name; // 可以添加其他字段,比如创建时间、版本号等 }; // 定义图类型:把GraphData作为全局属性(最后一个模板参数) using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::no_property, GraphData>; int main() { // 创建图并设置全局属性 Graph g; g[boost::graph_bundle].name = "Student_Info_Graph"; // 访问全局属性 // 添加测试顶点和边 auto v1 = boost::add_vertex(g); auto v2 = boost::add_vertex(g); boost::add_edge(v1, v2, g); // 写入GraphML std::ofstream out_file("global_property.graphml"); boost::dynamic_properties dp_write; dp_write.property("graph_name", get(&GraphData::name, g)); // 绑定全局属性的name字段 boost::write_graphml(out_file, g, dp_write, true); out_file.close(); // 读取GraphML Graph g_read; std::ifstream in_file("global_property.graphml"); boost::dynamic_properties dp_read; dp_read.property("graph_name", get(&GraphData::name, g_read)); boost::read_graphml(in_file, g_read, dp_read); in_file.close(); // 验证结果 std::cout << "读取到的图名称:" << g_read[boost::graph_bundle].name << std::endl; // 输出:读取到的图名称:Student_Info_Graph return 0; }
场景2:GraphData是顶点属性(每个顶点对应一个学生)
如果每个顶点代表一个学生,GraphData是学生的信息(比如姓名、年龄),代码调整如下:
#include <boost/graph/adjacency_list.hpp> #include <boost/graph/graphml.hpp> #include <fstream> #include <string> // 顶点属性:学生信息结构体 struct GraphData { std::string name; int age; }; // 定义图类型:把GraphData作为顶点属性(第四个模板参数) using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, GraphData>; int main() { // 创建图,添加学生顶点 Graph g; auto alice = boost::add_vertex(GraphData{"Alice", 20}, g); auto bob = boost::add_vertex(GraphData{"Bob", 21}, g); boost::add_edge(alice, bob, g); // 写入GraphML std::ofstream out_file("student_vertices.graphml"); boost::dynamic_properties dp_write; // 注册顶点的name和age属性 dp_write.property("student_name", get(&GraphData::name, g)); dp_write.property("student_age", get(&GraphData::age, g)); boost::write_graphml(out_file, g, dp_write, true); out_file.close(); // 读取GraphML Graph g_read; std::ifstream in_file("student_vertices.graphml"); boost::dynamic_properties dp_read; dp_read.property("student_name", get(&GraphData::name, g_read)); dp_read.property("student_age", get(&GraphData::age, g_read)); boost::read_graphml(in_file, g_read, dp_read); in_file.close(); // 验证第一个学生的信息 auto& first_student = g_read[*boost::vertices(g_read).first]; std::cout << "第一个学生:" << first_student.name << ",年龄:" << first_student.age << std::endl; // 输出:第一个学生:Alice,年龄:20 return 0; }
解释一下:对于std::string、int这类基础类型,Boost已经内置了读写逻辑,所以直接用get(&GraphData::name, g)获取属性映射,再注册到dynamic_properties里就可以了,不需要额外写转换函数。
内容的提问来源于stack exchange,提问作者Milan Dabhi
相关产品推荐
相关产品推荐

