首先,C# List<>.Sort() 排序的底层实现原理就是快速排序 + 堆排序(.net 4.5用的内省排序)。
大佬可以 return了。
接下来,让我们一一还原案发现场。
// 1,看到我们调用的Sort方法
public void Sort(IComparer<T> comparer)
{
Sort(0, Count, comparer);
}
// 2,进入Sort(), 这里只关注倒数第二行,调用了Array.Sort()
public void Sort(int index, int count, IComparer<T> comparer)
{
if (index < 0)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
if (count < 0)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
if (_size - index < count)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
}
Array.Sort(_items, index, count, comparer);
_version++;
}
// 3, 这里只关注最后一行,调用了ArraySortHelper.Default.Sort()
public static void Sort<T>(T[] array, int index, int length, IComparer<T> comparer)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
if (index < 0 || length < 0)
{
throw new ArgumentOutOfRangeException((length < 0) ? "length" : "index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
if (array.Length - index < length)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
}
if (length > 1 && ((comparer != null && comparer != Comparer<T>.Default) || !TrySZSort(array, null, index, index + length - 1)))
{
ArraySortHelper<T>.Default.Sort(array, index, length, comparer);
}
}
// 4, 这一段,根据版本使用不同的排序
public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
{
try
{
if (comparer == null)
{
comparer = Comparer<T>.Default;
}
// 如果.net版本是4.5 则执行IntrospectiveSort
if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
{
IntrospectiveSort(keys, index, length, comparer);
}
// 否则都执行深度限制快速排序, 深度限制是32
else
{
DepthLimitedQuickSort(keys, index, length + index - 1, comparer, 32);
}
}
catch (IndexOutOfRangeException)
{
IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
}
catch (Exception innerException)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), innerException);
}
}
// 5,IntrospectiveSort 使用内省排序 , 不在本篇文章介绍中
internal static void IntrospectiveSort(T[] keys, int left, int length, IComparer<T> comparer)
{
if (length >= 2)
{
IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length), comparer);
}
}
// 6,DepthLimitedQuickSort 重点!!!!!
// 深度限制 32 也就是说快排的轮次最大进行32轮, 32轮能排2^32个数
// 以下快排用的双边循环法 不清楚的可以参考我的博文 排序算法--快速排序的两种遍历方法(C#)
internal static void DepthLimitedQuickSort(T[] keys, int left, int right, IComparer<T> comparer, int depthLimit)
{
while (depthLimit != 0)
{
// 确定起始点,中点,终点
int num = left;
int num2 = right;
int num3 = num + (num2 - num >> 1);
// 将三个位置的顺序确定
SwapIfGreater(keys, comparer, num, num3);
SwapIfGreater(keys, comparer, num, num2);
SwapIfGreater(keys, comparer, num3, num2);
T val = keys[num3];
//找基准位置
while (true)
{
if (comparer.Compare(keys[num], val) < 0)
{
num++;
continue;
}
while (comparer.Compare(val, keys[num2]) < 0)
{
num2--;
}
if (num > num2)
{
break;
}
if (num < num2)
{
T val2 = keys[num];
keys[num] = keys[num2];
keys[num2] = val2;
}
num++;
num2--;
if (num > num2)
{
break;
}
}
depthLimit--;
if (num2 - left <= right - num)
{
if (left < num2)
{
// 排左边
DepthLimitedQuickSort(keys, left, num2, comparer, depthLimit);
}
left = num;
}
else
{
if (num < right)
{
// 排右边
DepthLimitedQuickSort(keys, num, right, comparer, depthLimit);
}
right = num2;
}
if (left >= right)
{
return;
}
}
// hello ,这里抓到一枚堆排同志
Heapsort(keys, left, right, comparer);
}
// 7, 接下来是堆排
private static void Heapsort(T[] keys, int lo, int hi, IComparer<T> comparer)
{
int num = hi - lo + 1;
// 构建堆
for (int num2 = num / 2; num2 >= 1; num2--)
{
DownHeap(keys, num2, num, lo, comparer);
}
// 交换堆顶与末尾元素,并重新构建堆
for (int num3 = num; num3 > 1; num3--)
{
Swap(keys, lo, lo + num3 - 1);
DownHeap(keys, 1, num3 - 1, lo, comparer);
}
}
// 8,堆下沉
private static void DownHeap(T[] keys, int i, int n, int lo, IComparer<T> comparer)
{
T val = keys[lo + i - 1];
while (i <= n / 2)
{
int num = 2 * i;
if (num < n && comparer.Compare(keys[lo + num - 1], keys[lo + num]) < 0)
{
num++;
}
if (comparer.Compare(val, keys[lo + num - 1]) >= 0)
{
break;
}
keys[lo + i - 1] = keys[lo + num - 1];
i = num;
}
keys[lo + i - 1] = val;
}
脑仁疼