在unordered_map中选择随机元素
Select random element in an unordered_map
我定义了一个这样的unordered_map
:
std::unordered_map<std::string, Edge> edges;
有没有一种有效的方法可以从unordered_map边中选择随机边?
O(1) 解决方案(除非你只有一个边):
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()));
选择有效随机数的函数由您选择,但请确保它在edges
不为空时返回范围内[0 ; edges.size() - 1]
范围内的数字。
std::next
函数只是以允许直接赋值的方式包装std::advance
函数。
有没有一种有效的方法可以从unordered_map边中选择随机边?
如果你所说的效率是指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) 范围内的随机数。
实际上,如果你有一个不错的哈希值,大多数桶将只包含一个元素,否则这个函数将稍微特权那些单独存在于其桶中的元素。
没有存储桶的严格 O(1) 解决方案:
- 保留一个键向量,
- 当你需要从地图中获取一个随机元素时,从向量中选择一个随机键并从地图中返回相应的值 - 需要恒定时间
- 如果您在映射中插入键值对,请检查该键是否已经存在,如果不是这种情况,请将该键添加到您的键向量中 - 需要恒定时间
- 如果要在选择元素后从映射中删除该元素,请将您选择的键与键向量的 back() 元素交换并调用 pop_back),然后从映射中删除该元素并返回值 - 需要恒定时间
但是,有一个限制:如果你想从地图中删除元素而不是随机选择,你需要修复你的键向量,这需要 O(n) 和幼稚的方法。但是仍然有一种方法可以获得 O(1) 性能:保留一个地图,告诉您密钥在密钥向量中的位置,并使用交换:)对其进行更新
这是从地图中获取随机元素的方法:
std::unordered_map<std::string, Edge> edges;
iterator item = edges.begin();
int random_index = rand() % edges.size();
std::advance(item, random_index);
或者看看这个答案,它提供了以下解决方案:
std::unordered_map<std::string, Edge> edges;
iterator item = edges.begin();
std::advance( item, random_0_to_n(edges.size()) );
的解决方案
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 index
范围从0
到vec.size() - 1
- 然后得到
edges[vec[index]]
你可以看到这个问题:
问题 380.插入删除 获取随机 O(1)您可以构建一个向量来使用向量随机迭代器,更有效地获取随机值。喜欢这个:
class RandomizedSet {
public:
unordered_map<int, int> m;
vector<int> data;
RandomizedSet() {
}
bool insert(int val) {
if(m.count(val)){
return false;
} else{
int index = data.size();
data.push_back(val);
m[val] = index;
return true;
}
}
bool remove(int val) {
if(m.count(val)){
int curr_index = m[val];
int max_index = data.size()-1;
m[data[max_index]] = curr_index;
swap(data[curr_index], data[max_index]);
data.pop_back();
m.erase(val);
return true;
} else{
return false;
}
}
int getRandom() {
return data[rand() % data.size()];
}
};
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
- 从C++数组中选择一个随机元素
- 通过选择 2 个随机值来优化表达式
- 如何更改此notify_one以便它选择一个随机线程
- 选择随机字符串数组的排序
- C++ 在运行时选择一个随机对象
- 如何从文件夹树中快速选择随机文件?
- 从长(且合理)稀疏向量中选择随机元素的最有效方法是什么?
- 如何在QT中设置样式表以选择假发背景的随机图像
- 随机选择 2 个不在范围内的整数
- 在C++中随机选择子类
- 如何从图形的邻接列表表示中随机选择边缘
- 回溯到sudoku求解每次选择随机单元和随机值的逻辑
- 如何有效地从std::集中选择随机元素
- 为多映射中的特定键选择随机元素
- 用于选择随机子集的通用算法实现
- 在unordered_map中选择随机元素
- 使用c++从.dat文件中选择“随机行”
- 从结构向量中选择随机结构
- 如何使用向量中的信息填充数组并从数组中选择随机项
- 有没有比这更好的方法从可变大小的数组中选择随机元素