数据结构与算法
冒泡/插入/选择排序
思考
- 如何分析一个排序算法
- 冒泡排序的原理和性能分析
- 插入排序的原理和性能分析
- 选择排序的原理和性能分析
如何分析一个排序算法
- 最好情况、最坏情况、平均情况时间复杂度
- 为了对比各种排序算法,有必要分析
- 有序和无序,性能还有有影响
- 时间复杂度的系数、常数、低阶
- 10,100,1000比较不同排序算法,系数、常数、低阶还是有必要的
- 比较次数和交换次数
- 元素比较大小
- 元素移动(交换)位置
❝排序算法的内存消耗:原地排序,空间复杂度为O(1)的排序算法
❞
❝排序算法的稳定性:元素中存在相同的元素,排序的同时,不改变相同元素的排序位置,前后顺序不变
❞
3, 3, 5, 6 => 6, 5, 3, 3 (3, 3 相对位置不变)
冒泡排序
冒泡排序只会操作相邻的两个数据
冒泡排序是原地排序算法
- 涉及常量数据的交换,空间复杂度O(1)
冒泡排序是稳定的排序算法
- 数据相同时,不改变相对位置
冒泡排序的时间复杂度
- 最好情况O(n)
- 最坏情况O(n^2)
冒泡排序的平均情况复杂度分析
- 有序度和逆序度
❝有序度:有序元素对:a[i] <= a[j], 如果i < j。
❞
❝逆序度:有序元素对:a[i] < a[j], 如果i > j。
❞
逆序度 + 有序度 = 满有序度
交换次数总是确定的,初始状态时,要进行n(n-1)/2次交换,最好情况下也就是n(n-1)/2,去中间值n(n-1)/4,冒泡排序的平均情况复杂度O(n^2)
插入排序
分为两个区间,已排序区间和未排序区间,取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入
- 稳定排序算法
- 原地排序算法
- 时间复杂度最好O(n),最坏O(n^2)
选择排序
分为两个区间,已排序区间和未排序区间,选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾
- 稳定排序算法
- 非原地排序算法,顺序不可控制
- 时间复杂度最好O(n),最坏O(n^2)
插入排序VS冒泡排序
// 冒泡排序中数据的交换操作:
if (a[j] > a[j+1]) { // 交换
let tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
flag = true;
}
// 插入排序中数据的移动操作:
if (a[j] > value) {
a[j+1] = a[j]; // 数据移动
} else {
break;
}
推荐用插入排序算法
❝用冒泡排序,需要 K 次交换操作,每次需要 3 个赋值语句,所以交换操作总耗时就是 3*K 单位时间。而插入排序中数据移动操作只需要 K 个单位时间
❞
希尔排序,插入排序的优化