排序算法是算法学习中比较经典的内容,面试也会经常考到,学习十大经典排序算法的目的在于理解并掌握其中运用的算法思想,还有装逼(不是
本片文章参考了博客十大经典排序算法(动图演示),该博客上还有排序的相关图解和JS代码实现,非常清晰
相关概念
- 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
- 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
- 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
- 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
下面代码通用的排序工具类,用于提供打印数组的方法和测试数据,并且下面排序算法都是按从小到大排序(从大到小反推即可)
1 | public class SortUtil { |
1.冒泡排序
冒泡排序的特点就是在交换相邻数组元素时,元素会一步一步地向末尾端移动,像冒泡一样
- 时间复杂度(平均):O(n^2)
- 时间复杂度(最好):O(n)
- 时间复杂度(最差):O(n^2)
- 空间复杂度:O(1)
- 稳定性:稳定
1 | public class BubbleSort { |
2.选择排序
选择排序的特点在于把数组分为有序和无序的,初始数组全为无序部分,然后从中选择最小(大)值放到有序部分(有序部分从数组的0下标开始),依次执行直到无序部分遍历结束
- 时间复杂度(平均):O(n^2)
- 时间复杂度(最好):O(n^2)
- 时间复杂度(最差):O(n^2)
- 空间复杂度:O(1)
- 稳定性:不稳定
1 | public class SelectSort { |
3.插入排序
插入排序的特点是也像选择排序那样分成有序和无序部分,不过它的第二轮循环没有遍历无序部分,而是遍历有序部分与无序部分的第一个元素进行比较,如果满足条件则将这当前元素插入到有序部分中,这里的插入是从后往前插
- 时间复杂度(平均):O(n^2)
- 时间复杂度(最好):O(n)
- 时间复杂度(最差):O(n^2)
- 空间复杂度:O(1)
- 稳定性:稳定
1 | public class InsertSort { |
4.希尔排序
希尔排序是第一个突破O(n^2)复杂度的排序算法。它是插入排序的优化版本,又叫缩小增量排序,插入排序每次比较的间隔都是1,而希尔排序的比较间隔是从大到小,如果后面的元素满足条件则也会从后往前插入
- 时间复杂度(平均):O(n^1.3)
- 时间复杂度(最好):O(n)
- 时间复杂度(最差):O(n^2)
- 空间复杂度:O(1)
- 稳定性:不稳定
1 | public class ShellSort { |
5.归并排序
归并排序的特点是通过分治法,先把无序队列分成子序列,分成子序列的关键在于变换首尾下标,起初是子序列是整个数组的长度然后慢慢递减到只有1个长度,然后使子序列有序,然后再把有序子序列合并起来,最终得到一个完整的有序序列
- 时间复杂度(平均):O(nlogn)
- 时间复杂度(最好):O(nlogn)
- 时间复杂度(最差):O(nlogn)
- 空间复杂度:O(n)
- 稳定性:稳定
1 | public class MergeSort { |
6.快速排序
快速排序的特点在于选择一个队列左侧的一个值作为基准值,然后通过比较基准值把比基准值小(大)的元素移动到队列前端(队列前端的数都比基准值小,后方都比基准值大),最后再把基准值移动到前端尾部进行下一轮递归。
- 时间复杂度(平均):O(nlogn)
- 时间复杂度(最好):O(nlogn)
- 时间复杂度(最差):O(n^2)
- 空间复杂度:O(nlogn)
- 稳定性:不稳定
1 | public class QuickSort { |
以后再写,困了…