地图中的随机元素
Random element in a map
从映射中选择随机元素的好方法是什么?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 ];
当然,如果地图真的很大,你可能无法像这样存储所有密钥的副本。如果你能负担得起,尽管你可以在对数时间内获得查找的优势。
也许可以绘制一个随机密钥,然后使用lower_bound查找实际包含的最接近的密钥。
继续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)时间中的值,用向量索引获取常量时间中的随机对。您可以将矢量/二进制搜索包装为具有随机访问功能的地图。
也许你应该考虑Boost.MultiIndex,尽管注意它的权重有点太重。
以下是所有映射项必须按随机顺序访问的情况。
- 将贴图复制到矢量
- 无序播放矢量
在伪代码中(它密切反映了以下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;
}
有人试过这个吗?https://github.com/mabdelazim/Random-Access-Map"随机访问映射的C++模板类。这与std::map类似,但您可以使用语法my_map.key(i)和my_map.data(i)通过索引随机访问项"
std::random_device dev;
std::mt19937_64 rng(dev());
std::uniform_int_distribution<size_t> idDist(0, elements.size() - 1);
auto elementId= elements.begin();
std::advance(elementId, idDist(rng));
现在elementId是随机的:)
相关文章:
- 从C++数组中选择一个随机元素
- 用随机元素填充矢量
- Deque 中元素的随机访问如何提供恒定的时间复杂度?
- 尝试从列表中随机选取单个元素并将其显示为C++
- C++ STL 数据结构常时按索引推送/弹出/随机访问,并具有指向元素的可靠指针
- 将集合的随机元素添加到列表中,然后将其从原始集合中移除
- 我怎样才能在不重复的情况下随机迭代向量的每个元素
- 从长(且合理)稀疏向量中选择随机元素的最有效方法是什么?
- 更快地访问 C++ 数组中的随机元素
- 如何将 50 行和 50 列的二维数组编码为一个为元素随机分配星号的函数?
- 分割故障:从2D矢量中随机删除元素
- 从容器中获取随机元素,该容器在恒定时间内没有严格的元素顺序
- 随机生成一个没有重复元素的枚举数组 (C++)
- 随机(只读)访问 Eigen::SparseVector 的元素
- C++ 随机选择标准::矢量<标准::矢量的非空元素> >
- 选择C++地图中随机元素的百分比
- 用于随机访问和元素循环的最佳数据结构(C++)
- 以最新的C 的类型安全方式从枚举中随机选择元素
- 用固定数量的元素随机填充矢量的矢量
- 如何使用push_back将元素随机添加到向量中