简单分析 C 语言的 qsort() 源码
stdlib.h 是使用 C 语言需要引入的库,在系统文件下可以搜索到这个文件夹,在里面可以看到有一个 qsort() 文件用编译器或者记事本打开就能看到里面的源码了。
单从文件名看,qsort() 采用的是快速排序算法,算法的时间复杂度为 O(nlogn) ,通常在企业的实际应用中对于快排这种 nlogn 复杂度的算法应用较多,对于 O(n) 例如 :桶排序。等线性排序方法会使用的较少。以桶排序为例,需要开辟额外的内存空间只适用于数据量大且密集的数据排序,例如高考全国考生的分数排序,近千万考生成绩都位于 0 - 750 分这个区间,采用桶排序就可以极大的提高排序的效率,因为「 桶 」之间有着自带的排序。
qsort() 是否全是使用快速排序
源码中以下几句话,设立 8 为使用快速排序和插入排序的分界点,当要排序的数组长度大于 8 时适合使用「 快速排序 」下与 8 时更适合使用「 插入排序 」
// This macro defines the cutoff between using QuickSort and insertion sort for
// arrays; arrays with lengths shorter or equal to the below value use insertion
// sort.
#define CUTOFF 8 // Testing shows that this is a good value.
qsort() 如何优化时间复杂度
插入排序的算法复杂度取决于分区点,如果是选择数组的头元素或是尾元素,出现最差时间复杂度此时 O(nlogn) 复杂度就会变成 O(n2) 。从 qsort() 的源码中我们可以看到,它选择的是 三数中值法。
注 :mid 为中值点、lo 为左起始点 width 为单个元素的大小,mid = lo + (size / 2) * width 是为了防止两数直接相加时「 上溢出 」。
// First we pick a partitioning element. The efficiency of the// algorithm demands that we find one that is approximately the median// of the values, but also that we select one fast. We choose the// median of the first, middle, and last elements, to avoid bad// performance in the face of already sorted data, or data that is made// up of multiple sorted runs appended together. Testing shows that a// median-of-three algorithm provides better performance than simply// picking the middle element for the latter case.// Find the middle element:char* mid = lo + (size / 2) * width;// Sort the first, middle, last elements into order:if (__COMPARE(context, lo, mid) > 0)swap(lo, mid, width);if (__COMPARE(context, lo, hi) > 0)swap(lo, hi, width);if (__COMPARE(context, mid, hi) > 0)swap(mid, hi, width);
因为源码中用了一些 goto 语句以及不是很明白的变量名,就不做细致分析了,可以参照这篇帖子链接
具体代码已上传至码云 源码链接
也可以参考我参照《 数据结构与算法分析 —— C 语言描述 》写的 快速排序(三数中值法)