在unordered_map中选择随机元素

时间:2014-11-19 18:29:49

标签: c++ prims-algorithm

我像这样定义unordered_map

std::unordered_map<std::string, Edge> edges;

是否有一种从unordered_map边缘选择随机Edge的有效方法?

5 个答案:

答案 0 :(得分:20)

Pre-C ++ 11解决方案:

std::tr1::unordered_map<std::string, Edge> edges;
std::tr1::unordered_map<std::string, Edge>::iterator random_it = edges.begin();
std::advance(random_it, rand_between(0, edges.size()));

C ++ 11向前解决方案:

std::unordered_map<std::string, Edge> edges;
auto random_it = std::next(std::begin(edges), rand_between(0, edges.size()));

选择有效随机数的功能取决于您的选择,但请确保在[0 ; edges.size() - 1]不为空时返回edges范围内的数字。

std::next函数只是以允许直接赋值的方式包装std::advance函数。

答案 1 :(得分:9)

  

是否有一种从unordered_map边缘选择随机Edge的有效方法?

如果有效你的意思是O(1),那么不,这是不可能的。

由于unordered_map::begin / end返回的迭代器是ForwardIterator s,所以简单地使用std::advance的方法在元素数量上是O(n)。

如果您的特定用途允许,您可以交换一些随机性以提高效率:

您可以选择随机存储桶(可以在O(1)中访问),然后选择该存储桶中的随机元素。

int bucket, bucket_size;
do
{ 
    bucket = rnd(edges.bucket_count());
}
while ( (bucket_size = edges.bucket_size(bucket)) == 0 );

auto element = std::next(edges.begin(bucket), rnd(bucket_size));

rnd(n)返回[0,n]范围内的随机数。

在实践中,如果你有一个像样的哈希,大多数桶将只包含一个元素,否则这个函数将略微保护其桶中单独的元素。

答案 2 :(得分:5)

这是你可以从地图中获取随机元素的方法:

std::unordered_map<std::string, Edge> edges;
iterator item = edges.begin();
int random_index = rand() % edges.size();
std::advance(item, random_index);

或者查看this answer,它提供了以下解决方案:

std::unordered_map<std::string, Edge> edges;
iterator item = edges.begin();
std::advance( item, random_0_to_n(edges.size()) );

答案 3 :(得分:1)

没有存储桶的严格O(1)解决方案:

  1. 保留一个键向量,当你需要从地图中获取一个随机元素时,从向量中选择一个随机键并从地图中返回相应的值 - 需要恒定时间
  2. 如果您在地图中插入键值对,请检查此键是否已存在,如果不是这样,请将该键添加到键矢量中 - 需要一段时间
  3. 如果要在选中后从地图中删除元素,请将您选择的键与键向量的back()元素交换并调用pop_back(),然后从地图中删除该元素并返回价值 - 需要一段时间
  4. 但是,有一个限制:如果你想从随机选择中删除地图中的元素,你需要修复你的关键向量,这需要采用天真的方法进行O(n)。但仍有一种方法可以获得O(1)性能:保留一张地图,告诉你键在关键向量中的位置并使用swap更新它:)

答案 4 :(得分:1)

解决方案

std::unordered_map<std::string, Edge> edges;
auto random_it = std::next(std::begin(edges), rand_between(0, edges.size()));

非常慢。...

一个更快的解决方案是:

  • 分配边缘时,将其键同时放置到std::vector<std::string> vec
  • 随机分配一个int index0的{​​{1}}
  • 然后得到vec.size() - 1