【问题标题】:Sorting the EdgeList in boost::graph在 boost::graph 中对 EdgeList 进行排序
【发布时间】:2011-09-28 13:50:17
【问题描述】:

我想对 boost::graph 的边列表进行排序,定义如下:

struct Vertex{
int index;
};

struct Edge{
double weight;
};

boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, Vertex, Edge> Graph;

添加顶点和边后,如何对边列表进行排序。首先获得最高权重的优势?

我知道有人可以使用

std::sort(edgeIt_begin,edgeIt_end,compare); 

适用于向量,但不适用于 std::list。

【问题讨论】:

    标签: c++ sorting boost boost-graph stdlist


    【解决方案1】:

    您可以编写自己的 EdgeList 或 OutEdgeList 类来自动对元素进行排序。 我举了一个例子,因为如何做到这一点并不那么明显。

    #include <iostream>
    #include <boost/graph/graph_traits.hpp>
    #include <boost/graph/adjacency_list.hpp>
    
    using namespace boost;
    
    template<class T> struct Sorted_list
    {
      std::list<T> v;
    
    public:
      typedef T value_type;
      typedef typename std::list<T>::size_type size_type;
      typedef typename std::list<T>::iterator iterator;
    
      iterator insert(const T& x)
      {
        Sorted_list<T>::iterator i = v.begin();
    
        while(i != v.end() && x > *i)
        {
          i++;
        }
    
        return v.insert(i, x);
      }
    
      iterator begin() { return v.begin(); }
      iterator end() { return v.end(); }
    
      size_type size() const { return v.size(); }
    };
    
    struct SlistS {};
    
    namespace boost {
      template <class ValueType> struct container_gen<SlistS, ValueType>
      {
        typedef Sorted_list<ValueType> type;
      };
    
      struct sorted_list_tag {};
    
      template<class T> sorted_list_tag container_category(Sorted_list<T>&)
      {
        return sorted_list_tag();
      }
    
      template<class T> std::pair<typename Sorted_list<T>::iterator, bool>
      push_dispatch(Sorted_list<T>& v, const T& x, sorted_list_tag)
      {
        return std::make_pair(v.insert(x), true);
      }
    
      template <> struct parallel_edge_traits<SlistS> { 
        typedef allow_parallel_edge_tag type;
      };
    }
    
    int main()
    {
      typedef adjacency_list<SlistS> Graph;
      Graph g(10);
      add_edge(1, 2, g);
      add_edge(1, 5, g);
      add_edge(1, 3, g);
      add_edge(1, 7, g);
      add_edge(1, 1, g);
    
      graph_traits<Graph>::edge_iterator i, end;
    
      for (tie(i, end) = edges(g); i != end; ++i) {
        std::cout << source(*i, g) << " -> " << target(*i, g) << std::endl;
      }
    
      return 0;
    }
    

    输出:

    1 -> 1
    1 -> 2
    1 -> 3
    1 -> 5
    1 -> 7
    

    【讨论】:

      【解决方案2】:

      对边缘进行排序不是惯用的 boost::graph。查看 Kruskal's algorithm 的 BGL implementation 以获取生成树。该算法需要按权重递增的顺序查看每条边。

        std::priority_queue<Edge, std::vector<Edge>, weight_greater> Q(wl);
        /*push all edge into Q*/
        typename graph_traits<Graph>::edge_iterator ei, eiend;
        for (boost::tie(ei, eiend) = edges(G); ei != eiend; ++ei) 
          Q.push(*ei);
      

      它使用单独的数据结构对边进行排序,然后按该顺序遍历边。在您的情况下,您首先需要最高的加权边缘,因此您需要更改比较器运算符。

      【讨论】:

        【解决方案3】:

        我不知道与 Boost Graph 表示的任何交互,但 IIRC 你可以使用std::list::sort(Cmp)

        std::list<int> l = { 1, 3, -1, 9, 2 };
        l.sort();
        

        【讨论】:

          【解决方案4】:

          上一个答案虽然非常有用,但管理 bgl 标签的方式有点不正确,这会导致多余的 push_dispatch 定义,并且如果调用其他 *_dispatch 函数(例如在擦除操作的情况下)可能会导致构建问题。

          第二个令人困惑的情况是在adj_list模板中替换了每个节点的边缘列表,但打印了不受影响的整个边缘列表。

          可能有一些代码可以纠正这些缺陷:

          // ...
          
          template<class T> struct Sorted_vector : public std::vector<T>
          {
          public:
          
            iterator insert(const T& x)
            { 
              iterator where = std::upper_bound(begin(), end(), x, std::less<T>());
              return std::vector<T>::insert(where, x);
            }
          
          };
          
          struct vecSS{};
          
          namespace boost{
          
              template <class ValueType> struct container_gen<vecSS, ValueType>
              {
                  typedef Sorted_vector<ValueType> type;
              };
          
              template <> struct parallel_edge_traits<vecSS> { 
                  typedef allow_parallel_edge_tag type;
              };
          
              template<class T> graph_detail::vector_tag container_category(const Sorted_vector<T>&)
              {
                  return graph_detail::vector_tag();
              }
          
              template <class T> graph_detail::unstable_tag iterator_stability(const Sorted_vector<T>&)
              {
                  return graph_detail::unstable_tag();
              }
          }
          
          typedef adjacency_list<vecSS, ...> Graph;
          
          // ....
          
            graph_traits<Graph>::vertex_iterator ii, ee;
            for(boost::tie(ii,ee) = vertices(g);ii!=ee;++ii){
                 std::cout << *ii << std::endl;
                 graph_traits<Graph>::adjacency_iterator jj, ff;
                 for(boost::tie(jj,ff)=adjacent_vertices(*ii, g);jj != ff; ++jj){
                      std::cout << "\t -> " << *jj<<std::endl;
                 }
            }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-10
            • 2019-03-21
            • 1970-01-01
            • 2013-07-25
            • 1970-01-01
            • 2012-09-16
            相关资源
            最近更新 更多