为什么有人想要使用链表而不是数组?
毫无疑问,编码一个链表比使用数组要多一些工作,人们可能会想知道如何才能证明这些额外的工作是合理的。
我认为在链表中插入新元素是微不足道的,但在数组中这是一个主要的任务。与将数据存储在数组中相比,使用链表存储一组数据还有其他优点吗?
这个问题不是这个问题的重复,因为另一个问题是专门问一个特定的Java类,而这个问题是关于一般数据结构的。
为什么有人想要使用链表而不是数组?
毫无疑问,编码一个链表比使用数组要多一些工作,人们可能会想知道如何才能证明这些额外的工作是合理的。
我认为在链表中插入新元素是微不足道的,但在数组中这是一个主要的任务。与将数据存储在数组中相比,使用链表存储一组数据还有其他优点吗?
这个问题不是这个问题的重复,因为另一个问题是专门问一个特定的Java类,而这个问题是关于一般数据结构的。
当前回答
假设您有一个有序集,您还想通过添加和删除元素来修改它。此外,您需要能够以这样的方式保留对元素的引用,以便稍后可以获得前一个或下一个元素。例如,一本书中的待办事项列表或一组段落。
首先,我们应该注意到,如果您想在集合本身之外保留对对象的引用,那么您可能最终会将指针存储在数组中,而不是存储对象本身。否则你将无法插入到数组中-如果对象嵌入到数组中,它们将在插入期间移动,并且任何指向它们的指针都将无效。数组下标也是如此。
您的第一个问题,正如您自己所注意到的,是插入链表允许插入O(1),但数组通常需要O(n)。这个问题可以部分克服——可以创建一种数据结构,提供类似数组的按顺序访问接口,其中读和写在最坏的情况下都是对数的。
Your second, and more severe problem is that given an element finding next element is O(n). If the set was not modified you could retain the index of the element as the reference instead of the pointer thus making find-next an O(1) operation, but as it is all you have is a pointer to the object itself and no way to determine its current index in the array other than by scanning the entire "array". This is an insurmountable problem for arrays - even if you can optimized insertions, there is nothing you can do to optimize find-next type operation.
其他回答
除了插入和删除方便之外,链表的内存表示方式也不同于数组。对于链表中的元素数量没有限制,而在数组中,您必须指定元素的总数。 看看这篇文章。
当集合不断增加和减少时,链表尤其有用。例如,很难想象尝试使用数组实现一个Queue(添加到末尾,从前面删除)—您将花费所有时间向下移动内容。另一方面,对于链表来说,这是微不足道的。
Eric Lippert最近发表了一篇关于数组应该保守使用的原因之一的文章。
链表比数组的维护开销更大,它还需要额外的内存存储,所有这些都是一致的。但是有一些事情是数组做不到的。在很多情况下,假设你想要一个长度为10^9的数组你无法得到它,因为必须有一个连续的内存位置。链表可能是这里的救世主。
假设你想用数据存储多个东西,那么它们可以很容易地扩展到链表中。
STL容器通常在后台有链表实现。
为什么有人想要使用链表而不是数组?
这只是一个原因——如果你需要一个链表数据结构,而你所使用的编程语言不支持指针。