博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET源码的内部排序实现
阅读量:2505 次
发布时间:2019-05-11

本文共 6654 字,大约阅读时间需要 22 分钟。

使用JetBrains的DotPeek工具可以方便地查看.net的部分源码。于是看了一下.NET的内部是如何实现排序的算法。

System.Collections.Generic 命名空间下可以看到ArraySortHelper<T>的实现。

public void Sort(T[] keys, int index, int length, IComparer
comparer) { try { if (comparer == null) comparer = (IComparer
) Comparer
.Default; if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) ArraySortHelper
.IntrospectiveSort(keys, index, length, comparer); else ArraySortHelper
.DepthLimitedQuickSort(keys, index, length + index - 1, comparer, 32); } catch (IndexOutOfRangeException ex) { IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer((object) comparer); } catch (Exception ex) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), ex); } }

发现在.NET4.5以上的版本,开始使用一种叫做 Introspective Sort的排序方法。

internal static void IntrospectiveSort(T[] keys, int left, int length, IComparer
comparer) { if (length < 2) return; ArraySortHelper
.IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length), comparer); } private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, IComparer
comparer) { for (; hi > lo; { int num; hi = num - 1; } ) { int num = hi - lo + 1; if (num <= 16) { if (num == 1) break; if (num == 2) { ArraySortHelper
.SwapIfGreater(keys, comparer, lo, hi); break; } else if (num == 3) { ArraySortHelper
.SwapIfGreater(keys, comparer, lo, hi - 1); ArraySortHelper
.SwapIfGreater(keys, comparer, lo, hi); ArraySortHelper
.SwapIfGreater(keys, comparer, hi - 1, hi); break; } else { ArraySortHelper
.InsertionSort(keys, lo, hi, comparer); break; } } else if (depthLimit == 0) { ArraySortHelper
.Heapsort(keys, lo, hi, comparer); break; } else { --depthLimit; num = ArraySortHelper
.PickPivotAndPartition(keys, lo, hi, comparer); ArraySortHelper
.IntroSort(keys, num + 1, hi, depthLimit, comparer); } } } private static int PickPivotAndPartition(T[] keys, int lo, int hi, IComparer
comparer) { int index = lo + (hi - lo) / 2; ArraySortHelper
.SwapIfGreater(keys, comparer, lo, index); ArraySortHelper
.SwapIfGreater(keys, comparer, lo, hi); ArraySortHelper
.SwapIfGreater(keys, comparer, index, hi); T obj = keys[index]; ArraySortHelper
.Swap(keys, index, hi - 1); int i = lo; int j = hi - 1; while (i < j) { do ; while (comparer.Compare(keys[++i], obj) < 0); do ; while (comparer.Compare(obj, keys[--j]) < 0); if (i < j) ArraySortHelper
.Swap(keys, i, j); else break; } ArraySortHelper
.Swap(keys, i, hi - 1); return i; }

而.NET4.5以下使用的是另一种排序的方案。

在排序的数字小于16个的时候,直接使用插入排序。

private static void InsertionSort(T[] keys, int lo, int hi, IComparer
comparer) { for (int index1 = lo; index1 < hi; ++index1) { int index2 = index1; T x; for (x = keys[index1 + 1]; index2 >= lo && comparer.Compare(x, keys[index2]) < 0; --index2) keys[index2 + 1] = keys[index2]; keys[index2 + 1] = x; } }

而如果大于16个的时候,且当递归深度在32次之内的话(也就是数字小于4GB的数量时),使用快速排序。

internal static void DepthLimitedQuickSort(T[] keys, int left, int right, IComparer
comparer, int depthLimit) { while (depthLimit != 0) { int index1 = left; int index2 = right; int index3 = index1 + (index2 - index1 >> 1); ArraySortHelper
.SwapIfGreater(keys, comparer, index1, index3); ArraySortHelper
.SwapIfGreater(keys, comparer, index1, index2); ArraySortHelper
.SwapIfGreater(keys, comparer, index3, index2); T obj1 = keys[index3]; do { while (comparer.Compare(keys[index1], obj1) < 0) ++index1; while (comparer.Compare(obj1, keys[index2]) < 0) --index2; if (index1 <= index2) { if (index1 < index2) { T obj2 = keys[index1]; keys[index1] = keys[index2]; keys[index2] = obj2; } ++index1; --index2; } else break; } while (index1 <= index2); --depthLimit; if (index2 - left <= right - index1) { if (left < index2) ArraySortHelper
.DepthLimitedQuickSort(keys, left, index2, comparer, depthLimit); left = index1; } else { if (index1 < right) ArraySortHelper
.DepthLimitedQuickSort(keys, index1, right, comparer, depthLimit); right = index2; } if (left >= right) return; } ArraySortHelper
.Heapsort(keys, left, right, comparer); }

而如果大于4GB的数量时,使用堆排序。

private static void Heapsort(T[] keys, int lo, int hi, IComparer
comparer) { int n = hi - lo + 1; for (int i = n / 2; i >= 1; --i) ArraySortHelper
.DownHeap(keys, i, n, lo, comparer); for (int index = n; index > 1; --index) { ArraySortHelper
.Swap(keys, lo, lo + index - 1); ArraySortHelper
.DownHeap(keys, 1, index - 1, lo, comparer); } } private static void DownHeap(T[] keys, int i, int n, int lo, IComparer
comparer) { T x = keys[lo + i - 1]; for (; i <= n / 2; { int num; i = num; } ) { num = 2 * i; if (num < n && comparer.Compare(keys[lo + num - 1], keys[lo + num]) < 0) ++num; if (comparer.Compare(x, keys[lo + num - 1]) < 0) keys[lo + i - 1] = keys[lo + num - 1]; else break; } keys[lo + i - 1] = x; }
最后,附上swap函数的实现:

private static void SwapIfGreater(T[] keys, IComparer
comparer, int a, int b) { if (a == b || comparer.Compare(keys[a], keys[b]) <= 0) return; T obj = keys[a]; keys[a] = keys[b]; keys[b] = obj; } private static void Swap(T[] a, int i, int j) { if (i == j) return; T obj = a[i]; a[i] = a[j]; a[j] = obj; }

转载地址:http://nnlgb.baihongyu.com/

你可能感兴趣的文章
matplotlib绘图跳过时间段的处理方案
查看>>
vnpy学习_04回测评价指标的缺陷
查看>>
读书笔记_量化交易如何建立自己的算法交易01
查看>>
设计模式05_单例
查看>>
设计模式06_原型
查看>>
设计模式07_建造者
查看>>
设计模式09_代理模式
查看>>
设计模式10_桥接
查看>>
满屏的指标?删了吧,手把手教你裸 K 交易!
查看>>
不吹不黑 | 聊聊为什么要用99%精度的数据回测
查看>>
量化策略回测唐安奇通道
查看>>
量化策略回测DualThrust
查看>>
量化策略回测DCCV2
查看>>
mongodb查询优化
查看>>
五步git操作搞定Github中fork的项目与原作者同步
查看>>
git 删除远程分支
查看>>
删远端分支报错remote refs do not exist或git: refusing to delete the current branch解决方法
查看>>
python multiprocessing遇到Can’t pickle instancemethod问题
查看>>
APP真机测试及发布
查看>>
通知机制 (Notifications)
查看>>