是否可以从std::set
中的O(log(n))
中随机选择一个元素,或者
O(1)
时间更好吗?它不需要非常均匀的分布,而只是相当随机的东西
(尽管显然更好)
看std::set::extract
似乎很有希望
因为它有可能在恒定时间内将set
分成两半,但是我找不到
确定靠近根节点的好方法,以及我可以的node_type
文档
找到的细节不多。
如果所有其他方法均失败,则可以使用我认为可以的随机密钥将内容复制到std::map
是O(n log(n))
时间,这将使我分期O(log(n))
时间,但这不是首选解决方案
因为在我不想要所有东西的情况下,这会需要一些开销
答案 0 :(得分:2)
如果集合中的元素本身在某个值域中均匀分布,那么您可以在该域中生成一个随机值,并使用std::set::lower_bound
获得集合中包含的第一个元素不少于比随机值。
鉴于您不需要非常均匀的分布,则对集合中元素的均匀性要求可能不是非常必要。选择一个元素的可能性取决于它与前一个元素的相对距离。
对于均匀分布,我认为没有比*std::next(std::begin(s), random_index)
更好的了,因为复杂度是线性的。
对于具有均匀分布和对数渐近复杂度的良好通用解决方案,您需要除std::set
之外的其他数据结构。
尤其是,Order statistic tree是一个不错的选择,它通过在节点中添加子树的大小来增强搜索树。 OST具有Select(i)
操作,类似于数组下标操作,您可以用相同的方法在索引0 ... N之间选择一个随机元素。
另一个选择是使用排序数组。可以使用sorted属性保留std::set
的对数查找属性。
不幸的是,标准库既没有订单统计树,也没有排序数组集。
答案 1 :(得分:0)
std :: set的复杂度为o(log(n)),因此,不能降低仅使用std :: set的搜索复杂度。您可以使用像矢量这样的索引结构来实现这一目标。
此外,您无法使用以下代码实现随机搜索:
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis( 0, set::size ( ) );
然后
set::operator [] (dis(gen));
或令人反感的