【发布时间】:2011-04-13 22:05:24
【问题描述】:
有一个关于如何对列表进行排序的问题。从基本的 List.Sort() 到 List.OrderBy() 有几种方法。最可笑的是roll-your-own-SelectionSort。我立即投了反对票,但这让我思考;应用于列表的 Linq 的 OrderBy() 不会做同样的事情吗? myList.OrderBy(x=>x.Property).ToList() 将产生一个迭代器,它基本上在集合的左侧找到投影的最小值,并返回它。遍历整个列表时,这就是选择排序。
这让我思考; Lists、SortedLists、Enumerables 等的内置排序器使用什么算法,并且通过扩展,对于大型集合是否应该避免使用它们中的任何一种? SortedList,因为它保持按键排序,可能会在每次添加时使用单遍 InsertionSort;找到值大于新索引的第一个索引,并在它之前插入。列表和数组本身可能非常有效地合并排序,但我不知道 Sort() 背后的实际算法。我们已经讨论了 OrderBy。
我在上面所知道的似乎表明 List.Sort() 或 Array.Sort() 是已知大小列表的最佳选择,不鼓励使用 Linq 对内存中的列表或数组进行排序。对于流,除了 OrderBy() 枚举之外真的没有其他方法了;您可以将数据保留为流,而不必在排序之前将其全部保存,从而减轻了性能损失。
编辑:
普遍的共识是,给定一个列表或数组的具体实现,Sort() 会更快。 OrderBy 是合理的,但速度较慢,因为它增加了从传递的枚举中提取数组的 O(N) 复杂性。 SortedList 初始化最终是 O(N^2) 因为引擎盖下的东西。故事的寓意,当你有一个实际的 List 时,使用 List.Sort() 而不是 List.OrderBy()。
【问题讨论】:
-
我认为大多数内置排序都使用快速排序。如果要加快速度,请删除边界检查。 List.Sort 在内部也使用 Array.Sort。
-
@Mikael 是正确的,OrderBy() 也使用快速排序。 @KeithS,您可以愉快地自己浏览源代码,它是公开的(并集成到 VS 中)。 EnumerableSorter.QuickSort 是 OrderBy 使用的方法的名称。
-
.Net Reflector 再次救援 - 一定会爱上它!
-
@Mikael:你不能在 .NET 中进行边界检查
-
@Henk:我的意思是,避免对集合长度进行边界检查。所有 .Sort() 方法都在开始时进行检查。对于时间紧迫的系统,您可以通过自己实现并跳过长度/索引检查来节省时间。
标签: .net performance sorting collections