如何从 O(1) C++哈希表中随机检索元素
How to random retrieve an element from C++ hash table in O(1)
有没有办法从 O(1) 平均时间C++unordered_set中随机检索元素?而不是做
std::unordered_set<int> s;
// initialize s
auto start = s.begin();
for (int i = 0; i < rand()%s.size()-1; ++i, ++start) {}
int randomNumber = *start;
更新:
我需要为这个职位而战,所以我添加了我需要上述功能的原因。
我正在玩实现迷宫生成器。不知何故,我需要一个支持以下数据结构:
- 在O(1)中插入/删除
- 从 O(1) 中的数据结构中随机检索元素
std::vector 具有随机访问功能,但插入/删除成本高昂
std::list 没有随机访问
std::set 支持 O(logN) 随机访问和 O(logN) 插入/删除,这很棒,但我的初始化是一个排序序列,很容易打破它的平衡。
所以我认为哈希表将是最好的选择,但是随机检索元素是不平凡的。
谢谢你的时间。
你不能在 O(1) 时间内从unordered_set
中随机选择一个元素。迭代器是 ForwardIterator
s,而不是 RandomAccessIterator
s。您必须使用其他容器。要么boost::container::flat_set<int>
,要么编写自己的,内部也有类似vector
的东西:
template <typename T>
class set_with_random_access
{
std::vector<T*> vec;
std::unordered_set<T> set;
};
为此,我们提供了使这些功能保持一致的功能,例如插入:
void insert(const T& value) {
auto pr = set.insert(value);
if (pr.second) {
vec.push_back(&*pr.first);
}
}
和随机性:
template <typename GEN>
T& random(GEN& gen) {
std::uniform_int_distribution<size_t> dist(0, vec.size() - 1);
return *vec[dist(gen)];
}
坦率地说,这是很多工作,所以可能会使用助推器。
一种从 O(1) 平均时间的C++
unordered_set
中随机检索元素的方法?
取决于什么算作你的目的的"随机",以及高于 O(1) 的一点点是否足够好。 您可以在 0
和 s.bucket_count() - 1
之间选择一个随机的桶"b
",如果桶为空,则重复,然后在 0
和 s.bucket_size(b) - 1
之间li
列表索引,然后std::advance(s.begin(li))
将迭代器获取到"随机"元素,但是,请考虑这种情况:
你掷三个骰子 - 然后随机选择其中一个:你得到一个随机的 1-6 值,概率均匀,但如果你继续掷而不再次掷,你只能得到三个骰子上最终的任何值:从 1 到 6 的每个值的概率严重不均匀。
上面在unordered_set
中随机选择元素的方法有点像:如果有x
个带有元素的存储桶,那么每个存储桶都有被选择的机会,但该存储桶中的元素1 / x / bucket_size()
选择的机会,对于任何给定的存储桶 - 可能小于或大于 1 / size()
。 换句话说,如果您认为散列实际上是随机的,那么各种元素在其放置中都有同样的机会受到青睐或惩罚,但是这种"偏斜"会让它变得一成不变,直到表数据显着变异或表被重新散列(如果它通过加倍表大小而不是更大的质数(unordered_set
加倍的模糊内存)来重新散列), 那么一旦受到惩罚的值往往会在一半时间内保持惩罚)。
上述 big-O 效率比 O(1) 略高,因为:
-
在初始探测中有一些重复来找到一个带有元素的桶,但是负载因子为 1.0 时,它不太可能需要超过几次尝试(给定一个好的哈希函数);其他选项是可用的 - 例如从空桶迭代,或按各种位移跳转(修改为表大小) - 这可能比尝试另一个完全随机的桶表现得更好一些,但也可能会加剧几率的差异元素选择
-
在任何给定存储桶中碰撞的元素中都有线性迭代,但由于默认负载系数为 1.0,因此很少发生超过几次碰撞的情况,并且越来越罕见地发生更多碰撞的情况。
从std::unordered_set
中随机选择一个元素是一个坏主意。这是因为std::unordered_set
不支持随机访问,因此没有下标运算符(即operator[]
)。
我坚信,您需要的是结合std::unique
的std::vector
,以满足元素的独特性。
在下面的示例中,我使用了一个std::vector
,然后通过对其应用std::unique
算法来确保它只有唯一的元素。然后我使用 random
实用程序来生成 [0, 向量的大小 - 1] 中的随机索引:
std::vector<int> v{1, 2, 8, 3, 5, 4, 5, 6, 7, 7, 9, 9, 19, 19};
v.erase(std::unique(v.begin(), v.end()), v.end());
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0, v.size() - 1);
std::cout << "Random number from vector: " << v[distribution(generator)] << std::endl;
现场演示
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 用C++将哈希表写入文件并从文件中恢复
- C++中的并发哈希表
- 在具有开放寻址的哈希表中插入节点 [优化逻辑]
- 与C++哈希表的基础知识混淆
- 调整大小和复制哈希表数组中的元素
- 带链接的基本哈希表
- C++哈希表中,两个相同的实现,但一个给出错误
- 如果索引不是整数,我们如何在 C++ 中插入哈希表
- 查找项目在哈希表中的位置
- 为什么C++ STL 哈希表 (unordered_map) 不接受向量作为键
- C++哈希表 - 如何解决自定义数据类型作为键的unordered_map冲突?
- 使用哈希表设置实现
- 同时写入和读取哈希表
- 在 C++ 中为特定哈希表创建插入函数
- 我可以比朴素哈希表更快地将随机字符串映射到两个类吗?
- 如何从 O(1) C++哈希表中随机检索元素
- 如何存储需要随机选择和删除的数据,矢量,哈希表或其他
- 如何散列字符串?我需要把随机字符串转换成整数,放到哈希表中