由于C ++ STL set / map被实现为红黑树,因此不仅可以在 O中执行insert
,delete
和find
(log n)时间,还有getMin
,getMax
,getRandom
。据我所知,前两个在begin()
和end()
中有等价物(这是正确的吗?)。最后一个怎么样?我怎么能这样做?
我到目前为止唯一的想法是使用随机参数advance
,但这需要线性时间......
编辑:'随机'应指均匀分布
答案 0 :(得分:8)
begin()
等同于getMin
操作,但end()
会返回超过最大值的迭代器,因此它是rbegin()
。
至于getRandom
:假设你的意思是以均匀概率随机获取任何项目,这可能在AVL树中的O(lg n )时间内,但我不是看看如何在红黑树中有效地做到这一点。您如何知道给定节点左右有多少个子树而不计算 n / 2 = O( n )时间?由于std::set
和std::map
不能直接访问其基础树,您将如何遍历它?
我看到三种可能的解决方案:
vector
,map
或set
中的元素与其平行; 修改:Boost.Intrusive也可以解决问题。
答案 1 :(得分:0)
是,begin和rbegin(not end!)分别是最小和最大键值。
如果您的密钥很简单,例如一个整数,你可以创建一个[min,max)范围内的随机整数(使用),然后获取地图的lower_bound
。
答案 2 :(得分:0)
如您怀疑begin()
,end() - 1
或rbegin()
将获得最小值和最大值。我无法看到任何方法在这样的树中统一获取随机元素。但是你有几个选择:
答案 3 :(得分:0)
如果您在集合或地图中均匀分布值,则可以选择最小值和最大值之间的随机值,并使用lower_bound
查找与其最接近的值。
如果插入和删除不常见,您可以使用向量代替并根据需要对其进行排序。填充向量并对其进行排序所需的时间与填充集合或映射的时间大致相同;它甚至可能更快,你需要测试它才能确定。那时选择一个随机元素将是微不足道的。
答案 4 :(得分:0)
我认为你可以用STL实际做到这一点,但它有点复杂。
您需要维护地图。每个都带有1..N
的密钥(N是元素的数量)。
因此,每次需要使用随机元素时,从1..N
生成随机数,然后使用所选键在地图中查找元素。这是你选择的元素。
之后,您需要通过查找最大元素来维护地图的一致性,并使用您刚刚选择的随机数更新其密钥。
由于每个步骤都是log(n)
操作,因此总时间为log(n)
。
答案 5 :(得分:0)
所以基本的想法是拥有所有现有密钥的连续数组。