【发布时间】:2013-03-03 18:09:22
【问题描述】:
如何在 c++ 中获取 std::map 的随机密钥?使用迭代器? 我不想维护额外的数据结构
【问题讨论】:
如何在 c++ 中获取 std::map 的随机密钥?使用迭代器? 我不想维护额外的数据结构
【问题讨论】:
std::map 迭代器是双向的,这意味着选择随机键将是O(n)。在不使用其他数据结构的情况下,基本上您唯一的选择是使用std::advance,并从begin() 随机递增。例如:
std::map<K, V> m;
auto it = m.begin();
std::advance(it, rand() % m.size());
K random_key = it->first;
(或者如果您有权访问<random>,则将rand() 替换为(例如)std::mt19939)。
【讨论】:
std::next。 :)
std::next吗?为什么它会比std::advance 更好(或不同)?
std::advance”的评论在技术上并不正确(但实际上是正确的选择)。
std::advance(和std::next)的复杂性通常是线性的,但如果容器具有随机访问权限,则为常数,例如std::vector。因此,这是从容器中获取随机元素而不影响性能的一种非常好的完全通用的方法。
这取决于您的目的是随机的。 std::map 是一个排序容器,但不支持按元素编号随机访问。鉴于这一点以及对一组键的了解,您可以使用lower_bound 或upper_bound 随机选择一个点来挖掘地图,以在附近找到一个元素。这倾向于根据元素与地图中其他元素之间的间隙来继续选择元素,这意味着如果元素/间隙本身是有效随机的,则初始结果可能被认为是有效随机的,但随机元素的重复选择不会是均匀分布。
例如,假设您的键是大写字母,而键“C”、“O”、“Q”和“S”在地图中。如果你从 AZ 生成一个随机字母,你最终会比 Q 更有可能最终出现在 C、O 或 S 上,因为只有 PQR 在 Q 附近并且使用上限或下限你最终会选择其中两个,所以尽管只有 4 个元素,但有 2/26 的机会。不过,如果一开始对 C、O、Q 和 S 的选择存在一些随机性,您可能会认为差距和选择是随机的。
您可以通过像这样插入容器,然后执行少量随机数的迭代器递增/递减来改进这一点,但它仍然不是真正随机的。
真正随机的结果需要逐一遍历列表或您要避免的二级索引容器。
【讨论】: