目录
一、内部排序算法的比较
选择排序、冒泡排序、堆排序在每趟处理后都能产生当前序列的最大或者最小值。
快速排序、选择排序、冒泡排序、堆排序每一趟都能确定一个元素的最终位置。
算法分类 | 算法名称 | 时间复杂度 | 空间复杂度 | 是否稳定 | 适用性 | ||
---|---|---|---|---|---|---|---|
最好情况 | 平均情况 | 最坏情况 | |||||
插入排序 | 直接插入排序 | 原本有序O(n) | O(n^2) | 原本逆序O(n^2) | O(1) | 是 | 顺序表、链表 |
折半插入排序 | 原本有序O(n) | O(n^2) | 原本逆序O(n^2) | O(1) | 是 | 顺序表 | |
希尔排序 | 取决于增量序列,通常优于O(n^2),平均O(n^(1.3~1.5)) | O(1) | 否 | 顺序表 | |||
交换排序 | 冒泡排序 | 原本有序O(n) | O(n^2) | 原本逆序O(n^2) | O(1) | 是 | 顺序表、链表(没有顺序表高效) |
快速排序(分治) | O(nlog2n)每次划分很平均 | O(nlog2n) | O(n^2)原本正序或逆序 | O(log2n)每次划分很平均。O(n)完全不平衡。 | 否 | 顺序表 | |
选择排序 | 简单选择排序 | O(n^2)与序列初始状态无关 | O(1) | 否 | 顺序表、链表(没有顺序表方便) | ||
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 否 | 顺序表 | |
归并排序 | 2路归并排序(分治) | O(nlog2n)与初始序列的排列无关 | O(n),需要大小为n的辅助数组用于合并。 | 是 | 顺序表、链表 | ||
基数排序 | 基数排序 | O(d(n+k)),其中d是关键字的位数,n是待排序元素的个数,k是基数个数。时间复杂度与序列初始状态无关 | O(k) | 是 | 通常链表(优先),也可以顺序表 |
二、内部排序算法的应用
通常情况,对排序算法的比较和应用应考虑以下情况。
- 选取排序方法需要考虑的因素
- 待排序的元素数目n。
- 元素本身信息量的大小。
- 关键字的结构及其分布情况。
- 稳定性的要求。
- 语言工具的条件,存储结构及辅助空间的大小等。
- 排序算法小结
- 若n较小,可采用直接插入排序或简单选择排序。由于直接插入排序所需的记录移动次数较简单选择排序的多,因而当记录本身的信息量较大时,用简单选择排序较好。
- 若文件的初始状态已按关键字基本有序,则选用直接插入排序或冒泡排序为宜。
- 若n较大,则应采用时间复杂度为O(nlogn)的排序方法:快速排序、堆排序或归并排序。快速排序被认为是目前基于比较的内部排序算法中最好的方法,当待排序的关键字随机分布时,快速排序的平均时间最短。堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况,这两种排序都是不稳定的。若要求排序稳定且时间复杂度为O(nlogn),则可选择归并排序。但从单个记录起进行两两归并的排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子文件,然后两两归并。直接插入排序是稳定的,因此改进后的归并排序仍是稳定的。
- 在基于比较的排序算法中,每次比较两个关键字的大小后,仅出现两种可能得转移,因此可以用一棵二叉树来描述比较判定的过程,由此可以证明:当文件的n个关键字随机分布时,任何借助于“比较”的排序算法,至少需要O(nlog2n)的时间。
- 若n很大,记录的关键字位数较少且可以分解时,采用基数排序较好。
- 当记录本身信息量较大时,为避免耗费大量时间移动记录,可用链表作为存储结构。