FCL源码中数组类型的学习及排序函数Sort函数的分析
2017-10-16 12:29
357 查看
Array 是所有数组的基类
ArrayList 解决了所有Array 类的缺点 能动态扩容, 但是类型不安全的,而是会有装箱与拆箱的性能开销
List<T> 则是解决了ArrayList 类的装箱,拆箱问题, 能够动态扩容,但是所有的顺序结构数据结构的缺点就是数据空间的开辟开销
这三个类都是基于数组实现的, 并没有用到链表的实现.
具体的源码可以通过.NET Reflector 来看。对于内置函数Sort 我一直比较好奇,分析着它的实现应该是快排实现的,分析了下List<T> 的Sort 函数,先看看源码:
代码
FCL的数组类中 内置了专门用来处理排序的一个类 ArraySortHelper<T>。
数组类型的数据结构(不管是List, ArrayList, Array)其Sort 排序函数都是基于ArraySortHelper<T> Sort 函数来排序的。
该函数主要涉及到三种排序算法: 快排, 插入排序, 堆排序, 内省排序
排序数字小于16个,直接使用插入排序
递归深度在32次之内(数字小于4GB)采用快排
大于4GB,则堆排序
看了下源码,不得不佩服那些大神写的框架源码,那些最基本的数据结构和算法在底层的应用这么广,起了这么大的作用,是我们平常使用的函数的基础。
ArrayList 解决了所有Array 类的缺点 能动态扩容, 但是类型不安全的,而是会有装箱与拆箱的性能开销
List<T> 则是解决了ArrayList 类的装箱,拆箱问题, 能够动态扩容,但是所有的顺序结构数据结构的缺点就是数据空间的开辟开销
这三个类都是基于数组实现的, 并没有用到链表的实现.
具体的源码可以通过.NET Reflector 来看。对于内置函数Sort 我一直比较好奇,分析着它的实现应该是快排实现的,分析了下List<T> 的Sort 函数,先看看源码:
代码
1 private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, IComparer<T> comparer) 2 { 3 while (hi > lo) 4 { 5 int num = (hi - lo) + 1; 6 if (num <= 0x10) 7 { 8 switch (num) 9 { 10 case 1: 11 return; 12 13 case 2: 14 ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi); 15 return; 16 17 case 3: 18 ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi - 1); 19 ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi); 20 ArraySortHelper<T>.SwapIfGreater(keys, comparer, hi - 1, hi); 21 return; 22 } 23 ArraySortHelper<T>.InsertionSort(keys, lo, hi, comparer); 24 return; 25 } 26 if (depthLimit == 0) 27 { 28 ArraySortHelper<T>.Heapsort(keys, lo, hi, comparer); 29 return; 30 } 31 depthLimit--; 32 int num2 = ArraySortHelper<T>.PickPivotAndPartition(keys, lo, hi, comparer); 33 ArraySortHelper<T>.IntroSort(keys, num2 + 1, hi, depthLimit, comparer); 34 hi = num2 - 1; 35 } 36 }
FCL的数组类中 内置了专门用来处理排序的一个类 ArraySortHelper<T>。
数组类型的数据结构(不管是List, ArrayList, Array)其Sort 排序函数都是基于ArraySortHelper<T> Sort 函数来排序的。
该函数主要涉及到三种排序算法: 快排, 插入排序, 堆排序, 内省排序
排序数字小于16个,直接使用插入排序
递归深度在32次之内(数字小于4GB)采用快排
大于4GB,则堆排序
看了下源码,不得不佩服那些大神写的框架源码,那些最基本的数据结构和算法在底层的应用这么广,起了这么大的作用,是我们平常使用的函数的基础。
相关文章推荐
- PHP数组排序函数合集 以及它们之间的联系分析
- 基于 Android NDK 的学习之旅-----数据传输一(基本数据类型和数组传输)(附源码)
- Libevent源码分析-----通用类型和函数
- Libevent源码分析-----通用类型和函数
- print()方法对char类型数组自动遍历输出源码分析
- C语言学习6 :指针的定义,指针类型要合法,指针要初始化,指针做函数参数,数组和指针的通用性,指针+1所代表的空间,void * 指针,交换函数中的指针,数组和字符型指针区别,字符型指针的应用,使用指针完成字符操作函数
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- VBS数组函数学习实例分析
- ffmpeg学习七:avformat_find_stream_info函数源码分析
- java学习之旅57、58--数组_StringBuilder和StringBuffer的使用_JDK源码分析内部机制、常用方法补充_常见面试题答法
- Libevent源码分析-----通用类型和函数
- jQuery1.3.2 源码学习-3 init 函数分析 - 1
- Libevent源码分析-----通用类型和函数
- Zepto源码分析(1)——类型判断函数
- nginx 源码学习笔记(三.1)——四种类型结构体中的函数何时调用
- VBS数组函数学习实例分析
- Java学习之数组1(1.数组的声明;2.元素为引用数据类型的数组;3.关于main方法里的String[] args;4.数组排序;5.数3退1 数组算法,(用数组模拟链表);6数组查找之二分法;7数组的拷贝)
- 基于 Android NDK 的学习之旅-----数据传输一(基本数据类型和数组传输)(附源码)
- PHP数组排序函数合集 以及它们之间的联系分析
- TCP/IP源码学习(58)——inet_select_addr函数分析