Boost.Graph
是 Boost 库中的强大图算法与图数据结构框架,提供了高度灵活的图模型表示和丰富的算法实现(如 BFS、DFS、最短路径、最小生成树等),广泛用于路径规划、图优化(如 SLAM)、依赖分析等场景。
一、Boost.Graph 核心概念
Boost.Graph(BGL)基于 模板元编程与概念机制,允许你灵活定制图的底层结构和操作方式。
主要组件
组件 | 说明 |
---|---|
graph_traits | 图类型的元信息(如边、点、迭代器类型等) |
adjacency_list | 最常用的图类型,支持定制化的邻接表 |
adjacency_matrix | 邻接矩阵型图结构 |
edge_descriptor / vertex_descriptor | 边 / 顶点的唯一标识 |
property | 节点/边属性,例如权重、颜色等 |
常用图结构模板 adjacency_list
template <
OutEdgeListS, // 边容器类型(vecS/listS/setS等)
VertexListS, // 顶点容器类型
DirectedS, // 有向/无向(directedS, undirectedS, bidirectionalS)
VertexProperties, // 顶点属性
EdgeProperties // 边属性(如权重)
>
class adjacency_list;
二、基本图构建与遍历示例
1. 简单图构建并遍历所有边
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <iostream>
int main() {
using namespace boost;
// 定义图类型
typedef adjacency_list<vecS, vecS, undirectedS> Graph;
Graph g;
// 添加边(隐式创建顶点)
add_edge(0, 1, g);
add_edge(0, 2, g);
add_edge(1, 2, g);
// 遍历所有边
graph_traits<Graph>::edge_iterator ei, ei_end;
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
std::cout << source(*ei, g) << " -- " << target(*ei, g) << std::endl;
}
}
三、BFS 和 DFS 遍历示例
2. BFS 遍历图
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <iostream>
using namespace boost;
struct bfs_visitor : public default_bfs_visitor {
void discover_vertex(int v, const auto&) const {
std::cout << "Visited: " << v << std::endl;
}
};
int main() {
typedef adjacency_list<vecS, vecS, undirectedS> Graph;
Graph g(5); // 5个节点
add_edge(0, 1, g);
add_edge(0, 2, g);
add_edge(1, 3, g);
add_edge(2, 4, g);
breadth_first_search(g, vertex(0, g), visitor(bfs_visitor()));
}
3. DFS 遍历图
#include <boost/graph/depth_first_search.hpp>
struct dfs_visitor : public default_dfs_visitor {
void discover_vertex(int v, const auto&) const {
std::cout << "DFS Visit: " << v << std::endl;
}
};
...
depth_first_search(g, visitor(dfs_visitor()));
4.Boost实现最小生成树(Kruskal 示例)
#include <iostream>
#include <vector>
#include <utility> // for std::pair
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
int main() {
using namespace boost;
// 定义图中边的权重属性类型
typedef property<edge_weight_t, int> EdgeWeightProperty;
// 图类型定义:无向图、邻接表结构
typedef adjacency_list<vecS, vecS, undirectedS,
no_property, EdgeWeightProperty> Graph;
typedef std::pair<int, int> Edge;
const int num_nodes = 5;
// 定义边与权重
enum nodes { A, B, C, D, E };
Edge edge_array[] = { Edge(A, B), Edge(A, C), Edge(B, C),
Edge(B, D), Edge(C, D), Edge(C, E), Edge(D, E) };
int weights[] = { 1, 3, 1, 6, 5, 2, 4 };
const int num_edges = sizeof(edge_array) / sizeof(Edge);
// 构建图
Graph g(edge_array, edge_array + num_edges, weights, num_nodes);
// 保存最小生成树的边
std::vector<graph_traits<Graph>::edge_descriptor> mst;
// 调用 Boost 的 Kruskal 最小生成树算法
kruskal_minimum_spanning_tree(g, std::back_inserter(mst));
// 输出结果
std::cout << "Edges in MST:\n";
for (auto& e : mst) {
std::cout << source(e, g) << " <--> " << target(e, g)
<< " with weight = " << get(edge_weight, g, e) << std::endl;
}
return 0;
}
输出示例(可能顺序不同):
Edges in MST:
0 <--> 1 with weight = 1
1 <--> 2 with weight = 1
2 <--> 4 with weight = 2
3 <--> 4 with weight = 4
点编号
0~4
对应A~E
,你也可以换成字符串或者自定义结构体做顶点属性。
说明
- 使用
adjacency_list
构建无向图。 - 通过
property<edge_weight_t, int>
给边设置权重。 - 使用
kruskal_minimum_spanning_tree()
直接获得最小生成树边集。 - 还可以使用
prim_minimum_spanning_tree()
实现 Prim 算法版本。
四、最短路径算法(Dijkstra)
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/adjacency_list.hpp>
using namespace boost;
int main() {
typedef adjacency_list<vecS, vecS, directedS,
no_property, property<edge_weight_t, int>> Graph;
Graph g(5);
add_edge(0, 1, 10, g);
add_edge(0, 2, 3, g);
add_edge(1, 2, 1, g);
add_edge(2, 1, 4, g);
add_edge(2, 3, 2, g);
add_edge(3, 4, 7, g);
add_edge(4, 3, 9, g);
std::vector<int> dist(num_vertices(g));
dijkstra_shortest_paths(g, 0,
distance_map(&dist[0]));
for (std::size_t i = 0; i < dist.size(); ++i)
std::cout << "Distance to " << i << ": " << dist[i] << std::endl;
}
五、自定义边权属性
typedef property<edge_weight_t, double> EdgeWeightProperty;
typedef adjacency_list<vecS, vecS, directedS, no_property, EdgeWeightProperty> Graph;
然后通过:
add_edge(u, v, EdgeWeightProperty(weight), g);
即可设置边权。
六、图搜索中的回调机制(自定义 Visitor)
你可以继承 default_dfs_visitor
或 default_bfs_visitor
,重写如:
discover_vertex(v, g)
finish_vertex(v, g)
tree_edge(e, g)
back_edge(e, g)
gray_target(e, g)
来定制搜索过程中的行为,如路径记录、统计、图染色等。
七、可视化(Graphviz 生成)
#include <boost/graph/graphviz.hpp>
...
write_graphviz(std::cout, g);
你可以将图结构输出为 .dot
文件后用 graphviz
工具渲染:
dot -Tpng graph.dot -o graph.png
八、应用场景与工程意义
Boost.Graph 可以扩展应用到以下场景:
- SLAM 后端中 图结构建模与优化前预处理
- 网络路径规划与依赖关系分析
- 拓扑排序、图染色、强连通分量划分
- 制约传播(如图约束系统)
- 与 GTSAM / g2o 等图优化库联合建图结构
- 点云数据法向量方向统一化