地图中的随机元素
时间:2020-03-06 14:59:20 来源:igfitidea点击:
从地图中选择随机元素的好方法是什么? C ++。据我了解,地图没有随机访问迭代器。关键是很长很长,并且地图上的人口稀少。
解决方案
map<...> MyMap; iterator item = MyMap.begin(); std::advance( item, random_0_to_n(MyMap.size()) );
如果地图很小或者我们不需要经常使用随机值,我会喜欢James的回答。如果它很大,并且我们经常进行此操作以使速度变得重要,那么我们也许可以保留一个单独的键值向量以从中选择一个随机值。
map<...> MyMap; vector<...> MyVecOfKeys; // <-- add keys to this when added to the map. map<...>::key_type key = MyVecOfKeys[ random_0_to_n(MyVecOfKeys.size()) ]; map<...>::data_type value = MyMap[ key ];
当然,如果地图真的很大,我们可能无法像这样存储所有键的副本。如果我们负担得起,尽管可以在对数时间内获得查找的优势。
也许我们应该考虑Boost.MultiIndex,尽管请注意它的权重有点太重了。
也许绘制一个随机密钥,然后使用lower_bound查找实际包含的最接近的密钥。
在这种情况下,必须以随机顺序访问所有地图项。
- 将地图复制到向量。
- 随机播放矢量。
用伪代码(它紧密反映了以下C ++实现):
import random
import time
# populate map by some stuff for testing
m = dict((i*i, i) for i in range(3))
# copy map to vector
v = m.items()
# seed PRNG
# NOTE: this part is present only to reflect C++
r = random.Random(time.clock())
# shuffle vector
random.shuffle(v, r.random)
# print randomized map elements
for e in v:
print "%s:%s" % e,
print
在C ++中:
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/foreach.hpp>
#include <boost/random.hpp>
int main()
{
using namespace std;
using namespace boost;
using namespace boost::posix_time;
// populate map by some stuff for testing
typedef map<long long, int> Map;
Map m;
for (int i = 0; i < 3; ++i)
m[i * i] = i;
// copy map to vector
#ifndef OPERATE_ON_KEY
typedef vector<pair<Map::key_type, Map::mapped_type> > Vector;
Vector v(m.begin(), m.end());
#else
typedef vector<Map::key_type> Vector;
Vector v;
v.reserve(m.size());
BOOST_FOREACH( Map::value_type p, m )
v.push_back(p.first);
#endif // OPERATE_ON_KEY
// make PRNG
ptime now(microsec_clock::local_time());
ptime midnight(now.date());
time_duration td = now - midnight;
mt19937 gen(td.ticks()); // seed the generator with raw number of ticks
random_number_generator<mt19937,
Vector::iterator::difference_type> rng(gen);
// shuffle vector
// rng(n) must return a uniformly distributed integer in the range [0, n)
random_shuffle(v.begin(), v.end(), rng);
// print randomized map elements
BOOST_FOREACH( Vector::value_type e, v )
#ifndef OPERATE_ON_KEY
cout << e.first << ":" << e.second << " ";
#else
cout << e << " ";
#endif // OPERATE_ON_KEY
cout << endl;
}
预先构建的映射和快速随机查找的ryan_s主题继续:代替矢量,我们可以使用并行的迭代器映射,这应该会加快随机查找的速度。
map<K, V> const original;
...
// construct index-keyed lookup map
map<unsigned, map<K, V>::const_iterator> fast_random_lookup;
map<K, V>::const_iterator it = original.begin(), itEnd = original.end();
for (unsigned i = 0; it != itEnd; ++it, ++i) {
fast_random_lookup[i] = it;
}
// lookup random value
V v = *fast_random_lookup[random_0_to_n(original.size())];
如果地图是静态地图,请使用向量而不是地图,而是使用向量以键顺序存储键/值对,使用二进制搜索以log(n)时间查找值,并使用向量索引以恒定时间获取随机对。我们可以包装矢量/二进制搜索,使其看起来像具有随机访问功能的地图。

