C# 泛型列表System.Collections.Generic.List<T>
是使用可增长的数组作为后备存储实现的,其方式类似于更多基于数组列表的实现。很明显,当对作为链表实现的列表执行随机(索引)访问时,这会带来巨大的好处。
但是我想知道为什么没有选择将其实现为循环数组。对于索引随机访问和附加到列表末尾,这样的实现将具有相同的 O(1) 性能。但是会提供额外的好处,例如允许 O(1) 前置操作(即在列表的前面插入新元素)并且平均将随机插入和删除所需的时间减半。
到目前为止的一些答案的总结
正如@Hachet 所指出的,为了使循环数组实现具有类似于的索引性能,System.Collections.Generic.List<T>
它需要始终增长到 2 的幂的容量(以便廉价的模运算可以被执行)。这意味着不可能像当前可能在构建列表实例时那样将其大小调整为用户提供的确切初始容量。所以这是一个明确的权衡问题。
正如一些快速而肮脏的性能测试所示,对于循环数组实现,索引可能会慢 2-5 倍左右。
由于索引是一个明显的优先事项,我可以想象这将是一个太大的惩罚,而不是在前置操作上获得更好的性能和在随机插入/删除上稍微更好的性能。
这是带有一些补充答案信息的副本
这个问题确实与为什么典型的数组列表实现不是双端的?,在发布我的问题之前我没有发现。我猜它没有以完全令人满意的方式回答:
我没有做过任何基准测试,但在我看来,还有其他瓶颈(例如非本地加载/存储)会大大超过这个。如果我没有听到更有说服力的东西,我可能会接受这个,谢谢。– Mehrdad 2011 年 5 月 27 日 4:18
这个问题的答案提供了有关如何使循环列表的索引表现得相当好的附加信息,包括一个代码示例,以及一些使权衡决策变得更加清晰的量化数字。因此,它们提供的信息与另一个问题中存在的信息相辅相成。所以我同意这个问题的意图非常相似,因此我同意它应该被视为重复。但是,如果现在随附此信息的新信息丢失,那将是一种耻辱。
此外,我仍然对可能尚未出现在任何一个问题的答案中的实施选择的潜在其他原因感兴趣。