【问题标题】:What is the time complexity of lookups and inserts in a Delphi TList?Delphi TList 中查找和插入的时间复杂度是多少?
【发布时间】:2015-03-07 22:58:40
【问题描述】:

Delphi 中的“TList”对象与它的“items[i]”属性有点混淆。此属性暗示 TList 可能会在某种数组中内部索引其所有列表项。

我完全知道,尽管此类索引属性可以在对象内部任意处理(在这种情况下,例如假设通过线性遍历整个链表直到使用提供的索引命中项目),所以我的问题是:以下替代方案是真正的替代方案:

1。 TList 确实在某种(动态)数组中对其项目进行内部索引,因此具有任意索引的列表项查找将具有 O(1) 时间复杂度(即常数),而添加的列表项将具有 O(n) 复杂度(即线性),因为数组在扩展大小时必须重新分配。

2。 TList 不会在某种(动态)数组中对其项目进行内部索引,因此具有任意索引的列表项查找将具有 O(n) 时间复杂度(即线性),而添加的列表项将具有 O(1) 复杂度(即常数)。

3。 另一个第三种选择,在这种情况下,非常欢迎您解释查找(按索引)和插入操作的时间复杂度。

【问题讨论】:

    标签: delphi time-complexity tlist


    【解决方案1】:

    购买 Delphi 即可获得 RTL 的源代码,因此很容易知道实际发生了什么。

    在底层,项目是在一个动态数组中管理的,该数组会随着您向其中添加项目而增长,但其方式比简单地随着每次新添加而增长 1 更智能。这意味着后备数组通常大于TList 对象中的项目的Count,因此索引是O(1) 操作,添加通常也是O(1)。 (特别是因为 FastMM 内存管理器通常可以在数组增长时就地重新分配数组,尤其是在较小的大小时,因此不需要复制。)但是当后备数组必须增长并被内存管理器复制时,它将是O(n) 操作。

    另一方面,Insert 操作(插入到列表的中间,而不是添加到末尾)是 O(n) 操作,因为它必须将插入点之后的所有内容向前移动一个。

    正如@SirRufo 指出的那样,Capacity 属性在这里是相关的:它是支持数组的大小。如果Count = Capacity 并且您尝试Add 一个新值,那么它将不得不调整数组的大小。

    【讨论】:

    • 添加通常是 O(1) 的事实并不那么重要。重要的是添加的平均复杂性。或者,如果每次添加都有时间限制,那么最坏情况的复杂性将是重要的。分析其中任何一个都相当困难。
    • 是的,O() 确实暗示了最坏情况的复杂性,所以平均复杂性不相关,我同意(尽管了解平均复杂性确实仍然很有趣超出 O() 定义的范围)。
    • TList<T>.Capacity 属性在这里也值得一提
    • @Question 我的主要观点是,当涉及到堆分配时,我认为很难说太多操作的复杂性。虽然梅森说过一些话,但我相信它要复杂得多。此外,此时大 O 表示法可能没有用。如果存在堆争用怎么办?或者,如果性能由常数而不是渐近行为支配怎么办。
    【解决方案2】:

    Delphi 的TList 是一个包装数组的类。所以它的操作复杂度和数组一样。随机访问是 O(1)。对于操作的复制部分,插入是 O(n)。与插入相关的内存分配更难分析,并且取决于许多因素。由于thois,我不确定分析插入的时间复杂度是否真的很容易处理。

    顺便说一句,从计算机科学的角度来看,Delphi 的列表类不是列表,这让我一直很沮丧。它们是数组。

    【讨论】:

    • 谢谢!然后是两个后续问题:1:同样适用于“泛型”列表,即 TList。 2:Delphi中是否有任何“真正的”链表类,还是我必须自己实现?
    • 顺便说一句,在 Stack Exchange 分配答案的推荐例程是什么,是将完全回答问题(您的问题)的最快答复分配为答案,还是最全面的答复(梅森惠勒的) ?
    • TList<T> 相同。把它想象成一个数组。这就是它的性能。在 RTL 中没有链表类。我确信第 3 方库提供了这一点。也许 Spring4D 有一个链表类。
    • 选择您喜欢的答案。不要选择最快的。选择你认为最好的。我不确定梅森是否更全面,但我会这么说! ;-) 我选择不在答案中重复您已经知道并在关于数组性能特征的问题中所说的内容。无论如何,梅森的回答很好。如果您愿意,请随时接受。我会很高兴的。也请随意投票!
    • 再次感谢,我将把 Mason 的回复指定为答案,但都赞成!
    猜你喜欢
    • 1970-01-01
    • 2011-02-16
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 2017-05-12
    • 1970-01-01
    • 2018-11-24
    相关资源
    最近更新 更多