【问题标题】:How sets, multisets, maps and multimaps work internally集合、多重集、映射和多重映射如何在内部工作
【发布时间】:2010-11-17 06:22:29
【问题描述】:

多重集如何工作?如果一个集合不能有一个值映射到一个键,它是否只包含键?

另外,关联容器是如何工作的?我的意思是内存中的向量和双端队列是顺序定位的,这意味着如果它们很大,删除/删除(除了开始[deque]和结束[vector,deque])会很慢。

而列表是一组指针,它们不是按顺序位于内存中的,这会导致搜索时间更长,但删除/删除速度更快。

集合、映射、多重集合和多重映射如何存储以及它们如何工作?

【问题讨论】:

  • STL 基本上是模板代码,整个源代码在头文件中可用。您可以获取特定代码并检查内部实现
  • 我认为对于初级程序员来说,理解标头实现的模板代码并不容易。但我认为几乎所有 C++ 书籍都描述了大多数容器的一般概念和用例。
  • 阅读关联容器后不在 Primer C++ 中。没有关于性能和解释它内部如何工作的线索:(

标签: c++ data-structures stl dictionary set


【解决方案1】:

所有关联容器类(map、multi-map、set、multi-set)都是用红黑(R-B 树)树实现的。所以 R-B 树的实现可能是这样的:-

struct Rb_node {
    int value;
    struct node *left, *right;
    int color;
    int size;
};

【讨论】:

  • 您的代码 sn-p 实际上并没有显示任何实现,只是数据结构。实现是所有工作完成的地方,也是 RB 树的用处所在。
【解决方案2】:

这 4 个容器通常都使用“节点”实现。节点是存储一个元素的对象。在 [multi]set 的情况下,元素就是值;在 [multi]map 的情况下,每个节点存储一个键及其关联的值。一个节点还存储多个指向其他节点的指针。与列表不同,集合和映射中的节点形成一棵树。您通常会安排它,使某个节点“左侧”的分支具有小于该节点的值,而某个节点“右侧”的分支具有高于该节点的值。

查找地图键/设置值等操作现在非常快。从树的根节点开始。如果匹配,你就完成了。如果根较大,则在左分支中搜索。如果根小于您要查找的值,请按照指向右分支的指针。重复直到找到一个值或一个空分支。

插入元素是通过创建一个新节点来完成的,在树中找到应该放置它的位置,然后通过调整节点周围的指针将节点插入那里。最后,还有一个“重新平衡”操作,以防止您的树最终完全失去平衡。理想情况下,每个左右分支的大小大致相同。重新平衡通过将一些节点从左向右移动来工作,反之亦然。例如。如果你有值 {1 2 3} 并且你的根节点是 1,那么你在左分支上有 2 和 3,右分支是空的:

1
 \
  2
   \
    3

通过选择 2 作为新的根节点来重新平衡:

  2
 / \
1   3

STL 容器使用更智能、更快速的重新平衡技术,但这种详细程度无关紧要。它甚至没有在标准中指定应该使用哪种更好的技术,因此实现可能会有所不同。

【讨论】:

  • 那么,所有这些容器都是使用AVL trees实现的吗?
  • @Jos:“标准中甚至没有指定应该使用哪种技术,因此实现可能会有所不同。”。
【解决方案3】:

可以有任何实现,只要它们符合这些容器的标准规范。

AFAIK,关联容器实现为二叉树(红黑)。更多细节...取决于实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    相关资源
    最近更新 更多