【问题标题】:C++ associative container with two search criteria具有两个搜索条件的 C++ 关联容器
【发布时间】:2012-04-07 22:43:05
【问题描述】:

我正在寻找一个用于存储我的类对象的容器,称为 Link,它有一个成员变量:“std::string linkID”。容器的大小可以高达数百万,因此更优选快速查找。 1-稍后我需要使用 linkID 查找容器 2-但是,由于某些原因,添加对象的顺序也很重要。

我已经学习了vector、list、set、map...,我将学习muliset、multimap 和boost multi index。但我想,作为 C++ 新手,我仍然需要一些更有经验的意见来帮助我根据上述两个标准选择最佳容器。

谢谢 虚无

【问题讨论】:

    标签: c++ boost stl associative-array


    【解决方案1】:

    对我来说,这看起来是 boost::multi_index_container 的完美用例

    您的类型声明应该与此类似(未经测试)

    typedef multi_index_container<
        Link,
        indexed_by<
            sequenced<>,
            ordered_unique< member< Link, std::string, &Link::linkID> >,
            ordered_unique< member< Link, std::string, &Link::linkID_2 > >
        >
    > LinkList;
    LinkList s;
    s.push_back(Link(...));
    

    通常与 Frerich Raabe 发布的解决方案相同。但我认为陷阱更少,并且可能更优化。 阅读 boost 页面上的tutorial,了解如何访问存储在 s 中的元素。

    您的评论...

    实际上,我正在开发一个已经存在的项目,其中他们 已使用 std::vector 仅存储元素(如您所指 出去)。所以现在我可以按原样使用“存储”向量并添加 你建议的地图?

    这是不可能的。矢量迭代器保持无效。当您向向量添加或删除元素时,它们可能会变得未定义。

    【讨论】:

    • thanx,我明天会测试并发布结果
    • 嗨,Smittii,我希望你还在关注这个。我花了一些时间来提升,所以我今天正在尝试你的解决方案。好的,关于你上面的代码 sn-p,我想确保我得到它是否正确:1-“sequenced”部分会帮助我按插入顺序遍历 Link 对象,并且 2-"ordered_unique >" 将帮助我按 Link::linkID 的升序访问对象。这两种说法都是真的吗?如果是,这是我的确切解决方案。否则,我应该如何修改代码以使这两个条件都成立?tanx
    • 我不知道你所说的“真实陈述”是什么意思。容器就像您描述的那样工作。您可以通过您在 indexed_by 模板中定义的所有机制访问元素。
    【解决方案2】:

    如果您用来查找链接的属性不经常更改,您可以选择std::list&lt;Link&gt; 作为保存链接对象的主要容器。然后,对于每个标准,您都有一个std::map,它将一个值映射到指向列表的迭代器。例如

    typedef std::list<Link> LinkList;
    
    LinkList links = ...;
    std::map<std::string, LinkList::iterator> linkByName;
    std::map<unsigned int, LinkList::iterator> linkByPopularity;
    

    std::list 的好处在于它具有非常强大的迭代器失效保证(基本上,只有从列表中删除元素时,您进入列表的迭代器才会失效)。

    为了使这些结构保持一致更新,您可以将它们全部包装到一个“LinkCollection”包装器中。

    【讨论】:

    • 与 std::set 相比,std::list 不慢吗?如果是,我可以在您的示例中将 std::list 替换为 std::set 吗?
    • @rahman:这个想法是std::list 仅用于存储元素,而不是用于访问它们。然后,您可以使用将迭代器保存到列表中的其他容器来实际访问元素。因此,如果您需要一种按索引快速访问元素的方法,您可以使用std::vector&lt;LinkList::iterator&gt;
    • :知道了。你提出了一个很好的观点,让我问了另一个简单的问题,可以以更好的方式解决我的问题。实际上,我正在开发一个已经存在的项目,其中他们使用 std::vector 仅存储元素(因为你指出)。那么现在我可以按原样使用“存储”向量并按照您的建议添加地图吗?这样,我将很乐意提高性能,而无需承担用列表替换该向量的负担。
    • @rahman:使用std::vector 存储对象的问题是指向向量的迭代器很快就会失效(例如,如果将元素添加到向量中,向量可能会使所有迭代器失效,或者它使您要删除的某个元素之外的所有迭代器无效)。这就是为什么使用std::list 进行存储很方便的原因。
    • 感谢您的帮助。我稍后会发布结果。其他人推荐来自 boost 的多索引与您的解决方案相似。任何cmets
    【解决方案3】:

    这听起来很适合使用Boost Bimap

    【讨论】:

    • 我查看了您发送的链接。好吧,我知道我提到了 order 和 linkID 作为我的查找条件。所以定义 boost::bimap (Link.linkID 的左值和 order 的右值),1-实际对象(Link*)将存储在哪里? 2-在填充该对的第二个值时,我不会保留一个计数器来使用它。我需要像vector的push_back这样的东西。任何想法我可以如何使用 bimap>
    猜你喜欢
    • 2019-06-03
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 2011-03-21
    • 2014-12-03
    相关资源
    最近更新 更多