用于按排序顺序存储元素并允许快速索引的数据结构?

时间:2013-01-02 15:44:05

标签: c++ data-structures vector set

我需要一个已排序和索引的容器。我想基于std:set或std :: vector构建它。通过使用set,我需要昂贵的std :: distance来计算其元素的索引。通过使用向量,我知道添加或删除元素是昂贵的。假设我的元素是一个指针(小对象)。我知道两个操作的复杂性是相同的。但哪一个更快?感谢。

3 个答案:

答案 0 :(得分:3)

如果您需要一个支持排序顺序和按索引查找的数据结构,那么您一定要查看 order statistic tree ,这是一个专门用于支持这些操作的数据结构。它支持O(log n)时间中的插入和删除,O(log n)时间内元素索引的查找,以及O(log n)时间内按值或索引查找,因此它应该比矢量或集合接近。

不幸的是,STL没有构建它的订单统计树,因此您必须搜索第三方库(this earlier question and answer provides an example of one)。也就是说,您应该从订单统计树中获得的加速应该值得投资。

希望这有帮助!

答案 1 :(得分:2)

根据你们的建议,我把它测量为底部代码(添加了flat_set)。调试版本的结果是

for set:4.720976s wall,4.711230s user + 0.000000s system = 4.711230s CPU(99.8%) (也测试了set :: insert,花费的时间很少)

for vector:1.407571s wall,1.404009s user + 0.000000s system = 1.404009s CPU(99.7%)

for flat_set:0.327714s wall,0.327602s user + 0.000000s system = 0.327602s CPU(100.0%)

发布版本(我需要写出结果让编译器优化不要过度使用我的代码)给每个加速大约10倍。

我的结论是矢量快2-3倍,而boost flat_set是最好的。并且对于少于几百个(例如200个)的条目数,flat_set insert不比std :: set(没有w / o索引计算)慢。

int N = 10000;
{
    boost::timer::auto_cpu_timer t;
    std::set<int> s;
    for (int i = 0; i < N; ++i)
    {
        auto it = s.insert(i);
        int index = std::distance(s.begin(), it.first);
    }
}

{
    boost::timer::auto_cpu_timer t;
    std::vector<int> v;
    for (int i = 0; i < N; ++i)
    {
        v.insert(v.begin(), i);
    }
}

{
    boost::timer::auto_cpu_timer t;
    boost::container::flat_set<int> s;
    for (int i = 0; i < N; ++i)
    {
        auto it = s.insert(-i); // negative sign is used to make insertion
                                // (at the beginning) expensive
        int index = std::distance(s.begin(), it.first);
    }
}

答案 2 :(得分:0)

分隔存储和索引:

有一个整数向量{I},用于索引对象类型{T}的存储向量。

{I}通过它在{T}中指向的对象之间的比较进行排序。 插入/删除{I}比{T}更便宜。

每当向{T}向量添加新项时,都会将其索引插入到已排序的{I}中。

当你删除一个项目时,删除{I}中的索引,但你可以保持{T}中的对象不受影响,只需将刚刚删除的索引推回到重用向量{I'}。下次添加新项目时,可以在{I'}中弹出__并重新使用存储。

如果您知道所使用的项目数,可以在启动时调用{T}上的resize()以避免在运行时(重新)分配。

此方法与使用指针向量类似,优点是动态分配较少,缓存更友好,因为对象存储位于连续内存中。