.NET源代码的内部排序实现
使用JetBrains的DotPeek工具能够方便地查看.net的部分源代码。于是看了一下.NET的内部是怎样实现排序的算法。
在System.Collections.Generic 命名空间下能够看到ArraySortHelper<T>的实现。
public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
{
try
{
if (comparer == null)
comparer = (IComparer<T>) Comparer<T>.Default;
if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
ArraySortHelper<T>.IntrospectiveSort(keys, index, length, comparer);
else
ArraySortHelper<T>.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<T> comparer)
{
if (length < 2)
return;
ArraySortHelper<T>.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<T> 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<T>.SwapIfGreater(keys, comparer, lo, hi);
break;
}
else if (num == 3)
{
ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi - 1);
ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi);
ArraySortHelper<T>.SwapIfGreater(keys, comparer, hi - 1, hi);
break;
}
else
{
ArraySortHelper<T>.InsertionSort(keys, lo, hi, comparer);
break;
}
}
else if (depthLimit == 0)
{
ArraySortHelper<T>.Heapsort(keys, lo, hi, comparer);
break;
}
else
{
--depthLimit;
num = ArraySortHelper<T>.PickPivotAndPartition(keys, lo, hi, comparer);
ArraySortHelper<T>.IntroSort(keys, num + 1, hi, depthLimit, comparer);
}
}
} private static int PickPivotAndPartition(T[] keys, int lo, int hi, IComparer<T> comparer)
{
int index = lo + (hi - lo) / 2;
ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, index);
ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi);
ArraySortHelper<T>.SwapIfGreater(keys, comparer, index, hi);
T obj = keys[index];
ArraySortHelper<T>.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<T>.Swap(keys, i, j);
else
break;
}
ArraySortHelper<T>.Swap(keys, i, hi - 1);
return i;
}
而.NET4.5下面使用的是还有一种排序的方案。
在排序的数字小于16个的时候,直接使用插入排序。
private static void InsertionSort(T[] keys, int lo, int hi, IComparer<T> 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<T> comparer, int depthLimit)
{
while (depthLimit != 0)
{
int index1 = left;
int index2 = right;
int index3 = index1 + (index2 - index1 >> 1);
ArraySortHelper<T>.SwapIfGreater(keys, comparer, index1, index3);
ArraySortHelper<T>.SwapIfGreater(keys, comparer, index1, index2);
ArraySortHelper<T>.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<T>.DepthLimitedQuickSort(keys, left, index2, comparer, depthLimit);
left = index1;
}
else
{
if (index1 < right)
ArraySortHelper<T>.DepthLimitedQuickSort(keys, index1, right, comparer, depthLimit);
right = index2;
}
if (left >= right)
return;
}
ArraySortHelper<T>.Heapsort(keys, left, right, comparer);
}
而假设大于4GB的数量时,使用堆排序。
private static void Heapsort(T[] keys, int lo, int hi, IComparer<T> comparer)
{
int n = hi - lo + 1;
for (int i = n / 2; i >= 1; --i)
ArraySortHelper<T>.DownHeap(keys, i, n, lo, comparer);
for (int index = n; index > 1; --index)
{
ArraySortHelper<T>.Swap(keys, lo, lo + index - 1);
ArraySortHelper<T>.DownHeap(keys, 1, index - 1, lo, comparer);
}
} private static void DownHeap(T[] keys, int i, int n, int lo, IComparer<T> 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<T> 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;
}
.NET源代码的内部排序实现的更多相关文章
- 七种机器内部排序的原理与C语言实现,并计算它们的比较次数与移动次数。
内部排序是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 排序是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个相知有序的序列.排序分为 ...
- 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)
写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...
- C++ 内部排序(一)
先讲两个概念,所谓内部排序,指待排序的节点均存储在内存中.所谓排序的稳定性,指排序后,值相等的两个元素原来相对的位置是否发生变化了.举个例子. 待排序列:3(1),1,5,3(2) 稳定排序:1,3 ...
- 排序算法练习--JAVA(:内部排序:插入、选择、冒泡、快速排序)
排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... 内部排序: 插入排序:直接插入排序 选 ...
- 内部排序->其它->地址排序(地址重排算法)
文字描述 当每个记录所占空间较多,即每个记录存放的除关键字外的附加信息太大时,移动记录的时间耗费太大.此时,就可以像表插入排序.链式基数排序,以修改指针代替移动记录.但是有的排序方法,如快速排序和堆排 ...
- 内部排序->基数排序->链式基数排序
文字描述 基数排序是和前面各类排序方法完全不相同,前面几篇文章介绍的排序算法的实现主要是通过关键字间的比较和移动记录这两种操作,而实现基数排序不需要进行记录关键字间的比较.基数排序是一种借助多关键字排 ...
- 内部排序->归并排序->2-路归并排序
文字描述 假设初始序列有n个记录,则可看成是n个有序的字序列,每个字序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列:再两两归并,…, 如此重复,直到得到一个长度为n的有序序列为 ...
- 内部排序比较(Java版)
内部排序比较(Java版) 2017-06-21 目录 1 三种基本排序算法1.1 插入排序1.2 交换排序(冒泡)1.3 选择排序(简单)2 比较3 补充3.1 快速排序3.2 什么是桶排序3.3 ...
- Java实现各种内部排序算法
数据结构中常见的内部排序算法: 插入排序:直接插入排序.折半插入排序.希尔排序 交换排序:冒泡排序.快速排序 选择排序:简单选择排序.堆排序 归并排序.基数排序.计数排序 直接插入排序: 思想:每次将 ...
随机推荐
- c#基于这些,你已经看到了?(一)-----谁才刚刚开始学习使用
1.注视(不要写的目光是流氓,从废话名盲人) '///'一般用于目光功能.凝视类. 2.热键 ctrl+k+d(有语法错误无法进行对齐) ctrl+j(高速弹出仅仅能提示) shift+end,shi ...
- Android笔记 之 旋转木马的音乐效果
一.前言-- 大家一定在百度音乐上在线听过歌,有没有注意到那个旋转唱片-- 就上面那个,当音乐在播放的时候,那个光碟轮子在转,就想旋转木马一般.感觉好好玩啊. 碰巧想起前阵子做音乐播放器,哎,那这个也 ...
- transform:translateZ() 字体模糊问题 父类重返Z轴平面
translateZ()变糊 第一种情况: 当translateZ(m)中的 m设置为 非整数,1.5px 之类的,字体会模糊,但是不明显;和浏览器渲染,字体格式,或者操作系统有关, 这个 css中 ...
- 致网友Wonderfei的一封信(怎样选择自己主动化框架的几点拙见)
注:本来这封信要发给Wonerfei网友的,可是由于每次仅仅能发200字,所以干脆贴到博客上,叫Wonderfei同学到这上面来看,也算是我自己的一个暂时总结吧.同一时候也希望大家给予Wonderfe ...
- cocos2dx 制作单机麻将(二)
cocos2dx 制作单机麻将(二) 打乱麻将顺序2 前面解说了怎样打乱初始给定的麻将牌堆, 另一种是打乱随意给定的麻将牌堆 //混乱扑克2 void RandAppointCardData(BYTE ...
- Intelli idea 常用快捷键汇总
To navigate to the implementation(s) of an abstract method, position the caret at its usage or its n ...
- 关于接收POST请求 $GLOBALS['HTTP_RAW_POST_DATA']
总是产生变量包含有原始的 POST 数据.否则,此变量仅在碰到未识别 MIME 类型的数据时产生.不过,访问原始 POST 数据的更好方法是 php://input.$HTTP_RAW_POST_DA ...
- 初步swift该研究指出语言(基本数据类型)
笔者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/28258805 转载请注明出处 假设认为文章对你有所帮助,请通过留言 ...
- Swift——(两)Swift访问元组
在Swift在,获取元组的值到一个位置,通过三种方法: 1.使用元组变量/常量 @Author: twlkyao转载或者引用请保留此行. let http404Error = (404, &q ...
- ArcGIS JavaScript API本地部署离线开发环境[转]
原文地址:http://www.cnblogs.com/brawei/archive/2012/12/28/2837660.html 1 获取ArcGIS JavaScript API API的下载地 ...