C++ 在Boost图库中选择给定顶点的随机进出邻域的有效方法?
我需要使用Boost图形库从图形中的给定顶点中随机选择出邻居或入邻居。我从RNG收到一个索引I,需要选择第I个输出边缘(它们可以是任意顺序,只需要在调用之间保持一致)。为此,我使用了C++ 在Boost图库中选择给定顶点的随机进出邻域的有效方法?,c++,boost,boost-graph,C++,Boost,Boost Graph,我需要使用Boost图形库从图形中的给定顶点中随机选择出邻居或入邻居。我从RNG收到一个索引I,需要选择第I个输出边缘(它们可以是任意顺序,只需要在调用之间保持一致)。为此,我使用了std::advance如下: typedef adjacency_list<vecS, vecS, bidirectionalS> Graph; Graph g; // Given graph int i; int v; // Given vertex // // Code to generate ra
std::advance
如下:
typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
Graph g; // Given graph
int i;
int v; // Given vertex
//
// Code to generate random index (guaranteed to be valid) and store it in i
//
typename graph_traits < graph_t >::in_edge_iterator ei, ei_end;
tie(ei,ei_end) = in_edges(v,g);
std::advance(ei,i);
// Now ei points to the ith out edge, and is ready to use
// Return the corresponding in-neighbor
return source(*ei,g);
typedef邻接列表图;
图g;//给定图
int i;
int v;//给定顶点
//
//生成随机索引(保证有效)并将其存储在i中的代码
//
typename graph\u traits:在边迭代器ei中,ei\u end;
连接(ei,ei_端)=in_边(v,g);
标准:预付款(ei,i);
//现在ei指向第i个out边缘,可以使用了
//返回邻居中相应的
返回源(*ei,g);
现在这工作正常,我得到了正确的输出。但是,我需要知道这是否有效,也就是说,std::advance
是否会在固定时间内工作,而不考虑I
的值,因为我使用了vecS
来存储邻接列表?如果没有,有没有有效的方法
我应该提到的是,我只需要选择一个随机的in-neighbor或out-neighbor,因此如果您有一种方法可以在不处理边缘的情况下实现这一点,那也将非常好。如果您想确保
advance(ei.I)
是o(1)
,您可以简单地添加一个static\u assert
:
static_assert(
std:::is_base_of<
std::random_access_iterator_tag,
typename std:::iterator_traits< decltype(ei) >::iterator_category
>::value,
"Not a random access iterator!" )
static\u断言(
std:::是的基础吗<
std::随机访问迭代器标记,
typename std::迭代器特征::迭代器类别
>::价值,
“不是随机访问迭代器!”)
如果ei
不是随机访问迭代器,则编译将失败
至于实际问题,拥有
OutEdgeList
(邻接列表中的第一个模板参数)=vecS
就足以随机访问out\u边
。我相信没有指定由_edges中的返回的迭代器是否为随机访问。我尝试将迭代器作为指针递增,但它仍然有效。我换了
std::advance(ei,i);
与
现在它在i
中以恒定时间运行,用于输入和输出边缘迭代器。然而,前者在i
中需要线性时间
出于某种原因,尽管我可以像上面那样进行随机访问,但另一个答案中描述的检查迭代器是否为随机访问失败。感谢您的回答。有趣的是,断言对于out和in边都失败了。考虑到外边缘被明确认为是随机访问,这种情况会发生吗?有没有另一种方法可以有效地选择一个随机的邻居(不需要通过边进行迭代)?我刚刚用一个简单的基准测试确认了这两种迭代器都不是随机访问的;在索引中,访问时间是线性的。即使我尝试使用邻接迭代器(断言也失败),这似乎也是正确的。out\u边
清楚地表明,如果使用vecS
,返回的迭代器应该是随机访问的。。所以现在我很困惑,我只是试着用ei+=I
来看看它是否有效,让我惊讶的是它确实有效。此外,它似乎是O(1)太为进出口边缘。这让我认为迭代器不是基于std的随机访问\u迭代器,而是内部随机访问。因此断言将失败,因为我们只检查std类型。会是这样吗?
ei+=i;