我刚开始学习boost图库,并且在boost图库中使用remove_edge函数存在一个基本问题。
我想删除多图中的边。对于有两条边连接顶点0和1的图形,我想删除其中一条,但保留另一条。
根据用户指南,remove_edge(u,v,g)删除所有出现的(u,v)。所以我应该使用remove_edge(e,g)代替。这里,e是有效的边缘描述符。
对于单个图形,g,我能够毫无问题地执行remove_edge(u,v,g)和remove_edge(e,g)操作。
然而,当我想通过将图形放在向量容器中来概括实现以满足我的需要时,我得到remove_edge的分段错误(e,graph_list [0])。 (编译器没有显示警告信息。)另一方面,remove_edge(u,v,g)工作正常。我不确定这两种语法之间的区别是什么导致了我的问题。
我真的想让remove_edge(e,g)和vector容器同时工作。因此,任何有助于我绕过这一困难的建议都会受到赞赏。
非常感谢!!
以下是我的测试代码。
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include "boost/graph/graph_traits.hpp"
#include "boost/graph/adjacency_list.
hpp"
using namespace boost;
typedef adjacency_list<vecS, vecS, undirectedS> UndirectedGraph;
typedef boost::graph_traits<UndirectedGraph>::edge_iterator edge_iterator;
int graph_show(UndirectedGraph &g);
int main(int argc, char *argv[])
{
UndirectedGraph g;
typedef boost::graph_traits<UndirectedGraph>::edge_descriptor edge_descriptor;
edge_descriptor ed;
std::vector<edge_descriptor> edge_list;
std::vector<std::vector<edge_descriptor> > graph_edge_list;
std::vector<UndirectedGraph> graph_list;
int nb=0;
int Nl=4;
bool inserted;
while(nb<Nl)
{
tie(ed,inserted)=add_edge(nb,nb+1,g);
edge_list.push_back(ed);
tie(ed,inserted)=add_edge(nb,nb+1,g);
edge_list.push_back(ed);
graph_edge_list.push_back(edge_list);
nb=nb+1;
graph_list.push_back(g);
}
std::cout<<"size of the graph vector is: "<<graph_list.size()<<std::endl;
remove_edge(graph_edge_list[0][0],graph_list[0]);//This is where the problem shows.
//I got Segmentation fault (core dumped)
//remove_edge(0,1,graph_list[0]);
/*Remove edges by assigning vertices works fine, but that is not what I need.*/
for (int ig = 0; ig < Nl; ++ig) {
std::cout<<"graph#"<<ig<<std::endl;
std::cout<<"Size of edge_list is: "<<graph_edge_list[ig].size()<<std::endl;
graph_show(graph_list[ig]);
}
std::cout<<"Success"<<std::endl;
return 0;
}
int graph_show(UndirectedGraph &g)
{
std::cout<<"Number of edges is : "<<boost::num_edges(g)<<std::endl;
std::cout<<"Number of vertices is : "<<boost::num_vertices(g)<<std::endl;
std::pair<edge_iterator,edge_iterator> ei=edges(g);
for (edge_iterator edge_iter = ei.first; edge_iter!=ei.second; ++edge_iter) {
std::cout<<"("<< boost::source(*edge_iter,g)<<","<<boost::target(*edge_iter,g)<<")"<<std::endl;
}
typedef boost::graph_traits<UndirectedGraph>::vertex_iterator iter_v;
std::cout<<"vertices(g)={ ";
for (std::pair<iter_v,iter_v> p = vertices(g); p.first != p.second; ++p.first) {
std::cout<< *p.first;
std::cout<<" ";
}
std::cout<<"}"<<std::endl;
return 0;
}
答案 0 :(得分:0)
这不是一个答案,但我尝试了代码,似乎问题出现在:
g.m_edges.erase(edge_iter_to_erase);
在第771行的adjacency_list.hpp中。
这似乎是一个错误。您可能需要查看提升邮件列表。
背景是:
template <>
struct remove_undirected_edge_dispatch<no_property> {
// O(E/V)
template <class edge_descriptor, class Config>
static void
apply(edge_descriptor e,
undirected_graph_helper<Config>& g_,
no_property&)
{
typedef typename Config::global_edgelist_selector EdgeListS;
BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
typedef typename Config::graph_type graph_type;
graph_type& g = static_cast<graph_type&>(g_);
no_property* p = (no_property*)e.get_property();
typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g));
typename Config::OutEdgeList::iterator out_i = out_el.begin();
typename Config::EdgeIter edge_iter_to_erase;
for (; out_i != out_el.end(); ++out_i)
if (&(*out_i).get_property() == p) {
edge_iter_to_erase = (*out_i).get_iter();
out_el.erase(out_i);
break;
}
typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
typename Config::OutEdgeList::iterator in_i = in_el.begin();
for (; in_i != in_el.end(); ++in_i)
if (&(*in_i).get_property() == p) {
in_el.erase(in_i);
break;
}
g.m_edges.erase(edge_iter_to_erase);
}
};
当我单步执行调试器时,它显示永远不会执行edge_iter_to_erase = (*out_i).get_iter();
。这会在调用vector erase方法时导致未定义的行为,因为该位置无效(我猜)。
如果仅使用g
代替graph_list[0]
,它也可以正常使用。
查看邮件列表中类似问题的here。他们使用不同的adjacency_list。
如果我将图表更改为:
typedef adjacency_list<vecS, vecS, undirectedS,no_property,no_property,no_property,setS> UndirectedGraph;
就像那篇文章一样。我得到访问读取违规而不是段错误。
看起来像一个bug,但我不知道为什么它会为矢量引用图而不是变量g执行此操作。