【问题标题】:What is the time complexity of free()?free() 的时间复杂度是多少?
【发布时间】:2017-12-14 05:31:14
【问题描述】:

我只是想知道free() 在 C 中的时间复杂度是多少。

例如,假设我的所有功能都是:

for (int i = 0; i < n; i++) {
    free(ptr[i]); // this is just an example to show n pointers
}

是 O(n) 还是 O(n^2)?

【问题讨论】:

  • 未由 C 语言本身指定。允许任何分配和解除分配策略。此外,如果每次您的示例程序具有未定义的行为时,它都是相同的ptr
  • 这里的 n 是什么?被释放的内存块的大小,或者调用 free 的次数?
  • 对不起,我没有具体说明,n 是要空闲的内存 ptr 的数量,并且 ptr 每次都会更改。我只是快速写了一个例子。
  • 你尝试了一些并计时了吗?并不是说您会从中获得一般信息,但仍然...
  • free() 相对于您的外部n 的时间复杂度将始终为 O(1)。包含此循环的函数将至少为 O(n)。

标签: c time-complexity big-o


【解决方案1】:

正如 Story Teller 所说,free() 的实现未指定,这也使其时间复杂度未指定。

管理分配的内存的不同概念可能具有不同的复杂性。

内存管理器使用的数据结构的几个简化示例
(请注意,这不是您创建的程序中的数据结构):

  • 对于单个 malloc()-free() 对,已分配块的链接列表将带有线性 O(n),
    使你的代码 O(n^2)
  • 伙伴方案将带有对数 O(log n),
    使您的代码 O(n log n)
  • 强调 malloc 和 free 的时间复杂度的实现(作为快速的一个方面),可能会接近 O(1),我在想象哈希表
    (这可能会导致内存消耗和“高 1”,即常数时间可能比其他低 n 概念更长),
    这将使您的代码 O(n)(或低 n 的 O(1))

注意:
有一种方案可以在管理内存中创建内存管理器数据结构(适用于上述所有示例),这将允许找到要释放的块,并在 O(1) 中找到与其相关的管理数据,从而产生free() O(1)的。 但是,malloc() 将搜索提到的数据结构,并为 unused 块(即 malloc() 的 size 参数没有帮助直接指向的块)采用提到的不同时间复杂度。 假设您的代码还必须 malloc() 您正在释放的块,您实际上可能最终会遇到整个程序所提到的复杂性。
严格来说,仅就显示的释放循环而言,任何广泛使用的内存管理器都会使您的代码 O(n),每个 free() 的 O(1)。

(感谢 Stargateur 迫使我更具体地思考这个问题所涉及的确切情况。)

【讨论】:

  • 我正在使用一个链表,并且在每次迭代中都有一个节点是空闲的。还是 O(n^2) 吗?
  • @Billi,不,一次释放一个节点是O(#nodes)
  • "分配块的链表对于单个 free() 将带有线性 O(n),使您的代码 O(n^2)" ???链表删除和插入操作一般都是O(1)!
  • @Yunnosch 我想你不知道你在说什么,如果 malloc 是用链表实现的,next 和 prev 指针将存储在 malloc 指针的元数据中。您不需要通过所有列表找到节点。因为该节点将类似于(struct header *)ptr - 1
  • @Stargateur 是的,你也是对的。我在编辑的答案中提到了这个概念。