将拓扑排序列表与原始列表进行比较

时间:2011-07-13 07:44:37

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

我有一个来自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";
    }
  }
}

3 个答案:

答案 0 :(得分:4)

  

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

不比较载体。测试是有缺陷的,如果它成功(两个矢量是相同的)你会知道它是有序的,但如果它失败(矢量不同)你将不知道它是否是故障或是否是一个不同的顺序。

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

  A
 / \
B   C
 \ /
  D

列表{ A, B, C, D }{ A, C, B, D }都是拓扑顺序,因为BC之间没有排序约束。如果您有其中一个选项并且boost::topological_sort产生了另一个选项,您将无法知道您的订单是否错误,或者是否是正确的订单。

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

答案 1 :(得分:2)

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

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

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

然而,这将与执行完整拓扑排序v一样慢(两者都是边缘数加上顶点数)。因此,如果您的目标只是在拓扑顺序中使用v,那么只需进行排序即可。如果您需要在当前订单中保留v,这将非常有用。

答案 2 :(得分:0)

std::vectoroperator==,因此您可以if(v1==v2)

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