我对此感到非常困惑。到处都写着“链表比数组更快”,但没有人愿意说出为什么。使用普通逻辑我无法理解链表如何更快。在一个数组中,所有单元格彼此相邻,因此只要您知道每个单元格的大小,就可以立即轻松到达一个单元格。例如,如果有一个包含10个整数的列表,并且我想在第四个单元格中获取该值,那么我只需直接到数组的开头+24个字节并从那里读取8个字节。
另一方面,如果你有一个链表并想要获得第四名的元素,那么你必须从列表的开头或结尾开始(取决于它是单列表还是双列表)并且去从一个节点到另一个节点,直到找到你要找的东西。
那么heck如何逐步进行比直接进入元素更快?
答案 0 :(得分:13)
这个题目标题具有误导性。
它断言链接列表 比数组更快,而不会很好地限制范围。有很多次,数组可以显着更快,并且链接列表可以显着更快的次数:链接的特定情况列表“更快”似乎不受支持。
有两件事需要考虑:
对于索引元素的访问:操作在数组中是O(1)
,并且如所指出的那样,非常快(只是一个偏移量)。 操作在链接列表中为O(k)
(其中k
是索引,可能始终为<< n
,视情况而定)但如果链接列表已经遍历然后每步O(1)
与数组“相同”。如果数组遍历(for(i=0;i<len;i++
)更快(或更慢)取决于特定的实现/语言/运行时。
但是,如果存在特定的情况,其中数组对于上述任一操作(搜索或遍历)都不会更快,那么看到在更多的情况下被解剖将会很有趣细节。 (我确信有可能在列表中找到一种非常简并的数组实现语言 cough Haskell cough )
快乐的编码。
我的简单用法摘要:数组适用于索引访问和涉及交换元素的操作。然而,非摊销的重新规模操作和额外的松弛(如果需要)可能相当昂贵。链接列表可以分摊重新调整大小(以及每个单元格的“指针”的交易松弛),并且通常可以在“切出或插入一堆元素”等操作中表现出色。最后,它们是不同的数据结构,应该这样对待。
答案 1 :(得分:7)
与编程中的大多数问题一样,上下文是所有。您需要考虑数据的预期访问模式,然后适当地设计存储系统。如果您插入一次,然后访问它1,000,000次,那么谁在乎插入成本是多少?另一方面,如果您在阅读时经常插入/删除,那么这些成本就会决定。
答案 2 :(得分:4)
取决于您所指的操作。在链表中添加或删除元素比在数组中快得多。
在链表和数组中,逐个顺序迭代列表的速度大致相同。
在数组中间获取一个特定元素要快得多。
并且数组可能会浪费空间,因为在扩展数组时,通常会在该时间点分配比所需更多的元素(想想Java中的ArrayList)。
因此,您需要根据自己的需要选择数据结构:
许多插入和顺序迭代 - &gt;使用LinkedList
随机访问,理想情况下是预定义的大小 - &gt;使用数组
答案 3 :(得分:3)
因为在数组中间插入时没有移动内存。 对于你提出的情况,它的真实 - 数组更快,你只需要算术从一个元素到另一个元素。链表需要间接和片段内存。 关键是要知道使用什么结构以及何时使用。
答案 4 :(得分:2)
在以下情况下,链接列表优于数组:
a)您需要从列表中进行恒定时间的插入/删除(例如在时间可预测性非常关键的实时计算中)
b)您不知道列表中有多少项。对于数组,如果数组变得太大,您可能需要重新声明和复制内存
c)您不需要随机访问任何元素
d)您希望能够在列表中间插入项目(例如优先级队列)
在以下情况下优先使用数组:
a)您需要对元素进行索引/随机访问
b)你提前知道数组中元素的数量,以便为数组分配正确的内存量
c)在按顺序迭代所有元素时需要速度。您可以在数组上使用指针数学来访问每个元素,而您需要根据链表中每个元素的指针查找节点,这可能会导致页面错误,从而导致性能下降。
d)记忆是一个问题。填充数组占用的内存少于链表。数组中的每个元素都只是数据。每个链表节点都需要数据以及指向链表中其他元素的一个(或多个)指针。数组列表(如.Net中的那些列表)为您提供了数组的好处,但为您动态分配资源,因此您不必过多担心列表大小,并且可以删除任何索引处的项目而无需任何努力或重新洗牌的元素。性能方面,arraylists比原始数组慢。