现在我有一个动态分配数组内存的算法:
这是用于动态内存分配的相当快的算法,尽管将元素复制到新分配的数组有额外的开销。
什么是基于数组的更快,List<T>
或这样的算法?你会建议使用什么?
List<T>
是否使用简单数组作为内部数据结构?
答案 0 :(得分:9)
回答你的问题:
确实,C#的List<T>
实现使用了一个
IEnumerable<T>
(这意味着它可以是LINQ查询,foreach
等等)等等
因此,我会要求您使用List<T>
而不是您自己的列表。
哦,顺便说一下,如果你想要来自微软的List<T>
的源代码,那么它就是
修改强>
EnsureCapacity
中List<T>
的源代码是:
// Ensures that the capacity of this list is at least the given minimum
// value. If the currect capacity of the list is less than min, the
// capacity is increased to twice the current capacity or to min,
// whichever is larger.
private void EnsureCapacity(int min) {
if (_items.Length < min) {
int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
if (newCapacity < min) newCapacity = min;
Capacity = newCapacity;
}
}
答案 1 :(得分:6)
除非您有特别的理由相信,否则使用C#附带提供的库几乎是一个好主意。这些实现已经很好地实现,经过良好调试,并且经过了充分测试。
您描述的数据结构是动态数组数据结构的标准实现,大多数语言都将此作为默认列表实现。查看the documentation for List<T>
,似乎List<T>
使用此实现,因为其文档引用了内部容量,并且只要大小小于容量,就保证O(1)追加。
简而言之,除非必须,否则请避免重新发明轮子。
希望这有帮助!
答案 2 :(得分:4)
List<T>
在内部使用数组,它使用与您类似的策略 - 如果长度超过数组的长度,它会使数组的大小加倍。但是,如果尺寸变小,它就不会变小。
mscorlib
中的相关方法:
private void EnsureCapacity(int min)
{
if (this._items.Length < min)
{
int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
if (num < min)
{
num = min;
}
this.Capacity = num;
}
}
数组的大小调整实际上发生在List<T>.Capacity
的设置器中。
答案 3 :(得分:2)
是的,List<T>
在内部使用T[]
来保存您的对象。
据我记得.NET 4.0源代码,在添加新对象之前,它确保数组有足够的容量来容纳新的对象数。如果现有数组不能容纳新数量的对象,则将其替换为大小加倍的新数组,并将所有对象和所有现有引用复制到新数组。
答案 4 :(得分:2)
无需重新发明轮子。
来自MSDN:
容量是List&lt;(Of&lt;(T&gt;)&gt;)可以存储的元素数量 在需要调整大小之前,Count是元素的数量 它实际上在List&lt;(Of&lt;(T&gt;)&gt;)中。
容量始终大于或等于Count。如果计数超过 添加元素时的容量,容量增加了 在复制旧数据之前自动重新分配内部数组 元素和添加新元素。
可以通过调用TrimExcess方法或通过调用容量来减少容量 显式设置Capacity属性。当Capacity的值 显式设置,内部数组也重新分配 容纳指定的容量,并复制所有元素。
检索此属性的值是O(1)操作;设置 该属性是O(n)操作,其中n是新容量。
答案 5 :(得分:0)
那是基本上 List<T>
(以及许多其他语言的动态数组)也是如此。调整大小的因素可能会有所不同,我认为在删除元素时它不会自行缩小支持数组 - 但是TrimToSize
你可以自己设置Capacity
,如果客户端代码很好地使用此功能,则可能允许更有效的策略。但基本上,它是渐近等价的。
至于使用哪一个:除非你有List<T>
对你的用例来说不是最理想的冷,硬数据,并且差异很重要(你显然还没有这方面的知识),你应该使用它。您自己的实现将是错误的,功能较少(参见IEnumerable<T>
,IList<T>
,众多方法),不太优化,不太广泛可识别,不被其他库接受(因此您可能需要创建昂贵的复制,或者至少做比List<T>
更多的工作更多的工作)等等,而且很可能绝对没有任何东西可以获得。