【问题标题】:compare topologically sorted list with the original list将拓扑排序列表与原始列表进行比较
【发布时间】:2011-07-13 07:44:37
【问题描述】:

我有一个来自 mygraph 的顶点向量,我对顶点进行拓扑排序。

typedef typename boost::adjacency_list<boost::listS, boost::vecS, 
       boost::directedS,Vertex_t*> Graph_t;

typedef typename boost::graph_traits<Graph_t>::vertex_descriptor Vd_t;
Graph_t mygraph;
std::vector<Vd_t> v1; 
//initialize the vertices and get a copy of vertices in vector v1
//...
//and then i use

std::vector<Vd_t> v2;
boost::topological_sort(mygraph,std::back_inserter(v2));

对顶点“按顺序”进行拓扑排序。 那么比较 v1 和 v2 以测试我的原始顶点向量(v1)是“有序”还是“无序”的最佳方法是什么。

编辑: 例如: 如果向量 v1 有顶点 {A, B, C} 并且我们有边 (A,B) (C,A)

所以在拓扑排序之后,我将在 v2 中拥有

{C, A, B}

在某些情况下,我可能无法获得唯一的拓扑顺序,例如,如果我有 (A,C) 作为唯一的边,那么 v2 可能会以 {A , B , C} 或 {B , A , C}

现在我需要查看 v1 和 v2 以确定 v1 和 v2 是否代表相同的订单。

第二次编辑: 我尝试了一种方法,它现在有效,请告诉我这是否是一个好方法。

template <typename Vertex_t>
void DepAnalyzer<Vertex_t>::CheckTotalOrder()
{
  //Vd_t is the vertex descriptor type
  typename std::vector<Vd_t> topo_order;
  typename std::vector<Vd_t>::iterator ordered_vertices_iter;

  //puts the topologically sorted vertices into topo_order
  DoTopologicalSort(topo_order);

  //will point to the vertices in the order they were inserted
  typename boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
  std::unordered_map<Vertex_t*,int,std::hash<Vertex_t*>,
                      VertexEqual> orig_order_map, topo_order_map;  

  int i = 0;
  for(std::tie(vi, vi_end) = boost::vertices(depGraph); vi != vi_end; ++vi) {
    orig_order_map[depGraph[*vi]] = ++i;
    //std::cout<<depGraph[*vi]->get_identifier_str()<<"\n";
  }
  i = 0;
  //will point to the vertices in the topological order
  ordered_vertices_iter = topo_order.begin();
  for(;ordered_vertices_iter != topo_order.end(); ordered_vertices_iter++) {
    topo_order_map[depGraph[*ordered_vertices_iter]] = ++i;
    //std::cout<<depGraph[*ordered_vertices_iter]->get_identifier_str()<<"\n";
  }
  //checking the order now
  ordered_vertices_iter = topo_order.begin();
  for(;ordered_vertices_iter != topo_order.end(); ordered_vertices_iter++) {
    //if the vertex in topologically sorted list occurs before(w.r.t. position)
    //the macro in the original list of vertices, then it's okay
    if(orig_order_map[depGraph[*ordered_vertices_iter]] >
      topo_order_map[depGraph[*ordered_vertices_iter]]) {
      std::cerr << depGraph[*ordered_vertices_iter]->get_identifier_str() 
                << ": out of order\n";
    }
  }
}

【问题讨论】:

  • 如果v2 已经是v1 的副本,则保证调用boost::topological_sort( mygraph, std::back_inserter(v2)) 不会给出相同的结果:v2 将包含所有v1 以相同的顺序跟随由排序版本。 (即v2.size()==2*v1.size())另请注意,在许多情况下,给定图有不止一种有效的拓扑排序,因此如果它们不相等,您将知道它们不是相同拓扑排序,这不同于知道v1 不是拓扑排序
  • 抱歉错误...现在更正

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


【解决方案1】:

那么比较 v1 和 v2 以测试我的原始顶点向量 (v1) 是“有序”还是“无序”的最佳方法是什么。

不比较向量。该测试的缺陷在于,如果它成功(两个向量相同),您将知道它是有序的,但如果它失败(向量不同),您将不知道它是无序还是不同顺序。

考虑图形(想象边缘向下):

  A
 / \
B   C
 \ /
  D

列表{ A, B, C, D }{ A, C, B, D } 都按拓扑顺序排列,因为BC 之间没有排序约束。如果您有其中一个选项,而 boost::topological_sort 产生了另一个变体,您将不知道您的订单是错误的还是不同的正确的。

最好编写一个简单的算法来检查顺序的正确性并在需要时重新排序。

【讨论】:

  • 是的,我理解这个问题,这就是为什么我问是否已经有一种方法可以确定 v1 和 v2 是否都按顺序排列。我应该采用简单的 O(n^2) 方法逐个元素地比较两个向量还是其他一些您可能建议的好方法。
  • @Aditya Kumar:您可以使用多种不同的方法,它们会比O(n^2) 方法更好。一个选项是保留一组已在容器中检查的节点,最初为空。遍历容器,为每个新节点检查所有边,如果任何引用的节点已经存在于集合中,则顺序无效。将此节点添加到集合中并继续前进。这种方法是O(V log N)V 是边数,N 是节点数)
  • @Aditya Kumar:现在,随着对代码的深入了解,如果你能保证所有的边都引用同一个向量中的元素,你可以使用指针算法来加速这个过程:因为向量连续存储元素,可以比较指针,如果&amp;b - &amp;a &gt; 0,则节点a在向量中的b之前。使用它,您可以遍历容器,并验证对于每条边,源节点的地址小于目标节点的地址。这应该是O( V ),其中V 是顶点数。
  • @Aditya Kumar:重读您的评论后,我不确定您是否理解问题所在。问题是您无法比较向量,您需要根据图形验证拓扑顺序,而不是根据给定的拓扑顺序。比较矢量内容将不会告诉您原始容器是否处于拓扑顺序(好吧,如果库提供的顺序与您的顺序一致,它会多次)。比较答案中的两个列表会告诉您它们不同,但不会告诉您两者都是正确的。
  • 我添加了一个我试过的方法,请看一下
【解决方案2】:

我是否正确理解了您想要测试顶点列表是否已按拓扑顺序排列的问题?

如果是这样,您可以执行以下操作:

  • 让顶点列表为v。现在构造一个列表r,其中r[i] 给出v 中顶点i 的索引,即v[r[i]] = i
  • 然后遍历所有有向边(i,j) 并检查r[i] &lt;= r[j]
  • 如果是这样,则列表v 已按拓扑顺序排列。

但是,这将与进行v 的完整拓扑排序一样慢(两者的边数加上顶点数都是线性的)。因此,如果您的目标只是让v 按拓扑顺序排列,那么只需进行排序即可。如果您需要尽可能将v 保持在当前顺序中,这将很有用。

【讨论】:

  • 您的想法更接近,为此 +1
【解决方案3】:

std::vectoroperator==,所以你可以简单地if(v1==v2)

编辑:这是一个充分但非必要的条件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多