【问题标题】:Indices instead of pointers in STL containers?STL容器中的索引而不是指针?
【发布时间】:2010-04-23 06:43:26
【问题描述】:

由于特定要求 [*],我需要一个使用整数索引而不是指向链接节点的指针的单链表实现。索引总是相对于包含列表节点的向量进行解释。

我想我可以通过定义我自己的分配器来实现这一点,但是查看 gcc 的实现,他们明确地使用了列表节点中链接字段的指针(即,他们不使用分配器提供的指针类型) :

  struct _List_node_base
  {
    _List_node_base* _M_next;   ///< Self-explanatory
    _List_node_base* _M_prev;   ///< Self-explanatory
    ...
  }

(为此,分配器接口的不足之处还在于它没有定义解引用函数;“解引用”整数索引总是需要指向底层存储的指针。)

你知道一个类似 STL 的数据结构库(我主要需要单链表和双链表),它使用索引(一个基向量)而不是指向链接节点的指针吗?

[*] 节省空间:列表将包含 许多 32 位整数。每个节点有两个指针(STL 列表是双向链接的),开销为 200%,或在 64 位平台上为 400%,不计算默认分配器的开销。

编辑:我正在寻找一个以下列方式定义节点的 SLL 实现:

  struct list_node
  {
    int _value;  ///< The value in the list
    int _next;   ///< Next node in the list
    ...
  }

_next 被解释为 wrt。隐式数组或向量(必须在外部提供给对列表进行操作的每个方法)。

EDIT2:经过一番搜索,我发现该标准实际上要求旨在与标准集合一起使用的分配器必须将指针类型定义为与 T* 等效。

【问题讨论】:

  • 请注意,对于许多 32 位整数 (=100000?),您的索引可能还需要为 32 位。
  • 是的,索引将是 32 位。它仍然是 64 位拱形指针大小的一半。
  • 为什么需要使用这个奇特的列表而不是直接使用向量或双端队列?这将完全减少每个元素的开销。
  • @Mark B:与想要使用链表的原因相同:在列表中的任何位置进行恒定时间插入和删除。

标签: c++ stl


【解决方案1】:

您为什么使用 STL 列表?除非您有非常特定要求,否则您应该改用vectordeque。如果您使用列表的原因是为了提高插入效率,您应该注意 deque 提供了 listvector 的大部分优点,因为它不需要维护连续存储,而是使用数组底层存储介质。

编辑:关于您对提供operator[] 的列表的渴望,这样的结构不存在(至少不存在并且仍然符合 STL)。 STL 的关键设计理念之一是算法和容器只提供它们可以有效 提供的东西。考虑在链表上提供operator[] 每次访问都需要线性时间,这样效率不高。

【讨论】:

  • 你完全误解了我的目的。
  • 他要求在自定义分配器下的数组中提供节点的链接列表。 operator[] 与数组相关,而不是列表。
  • @Photoswatter:是的,我误解了为什么你会有两个容器跟踪完全相同的数据。
  • @zvrba:鉴于反对单次反对票的赞成票数量(我猜是你的反对票),也许您需要更好地解释您的需求。
  • @zvrba:我认为比利是在谈论列表中的整数所索引的结构。 最好实现为vectordeque;这些容器将存储开销降至最低。至于使用整数而不是指针的 SLL 或 DLL:你只需要写出那部分。没有标准的容器,也没有人用它制作一个库,因为这是你在介绍数据结构课程中所做的那种事情,除非你用指针来做。
【解决方案2】:

我们必须编写自己的列表容器才能准确地做到这一点。这大约是半天的工作。

【讨论】:

  • 是的,这不是很多工作,但我仍然希望找到一个经过调试的实现。我想我还是得硬着头皮自己做:-)
  • 请注意,在某些架构上,使用非字 int 类型(例如,64 位平台上的 16 位短)进行迭代或以其他方式索引的成本可能很高。
【解决方案3】:

Boost.Interprocess (containers) 提供使用分配器指针类型的 slist 容器。也许这就是你要找的:)

即使这些容器包含在 Boost.Interprocess 中,它们也可以在进程内内存上完美运行。另外作者已经做了分离,提出给bots为Boost.Containers (Documentation/Source)

【讨论】:

  • 公司编码标准。
【解决方案4】:

一个有点过时的选项是使用Judy Arrays。它们提供高效的存储和计算效率。它们适用于存储整数集;我不知道这是否适合你的问题。

【讨论】:

    【解决方案5】:

    如果您担心存储大量int 值的链表的内存开销,您绝对应该考虑使用vectordeque as Billy ONeal suggested

    与链表相比,这些容器的缺点在于插入元素。如果您将项目插入容器的中间,dequevector 中的任何一个都必须复制元素(如果您要在容器的开头插入,deque 比向量有很大的优势,甚至添加到容器末端时具有优势)。

    然而,在插入后复制int 元素实际上并不比扫描链表以按索引查找元素的成本高出很多。由于dequevector 可以在恒定时间内按索引定位元素,并且由于数据结构的读取频率通常远高于修改它们的频率,因此您可能会看到使用deque 或@987654332 中的任何一个都会获得净收益@ 通过索引访问的int 链接列表(甚至是自定义版本)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-11
      • 2011-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多