提升图表列表或vec

时间:2015-05-14 17:45:31

标签: c++ algorithm boost graph boost-graph

我花了几天时间使用boost图库。据我所知,在考虑VertexList和EdgeList存储时:

vecS:

  • 拥有索引,因此可以使用它进行访问
  • 删除顶点时,迭代器无效

listS:

  • 没有索引
  • 不会使迭代器无效

它有点短,但这就是我的问题。我需要那些索引号,我希望以后能够轻松删除顶点。

我有一个使用此图结构的工作算法:

typedef boost::adjacency_list<
        boost::vecS, boost::vecS, boost::undirectedS, 
        topologicalmap::Intersection_Graph ,
        boost::edge_weight_t, 
        boost::no_property > Graph_boost;

我有一个自定义结构Intersection_Graph用于我需要使用的顶点。在这里我使用vecS。

我想使用listS代替能够删除顶点。同样,我希望以后能够在Dijkstra算法中使用它。

我有点明白我需要在列表中添加boost::vertex_index_t,但我真的很困惑如何做到这一点并同时保留我的自定义结构。

我尝试过这些方法:

typedef boost::adjacency_list<
        boost::listS, boost::listS, boost::undirectedS, 
        boost::property<boost::vertex_index_t, topologicalmap::Intersection_Graph>,
        boost::edge_weight_t, 
        boost::no_property > Graph_boost;

但我甚至无法访问我的自定义结构。另外,索引访问不起作用。

我真的需要索引访问功能,因为我的图表将依赖于返回父节点索引的算法。我觉得我可以使用Vertex而不是索引,但这意味着重新编写代码,我想知道我是否可以避免它。

所以我的问题是:在保持listS优势的同时,有没有办法让listS以类似于vec的方式运行?

如果它听起来很愚蠢,请跟我说。我现在很困惑,所以我可能会说些蠢话。如果您需要更多信息,请询问。

1 个答案:

答案 0 :(得分:5)

内部属性配方是:

property<tag, type, next_property>

当然,除非您使Intersection_Graph 表现类似于整数类型,否则您无法直接将其用作vertex_index属性的类型。它也可能不是你想要的。

这看起来更接近:

boost::property<boost::vertex_index_t, int, topologicalmap::Intersection_Graph>

它会声明两个属性:

  1. 标记为vertex_index_t(类型int
  2. 的内部属性
  3. 捆绑属性(键入Intersection_Graph)。请注意,可以通过vertex_bundle_t标记隐式访问捆绑属性。
  4. 现在考虑到这一点,一切都应该一帆风顺:

    <强> Live On Coliru

    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/random.hpp>
    #include <boost/graph/graph_utility.hpp>
    #include <boost/graph/iteration_macros.hpp>
    
    #include <random>
    #include <iostream>
    
    using namespace boost;
    
    namespace topologicalmap {
        struct Intersection_Graph {
            std::string bundled;
        };
    }
    
    typedef boost::adjacency_list<
            boost::listS, boost::listS, boost::undirectedS, 
            boost::property<boost::vertex_index_t, int, topologicalmap::Intersection_Graph>,
            boost::edge_weight_t, 
            boost::no_property > Graph_boost;
    
    int main() {
    
        std::mt19937 prng { std::random_device {} () };
        Graph_boost g;
    
        generate_random_graph(g, 10, 20, prng);
    
        // assign indices
        int i = 0;
        BGL_FORALL_VERTICES(v, g, Graph_boost) { 
            get(vertex_index, g)[v] = i; 
            g[v].bundled = "id:" + std::to_string(i);
    
            i++;
        }
    
        // print the graph using the `bundled` property as a label:
        print_graph(g, get(&topologicalmap::Intersection_Graph::bundled, g));
    
        // do some index accesses:
        for (int i : {1,7})
            std::cout << "\nVertex at index #" << i << " has a bundled property of '" << g[vertex(i,g)].bundled << "'";
    }
    

    打印例如(随机生成每次运行)

    id:0 <--> id:8 id:8 id:7 id:6 id:1 
    id:1 <--> id:3 id:4 id:4 id:3 id:0 id:2 
    id:2 <--> id:7 id:1 
    id:3 <--> id:1 id:7 id:1 id:9 id:4 
    id:4 <--> id:1 id:1 id:5 id:6 id:3 
    id:5 <--> id:4 id:9 
    id:6 <--> id:0 id:9 id:4 id:8 
    id:7 <--> id:3 id:0 id:2 id:9 
    id:8 <--> id:0 id:0 id:6 
    id:9 <--> id:7 id:6 id:3 id:5 
    
    Vertex at index #1 has a bundled property of 'id:1'
    Vertex at index #7 has a bundled property of 'id:7'
    

    注意:

    • 图表“知道”vertex_index现在并不意味着它得到维护;你必须自己填写:

      int i = 0;
      BGL_FORALL_VERTICES(v, g, Graph_boost) get(vertex_index, g)[v] = i++; 
      
    • 您实际上不需要将vertex_index与您的图表类型相关联,因为您可以将其作为命名参数传递给所有相关算法AFAIK。这包括构建依赖于vertex_index的派生属性映射(例如make_iterator_property_map

    • 我相信也可以使用图形特征来关联顶点索引(但我过去没有这样做)。这似乎是一个很好的方式去,如你,例如想要将索引存储在Intersection_Graph结构的成员中。
    • 就像我在my comment中所说的那样,如果存储vertex_descriptor而不是整数索引,则可能不需要这些。