如果随机访问很重要,并且您可以忍受 O(N) 平均插入工作量,那么this paper 中给出的解决方法可能很方便。
主要思想是使用排序向量,然后查找函数std::lower_bound。就像在正常集合中一样,查找需要 O(log N)。此外,(随机)插入需要 O(N),因为所有后续元素必须像在法线向量中一样移动(并且可能执行重新分配)。然而,在后面的插入是恒定的(除了重新分配。您可以通过调用reserve() 来避免这种情况,并具有足够大的存储空间)。
最后,问题的重点:随机访问是O(1)。 只需从[0, V.size()-1]中的均匀分布中抽取一个随机数i,并返回对应的元素@ 987654327@。
这是论文中的代码基础,它实现了这个排序的向量。根据需要扩展它:
template <class T, class Compare = std::less<T> >
struct sorted_vector {
using std::vector;
using std::lower_bound;
vector<T> V;
Compare cmp;
typedef typename vector<T>::iterator iterator;
typedef typename vector<T>::const_iterator const_iterator;
iterator begin() { return V.begin(); }
iterator end() { return V.end(); }
const_iterator begin() const { return V.begin(); }
const_iterator end() const { return V.end(); }
//...if needed, implement more by yourself
sorted_vector(const Compare& c = Compare()) : V(), cmp(c) {}
template <class InputIterator>
sorted_vector(InputIterator first, InputIterator last, Const Compare& c = Compare())
: V(first, last), cmp(c)
{
std::sort(begin(), end(), cmp);
}
//...
iterator insert(const T& t) {
iterator i = lower_bound(begin(), end(), t, cmp);
if (i == end() || cmp(t, *i))
V.insert(i, t);
return i;
}
const_iterator find(const T& t) const {
const_iterator i = lower_bound(begin(), end(), t, cmp);
return i == end() || cmp(t, *i) ? end() : i;
}
};
对于更复杂的实现,您还可以考虑this page。
编辑:或者更好的是,使用boost::container::flat_set,它使用上面的想法实现集合,即作为排序向量。