【问题标题】:Boost Graph: Algorithm to traverse a tree down to single leafBoost Graph:遍历树到单叶的算法
【发布时间】:2020-07-22 18:53:32
【问题描述】:

这是我想要实现的目标:

  • 我有一个结构类似于树根的固定图:单头,向下多级,大多数级别有单个节点,一些级别有兄弟节点。没有循环分支。
  • 在每次运行时,我都想遍历图从头部到遇到的第一片叶子。
  • 在随后的运行中,我想再次遍历,但在每个级别使用交替分支。分支切换首先从顶部发生,然后向下传播。
  • 在每个级别,我都想对遍历命中的节点执行一个操作。没有任何操作会修改图表。

我可以从头开始,但我认为 Boost Graph 很可能是我最好的朋友。但是有很多不同的结构和算法,其名称只有专家才能理解。

你知道我想做的(上面)是否已经存在于 Boost Graph 中?

【问题讨论】:

  • “我想再次遍历,但在每一层都使用交替分支”在每一层是什么意思?当然,当您在第一级选择不同的分支时,另一级的分支不能与先前遍历中的相同...

标签: algorithm boost graph traversal


【解决方案1】:

您的要求似乎矛盾:

  • 每次运行时,我都想从头到头遍历图 遇到叶子。

这正是深度优先遍历 (DFS) 的典型特征

  • 在随后的运行中,我想再次遍历,但使用 每个级别的交替分支。分支切换从顶部发生 先向下传播。

这是典型的广度优先遍历 (BFS)

我可以向您展示带有 Boost 的标准 BFS/DFS,但如果您想要自己的混合算法,您可能必须自己编写。我的猜测是您实际上想要 BFS¹

代码

  • 我有一个结构类似于树根的固定图:单头,向下多级,大多数级别有单个节点,一些级别有兄弟节点。没有循环分支。
auto make_graph() {
    enum { root, a, b, c, d, e, f, g, h, i, j };
    boost::adjacency_list<> graph(j+1);
    add_edge(root, a, graph);
    add_edge(root, b, graph);
    add_edge(root, c, graph);
    add_edge(a,    d, graph);
    add_edge(a,    e, graph);
    add_edge(d,    f, graph);
    add_edge(b,    h, graph);
    add_edge(h,    i, graph);
    add_edge(i,    j, graph);
    return graph;
}

对应于

进行遍历:

最简单的 BFS 是:

int main() {
    Graph const graph = make_graph();

    boost::default_bfs_visitor vis;

    std::vector<boost::default_color_type> colors(num_vertices(graph));
    boost::breadth_first_visit(graph, Vertex{ root },
        boost::visitor(vis).color_map(colors.data()));
}

这使用默认访问者,它实际上什么都不做。

您可以覆盖任何事件,例如:

struct Vis : boost::default_bfs_visitor {
    void discover_vertex(Vertex u, Graph const&) {
        std::cout << "Discover " << names[u] << "\n";
    }
    void examine_vertex(Vertex u, Graph const& g) {
        if (0 == out_degree(u, g)) {
            std::cout << "Examine Leaf Node " << names[u] << "\n";
        }
    }
    using Edge = Graph::edge_descriptor;
    void tree_edge(Edge e, Graph const& g) const {
        auto a = source(e, g);
        auto b = target(e, g);
        std::cout << "Tree edge " << names[a] << " -> " << names[b] << "\n";
    }
} vis;

全部启用后将打印:

Discover root
Tree edge root -> a
Discover a
Tree edge root -> b
Discover b
Tree edge root -> c
Discover c
Tree edge a -> d
Discover d
Tree edge a -> e
Discover e
Tree edge b -> h
Discover h
Examine Leaf Node c
Tree edge d -> f
Discover f
Examine Leaf Node e
Tree edge h -> i
Discover i
Examine Leaf Node f
Tree edge i -> j
Discover j
Examine Leaf Node j

事件的完整文档在这里:https://www.boost.org/doc/libs/1_73_0/libs/graph/doc/BFSVisitor.html


¹(因为即便如此,仍然会首先报告第一个叶子,因此可能无法观察到它访问其他正在进行的节点的事实)

【讨论】:

  • 谢谢。现在我对要查找的内容有了一些提示,我将进行更深入的了解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多