列出操作复杂性
本文关键字:复杂性 操作 | 更新日期: 2023-09-27 18:33:11
我一直认为C#
中的List<T>
是一个经典的链表,但最近我读到它实际上是由数组内部支持的。
这是否意味着当我们插入到列表的开头时,它是 O(n( 操作,因为其他元素需要像在简单数组中一样进一步移动一个位置?每次我们添加新项目时,都会创建具有更大容量的新数组?还是像Java
中的ArrayList
那样的混合体?
如果有人与 C# 列表操作的复杂性有一些联系,那就太好了。
你的假设是对的。您可以找到 MSDN 上记录的操作的复杂性:
List<T>.Insert
:
此方法是 O(n( 操作,其中 n 是计数。
List<T>.Add
:
如果 Count 已等于 Capacity,则通过自动重新分配内部数组来增加 List 的容量,并在添加新元素之前将现有元素复制到新数组中。
如果计数小于容量,则此方法为 O(1( 操作。如果需要增加容量以容纳新元素,则此方法将成为 O(n( 操作,其中 n 是 Count。
是的,容量会根据需要增加,但不可以,不会为每个添加操作增加容量。正如我们在引用源中构造函数的文档中看到的那样,列表具有一定的基本容量,并且每次超过容量时容量都会翻倍:
// Constructs a List. The list is initially empty and has a capacity
// of zero. Upon adding the first element to the list the capacity is
// increased to 16, and then increased in multiples of two as required.
public List() {
...
}
因此,简而言之,选择正确的列表取决于您的需求。这个答案比较了基于数组的列表(如List<T>
(和链表(如LinkedList<T>
(中常见操作的复杂性:
- .NET 集合类的渐近复杂性