1. 简介
1.1 常用术语
- 时间复杂度:程序执行时间与数据输入规模的关系
- 空间复杂度:程序存储空间与数据输入规模的关系
- 稳定性:
- 稳定:一组数据中,a在b前面并且a = b,排序后依旧a 依旧在b前面
- 不稳定:一组数据中,a在b前面并且a=b,排序后a可能在b后面
1.2 十大排序算法
- 冒泡,插入,选择
- 归并,快速
- 桶排序,计数排序,基数排序
- 堆排序,希尔排序
- Time排序:插入排序 + 归并排序
1.3 面试考察点
- 分析某个具体的排序算法(Time, Space, 稳定性)
- 对比某几个排序算法(Time, Space, 稳定性)
- 代码实现某种排序算法(快排,归并等)
2. 冒泡排序Bubble Sort
2.1 特点
- 比较相邻元素
- 大的元素后置
2.2 应用
5, 3, 1, 2, 7, 6 排序
3, 5, 1, 2, 7, 6
3, 1, 5, 2, 7, 6
3, 1, 2, 5, 7, 6
3, 1, 2, 5, 7, 6
3, 1, 2, 5, 6, 7
1, 3, 2, 5, 6, 7
1, 2, 3, 5, 6, 7
2.3 算法分析
时间复杂度:
最好时间复杂度:排好序的,不用交换O(n)
最差时间复杂度:n + (n - 1) + (n - 2) + … + 2 + 1 = n(n + 1)/2 ,取最大项O(n^2)
空间复杂度:两个数交换,没有用到额外空间O(1)
稳定性:
举例:
9, 9, 1, 2 排序
9, 9, 1, 2
9, 1, 9, 2
9, 1, 2, 9
1, 9, 2, 9
1, 2, 9, 9
第一个9和第二个9位置没有发生变化,稳定
3. 选择排序Selection Sort
3.1 特点
- 找到最小元素
- 交换
3.2 示例
5, 3, 1, 2, 7, 6 排序
1, 3, 5, 2, 7, 6
1, 2, 5, 3, 7, 6
1, 2, 3, 5, 7, 6
1, 2, 3, 5, 6, 7
3.3 算法分析
- 时间复杂度:
- 最好时间复杂度:排好序的,不需要交换,但需要遍历数组找到最小值放到第一、第二…个位置 n(n+1)/2 = n^2 O(n^2)
- 最差时间复杂度:O(n^2)
- 空间复杂度:只是两数内部交换,没有用到额外的空间O(1)
- 稳点性:
举例:
3, 3, 1
1, 3, 3
第一个3和第二3位置发生了改变,不稳定
4. 插入排序 Insertion Sort
4.1 特点
- 找到数的位置
- 插入数
4.2 示例
5, 3, 1, 2, 7, 6 排序
3, 5, 1, 2, 7, 6
1, 3, 5, 2, 7, 6
1, 2, 3, 5, 7, 6
1, 2, 3, 5, 6, 7
4.3 算法分析
时间复杂度:
最好时间复杂度:排好序的,不用插入,但需要遍历 O(n)
最坏时间复杂度:只是两数内部交换,没有使用额外空间O(1)
稳点性:
举例:
3, 3, 1 排序
3, 3, 1
3, 1, 3
1, 3, 3
3排序前后位置没有发生改变,稳定
- 二分插入排序法:
5, 3, 1, 2, 7, 6
3, 5, 1, 2, 7, 6
3 和5 用二分查找,时间复杂度为logn
5. 快速排序 Quick Sort
5.1 特点
- 挑一个元素 pivot[基准]
- 小于pivot的值放大前面
- 大于pivot的值放到后面
- [<pivot] pivot [>pivot]
5.2 示例
8, 5, 3, 1, 7, 2, 6 排序
- 选取 6 为pivot 双指针
2, 5, 3, 1, 7, 8, 6
2, 5, 3, 1, 6, 8, 7
2, 5, 3, 1 6, 8, 7
- 选取1为pivot
1, 5, 3, 2 7, 8
1 5, 3, 2 6 7, 8
- 选取2为pivot
1, 2, 3, 5, 6 7, 8
1, 2 3, 5, 6 7, 8
算法分析:
时间复杂度:
最好时间复杂度:每次取到的数都能把数分为两个部分O(nlogn)
最坏时间复杂度:O(n^2)
空间复杂度:使用递归,每次都折半 O(logn)
稳定性:
举例:
8, 7, 7 排序
选择7位pivot
7, 7, 8
排序前后7位置发生了改变,不稳定