Boost中boost::graph模块相关内容详解和代码示例

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_visitordefault_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 等图优化库联合建图结构
  • 点云数据法向量方向统一化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云SLAM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值