排序
通常来说, 排序是为了进行快速排序
衡量排序算法的优劣方式
- 时间复杂度: 关键字的比较次数 与 记录的移动次数
- 空间复杂度: 排序算法中需要多少辅助内存
- 稳定性: 如果a原本在b前面, 且a=b, 排序之后a仍然在b的前面
排序前: [1, 2, 5, 3, 2]
排序后: [1, 2, 2, 3, 5]
可以看到第一个数组中有两个2, 如果排序后, 第一个2还是在前面, 第二个2在其后面, 称这个排序算法是稳定的
排序的分类
- 内部排序: 整个排序过程不需要借助于外部存储器(如磁盘等), 所有排序操作都在内存中完成
- 外部排序: 参与排序的数据较多, 数据量较大, 计算机内存发放全部加载, 必须借助于外部存储器(如磁盘);
外部排序最常见的是多路归并排序, 可以认为, 外部排序是由多次内部排序组成的.
算法的5大特征
- 输入: 有0个或多个输入数据, 这些输入必须有清楚的描述和定义
- 输出: 至少有一个或多个输出结果, 不可以没有输出结果
- 有穷性: 算法在有限的步骤之后会自动结束而不会无限循环, 并且每一个步骤可以在可接受的时间内完成
- 确定性: 算法中的每一步都有确定的含义, 不会出现歧义性(二义性)
- 可行性: 算法的每一步都是清楚且可行性的, 能让用户用纸和笔计算而求出答案
常见的排序算法及复杂度
算法分类
时间复杂度
算法比较分析
- 从平均时间而言: 快速排序最佳, 但是在最坏的情况下时间性能不如堆排序和归并排序
- 从算法简单性看: 由于选择排序/插入排序和冒泡排序的算法比较简单, 将其认为是加单算法; 对于希尔排序/堆排序/快速排序和归并排序算法, 其算法比较复杂, 认为是复杂排序
- 从稳定性看: 插入排序/冒泡排序和归并排序是最稳定的; 选择排序/快速排序/希尔排序和堆排序是不稳定的
- 从待排序的记录数n的大小看: n较小时, 宜采用简单排序, 而n较大时宜采用快速排序
算法的选择
- 若N较小(如$$ n ≤ 50 $$), 可以采用插入排序或者选择排序;
当记录规模较小时, 插入排序较好, 否则, 因为选择排序移动的记录数少于插入排序, 选择排序比较合适 - 若文件初始状态基本有序(正序), 应选用插入排序/冒泡排序或快速排序
- 若N较大, 应采用时间复杂度为$$O(nlogn)$$的排序方法: 快速排序/堆排序/归并排序
常见算法的实现
冒泡排序(Bubble Sort)
依次比较相邻元素的排序, 若发现逆序, 则交换, 使较大的元素交换到最后面
动图演示
%accordion% 代码实现 %accordion%
public static int[] maoPaoSort() {
/*
* 两个 for 循环的结束条件是重点; 每进行一次大循环, 就减少一个参与比较的数
*/
int[] arrMaoPao = new int[] { 46, 89, 23, 45, 12, 99, 55, 44, 43 };
for (int i = 0; i < arrMaoPao.length - 1; i++) {
for (int j = 0; j < arrMaoPao.length - i - 1; j++) {