我正在寻找一种可以轻松添加项目而不会影响性能的数组数据类型。
- 系统。数组-
Redim Preserve
将整个 RAM 从旧的复制到新的,与现有元素的数量一样慢 - System.Collections。ArrayList - 够好吗?
- System.Collections。IList - 够好吗?
我正在寻找一种可以轻松添加项目而不会影响性能的数组数据类型。
Redim Preserve
将整个 RAM 从旧的复制到新的,与现有元素的数量一样慢简单总结一下数据结构:
System.Collections.ArrayList:无类型数据结构已过时。请改用 List(of t)。
System.Collections.Generic.List(of t):这表示一个可调整大小的数组。这个数据结构在幕后使用了一个内部数组。只要底层数组没有被填充,将项目添加到 List 是 O(1),否则它是 O(n+1) 来调整内部数组的大小并复制元素。
List<int> nums = new List<int>(3); // creates a resizable array
// which can hold 3 elements
nums.Add(1);
// adds item in O(1). nums.Capacity = 3, nums.Count = 1
nums.Add(2);
// adds item in O(1). nums.Capacity = 3, nums.Count = 3
nums.Add(3);
// adds item in O(1). nums.Capacity = 3, nums.Count = 3
nums.Add(4);
// adds item in O(n). Lists doubles the size of our internal array, so
// nums.Capacity = 6, nums.count = 4
添加项目仅在添加到列表末尾时才有效。在中间插入会强制数组将所有项目向前移动,这是一个 O(n) 操作。删除项目也是 O(n),因为数组需要向后移动项目。
System.Collections.Generic.LinkedList(of t):如果您不需要对列表中的项目进行随机或索引访问,例如您只计划添加项目并从头到尾迭代,那么 LinkedList 就是您的朋友。插入和删除是 O(1),查找是 O(n)。
您应该为此使用 Generic List<> ( System.Collections.Generic.List )。它以固定的摊销时间运作。
它还与 Arrays 共享以下功能。
如果您需要在开头或结尾快速插入和删除,请使用链表或队列
LinkedList< T> 结构对你有用吗?它(在某些情况下)不像直接数组那样直观,但非常快。
但是,随机访问并不是那么快,因为您必须遍历结构才能访问您的项目......但是,它具有 .ToList() 和 .ToArray() 方法来获取列表/数组形式的结构副本所以对于读取访问,你可以在紧要关头做到这一点。插入的性能提高可能超过随机访问需求的性能降低,也可能不会。这将完全取决于您的情况。
还有这个参考资料可以帮助您确定正确的方法:
什么对你来说“足够好”?你到底想用那个数据结构做什么?
没有数组结构(即 O(n) 访问)允许在没有 O(n) 运行时的情况下插入中间;最后插入是 O(n) 最坏的情况,O(1) 摊销用于像 ArrayList 这样的自调整大小数组。
也许哈希表(在任何地方进行分摊的 O(1) 访问和插入,但对于插入来说是 O(n) 最坏的情况)或树(O(log(n)) 用于在任何地方进行访问和插入,保证)更适合。
如果速度是您的问题,我看不出所选答案比使用原始数组有什么好处,尽管它会自行调整大小,但它使用与调整数组大小完全相同的机制(并且应该只需要一点时间) 除非你总是添加到最后,在这种情况下它应该做的事情更聪明一些,因为它一次分配一个块而不是一个元素。
如果您经常在集合的开头/中间添加附近并且不经常索引到中间/结尾,您可能需要链接列表。这将具有最快的插入时间并且将具有很长的迭代时间,它只是在索引方面很糟糕(例如从末尾查看第 3 个元素或第 72 个元素)。