我使用了很多列表和数组,但我还没有遇到一个场景,数组列表不能像链表一样容易使用,如果不是更容易的话。我希望有人能给我一些例子,说明什么时候链表明显更好。


当前回答

我认为主要的区别在于你是否经常需要从列表顶部插入或删除内容。

对于一个数组,如果你从列表的顶部移除一些东西复杂度是o(n)因为数组元素的所有下标都要移位。

对于链表,它是o(1),因为您只需要创建节点,重新分配头,并将对next的引用分配为前一个头。

当经常在列表的末尾插入或删除时,数组是更可取的,因为复杂度将是o(1),不需要重新索引,但对于链表,它将是o(n),因为你需要从头到最后一个节点。

我认为在链表和数组中搜索都是o(log n)因为你可能会使用二分搜索。

其他回答

数组具有O(1)随机访问,但是向数组中添加或删除内容的代价非常高。

链表在任何地方添加或删除项目和迭代都非常便宜,但随机访问是O(n)。

Algorithm           ArrayList   LinkedList
seek front            O(1)         O(1)
seek back             O(1)         O(1)
seek to index         O(1)         O(N)
insert at front       O(N)         O(1)
insert at back        O(1)         O(1)
insert after an item  O(N)         O(1)

数组列表适用于写一次读多次或追加程序,但不适用于从前面或中间进行添加/删除。

To add to the other answers, most array list implementations reserve extra capacity at the end of the list so that new elements can be added to the end of the list in O(1) time. When the capacity of an array list is exceeded, a new, larger array is allocated internally, and all the old elements are copied over. Usually, the new array is double the size of the old one. This means that on average, adding new elements to the end of an array list is an O(1) operation in these implementations. So even if you don't know the number of elements in advance, an array list may still be faster than a linked list for adding elements, as long as you are adding them at the end. Obviously, inserting new elements at arbitrary locations in an array list is still an O(n) operation.

访问数组列表中的元素也比访问链表快,即使访问是顺序的。这是因为数组元素存储在连续的内存中,可以很容易地缓存。链表节点可能分散在许多不同的页面上。

如果知道要在任意位置插入或删除项,我建议只使用链表。数组列表在其他方面会更快。

我做了一些基准测试,发现list类实际上比LinkedList随机插入更快:

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int count = 20000;
            Random rand = new Random(12345);

            Stopwatch watch = Stopwatch.StartNew();
            LinkedList<int> ll = new LinkedList<int>();
            ll.AddLast(0);
            for (int i = 1; i < count; i++)
            {
                ll.AddBefore(ll.Find(rand.Next(i)),i);

            }
            Console.WriteLine("LinkedList/Random Add: {0}ms", watch.ElapsedMilliseconds);

            watch = Stopwatch.StartNew();
            List<int> list = new List<int>();
            list.Add(0);
            for (int i = 1; i < count; i++)
            {
                list.Insert(list.IndexOf(rand.Next(i)), i);

            }
            Console.WriteLine("List/Random Add: {0}ms", watch.ElapsedMilliseconds);

            Console.ReadLine();
        }
    }
}

链表需要900毫秒,列表类需要100毫秒。

它创建后续整数的列表。每个新的整数被插入到一个已经在列表中的随机数之后。 也许List类使用了比数组更好的东西。

这个问题的简单答案可以用以下几点来给出:

当需要类似类型的数据元素集合时,将使用数组。而链表是混合类型数据链接元素(称为节点)的集合。 在数组中,可以在O(1)时间内访问任何元素。然而,在链表中,我们需要遍历整个链表,从头到所需的节点,花费O(n)时间。 对于数组,需要在初始时声明特定的大小。但是链表的大小是动态的。