【问题标题】:Pros and Cons of implementing dynamic data structures as array in C? [closed]在 C 中将动态数据结构实现为数组的优缺点? [关闭]
【发布时间】:2021-09-17 11:36:22
【问题描述】:

我在大学里了解到,当实现为结构的动态数组时,在 C 中实现,比如说一个列表,缓存效率会更高。因此,据我了解,它的 O(N) malloc 调用与(最坏情况) O(N log(N)) 时间复杂度通过 realloc 调用来维护内存。但是大量数据的“真实列表”会导致更多的缓存未命中。是否有 goto 选项,或者它取决于?

【问题讨论】:

  • 我认为“这取决于”它。这在很大程度上取决于您最有可能如何访问列表中的成员:主要是按顺序访问,还是主要是随机访问?
  • 不幸的是,这种开放式问题不太适合像堆栈溢出这样的客观编程问答网站。
  • 如果您可以描述如何计划访问数据以及实际数据是什么,那么用事实(如基准)来回答会更容易。
  • 实际上我对“它取决于”很好。只是想确保我对该主题有正确的理解。 ATM 我正在​​研究字符串的 R/B 树。也许我以两种方式实现它并对实际数据进行基准测试。它甚至不是时间紧迫的,我只是好奇。
  • 动态数组可以使用 2 的幂增长策略有效地调整大小。例如,这就是 C++ 中著名的std::vector 的作用。这只需要O(log(n)) 分配和复制(并且开销与数组的大小成线性关系)。列表也可以使用存储桶进行优化,以减少分配量。在大多数情况下,数组更好。但是,考虑到访问模式和数据大小,在某些情况下,列表可能会更好,例如在中间插入一些项目或进行拼接时。

标签: c performance dynamic-memory-allocation


【解决方案1】:

如上所述,这取决于。通常对于小型对象,是的,将数据存储为数组将很有意义。例如,让我们假设一个 64 位平台上的单链表,在最坏的情况下:

typedef struct ListNode {
  struct ListNode* next;
  char data;
  /* 7 bytes of padding */
} ListNode;

sizeof(ListNode) 是 16,然后添加典型的 malloc 标头大小 (为了参数,我会说这是另外 16 个字节,但这取决于底层分配器)。所以对于 1 字节的数据,每个元素至少要消耗 32 字节的内存。

如果我们假设一个典型的cache line是64bytes,并且我们假设链表节点在内存中是线性分配的(最好的情况),那么每次我们接触一个内存位置,64bytes就是加载到缓存中 - 足以容纳 2 个数据项(这是最好的情况 - 如果列表在内存中布局稀疏,我们只会得到 1 个)。这比最好情况下的数组差 32 倍,在最坏情况下差 64 倍。

但是,如果要存储的数据要么非常大,要么构建/复制成本很高,那么重新分配数组以在中间插入项目的成本可能太高。 (在这种情况下,链表可能会胜出)

那么当然,总会有中途的数据结构,例如

typedef struct ListNode_X1024 {
  struct ListNode_X1024* next;
  uin32_t num_used;
  char data[1024];
} ListNode_X1024;

本质上是较小数组的链表。

Tl;dr,这取决于您的用例是什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多