有很多关于对阵列for
和foreach
循环和IEnumerable
S IN表现一般职位。不幸的是,他们主要处理与foreach
循环相关的开销,我无法在链接列表上找到任何关于其性能的任何明确信息 - 或者更确切地说,是List<T>
。性能for/while循环VS名单上foreach循环<T>
为了保持简单,我将提出我的问题作为两个假设,并询问它们是否正确。
假设1
当我运行下面的代码:
List<Foo> list = new List<Foo>();
//(list is filled here)
foreach (Foo f in list)
{
f.baz();
}
循环迭代要执行这样的:
0:你有一个指针到节点0通话节点0的项目上的
baz()
。将指针移至节点0之后的节点。1:您有一个指向节点1的指针。在节点1的项目上调用
baz()
。将指针移动到节点1之后的节点。2:您有指向节点2的指针。请在节点2的项目上调用
baz()
。指针移动到节点节点2后...
N:你有一个指向节点n。在节点n的项目上调用
baz()
。在节点n之后将指针移动到节点。
换句话说,上面的代码具有O(n)的复杂性。
假设2
当我运行下面的代码:
List<Foo> list = new List<Foo>();
//(list is filled here)
for (int i = 0; i < list.Count; i++)
{
list[i].baz();
}
或以下代码:
List<Foo> list = new List<Foo>();
//(list is filled here)
int i = 0;
while (i < list.Count)
{
list[i].baz();
i++;
}
循环迭代要执行这样的:
0:你有一个指向01的指针。从
list
获取指向节点0的指针。在节点0的项目上调用baz()
。1:您有一个指向
list
的指针。从list
获取指向节点0的指针。移动指针到节点0之后的节点。在节点1的项目上调用baz()
。2:您有一个指向
list
的指针。从list
获取指向节点0的指针。在节点0之后将指针移动到节点。将节点1之后的节点移动到节点。在节点2的项目上调用baz()
。...
N:你有一个指针
list
。从list
获取指向节点0的指针。将指针移至节点0之后的节点。将指针移至节点1之后的节点。将指针移至节点2之后的节点。[...]将指针移至节点(n-2)之后的节点。在节点(n-1)之后移动指针到节点。在节点n的项目上调用baz()
。
换句话说,上面的代码具有O(n )的复杂性。
我的假设是否正确?
'List'不是一个链表,你可以从阅读这个类型的文档中看到。 – Servy
您所做的主要假设不正确的是,链接列表和列表具有可比性。他们不是。其中一个显着差异是链接列表中的元素不能直接访问,而列表则可直接访问元素。这会导致假设2中的错误假设。将列表视为与数组相同的类别可能会有帮助。 –
hatchet
另外,由于枚举器可以维护状态(它们在哪里),即使LinkedList枚举器可以在由foreach使用时(foreach使用封面下的枚举器)提供O(n)。 – hatchet