用std :: set替换std :: map并按索引搜索

时间:2014-05-28 12:44:01

标签: c++ boost vector stl set

假设我们有一个map,包含更大的对象和索引值。索引值也是较大对象的一部分。

我想知道的是,是否可以用map替换set,提取索引值。

通过提取索引值,可以很容易地创建一个set,在仿函数上对两个较大的对象进行排序。

通过索引值进行搜索,我认为默认情况下set不支持。

我在考虑使用std::find_if,但我认为线性搜索,忽略了我们设定的事实。

然后我考虑使用std::binary_search与仿函数比较较大的对象和值,但我相信它在这种情况下不起作用,因为它不会使用该结构并会使用遍历因为它没有随机访问迭代器。它是否正确?或者是否存在在set上正确处理此调用的重载?

然后我最后考虑使用boost::containter::flat_set,因为它有一个底层向量,因此可能应该能够与std::binary_search一起使用?

但也许有更简单的方法可以做到这一点?

在你回答之前只使用一张应该使用地图的地图 - 我实际上正在使用一个手动排序的矢量(好std::lower_bound)并且正在考虑用boost::containter::flat_set替换它,但是这样做似乎不太可能,所以我可能会坚持使用矢量。

3 个答案:

答案 0 :(得分:3)

C ++ 14将引入通过不需要构造整个存储对象的键进行查找的能力。这可以使用如下:

#include <set>
#include <iostream>

struct StringRef {
    StringRef(const std::string& s):x(&s[0]) { }
    StringRef(const char *s):x(s) { std::cout << "works: " << s << std::endl; }
    const char *x;    
};

struct Object {
    long long data;
    std::size_t index;
};
struct ObjectIndexer {
    ObjectIndexer(Object const& o) : index(o.index) {}
    ObjectIndexer(std::size_t index) : index(index) {}
    std::size_t index;
};
struct ObjComp {
    bool operator()(ObjectIndexer a, ObjectIndexer b) const { 
        return a.index < b.index; 
    }
    typedef void is_transparent; //Allows the comparison with non-Object types.
};

int main() {
    std::set<Object, ObjComp> stuff;
    stuff.insert(Object{135, 1});
    std::cout << stuff.find(ObjectIndexer(1))->data << "\n";
}

更一般地说,使用Boost.MultiIndex可以解决有多种索引数据方式的问题。

答案 1 :(得分:1)

使用boost::intrusive::set可以直接利用对象的索引值。它具有对数复杂度的find(const KeyType & key, KeyValueCompare comp)函数。还有其他基于展开树,AVL树,替罪羊树等的集合类型,根据您的要求可能会有更好的表现。

答案 2 :(得分:0)

如果将以下内容添加到包含的对象类型中:

  • 小于仅比较对象索引的运算符
  • 仅比较对象索引的等于运算符
  • 一个构造函数,它接受索引类型并使用索引值
  • 初始化一个虚拟对象

然后你可以将你的索引类型传递给find,lower_bound,equal_range等......它会按你想要的方式运行。当你将索引传递给set(或flat_set)的find方法时,它将构造一个包含类型的虚拟对象,用于比较。

现在,如果您的对象非常大,或构建成本高,那么这可能不是您想要的方式。