Iterating over edges of a graph using range-based for

前端 未结 3 2119
礼貌的吻别
礼貌的吻别 2021-02-08 00:42

I have a representation of a graph as a std::vector> neighbors, that is, vertices are integers, and for each vertex we keep

3条回答
  •  误落风尘
    2021-02-08 01:34

    I strongly recommend using the Boost.Graph library for such computations. The main reason is that graphs are complicated data structures on which you can run even more complicated algorithms. Even if your own hand-made data structure works correctly, it is likely not to run efficiently (in terms of space/time complexity) and may not support the algorithms that your applications needs.

    As an indication on how accessible this library is: I had no prior experience with Boost.Graph, but it took about 30 minutes to come up with the following 30 lines of code that completely reproduces your example.

    #include 
    #include 
    #include 
    
    typedef unsigned V;
    typedef std::pair E;
    
    // store neighbors in a std::set, vertices in a std::vector
    typedef boost::adjacency_list Graph;
    
    int main()
    {
       // construct the graph
       E e[] = { E(1,2), E(2,3), E(1,3) };
       Graph g(std::begin(e), std::end(e), 5);
    
       std::cout << "iterate over vertices, then over its neighbors\n";
       auto vs = boost::vertices(g);
       for (auto vit = vs.first; vit != vs.second; ++vit) {
           auto neighbors = boost::adjacent_vertices(*vit, g);
           for (auto nit = neighbors.first; nit != neighbors.second; ++nit)
               std::cout << *vit << ' ' << *nit << std::endl;
       }
    
       std::cout << "iterate directly over edges\n";
       auto es = boost::edges(g);
       for (auto eit = es.first; eit != es.second; ++eit) {
           std::cout << boost::source(*eit, g) << ' ' << boost::target(*eit, g) << std::endl;
       }
    }
    

    Output on LiveWorksSpace

    Granted, because boost::edges returns a std::pair, you can't use range-based for on the edges, but that's only syntactic sugar which you can try to repair by defining your own begin/end functions. What's important is that you can iterate over edges directly.

    Note that the boost_adjacency_list data structure provides you with edge and vertex operations of well-defined time and space complexity. The code above merely reproduces your example without knowing what kind of operations you really want. Changing the underlying containers allows you to make tradeoffs appropriately to your application.

提交回复
热议问题