八大排序方式
1.冒泡排序(属于交换排序的一种)
冒泡是最简单的一种排序方式了吧,从第一个元素开始和相邻的元素进行比较,比他大的不动,比它小的交换位置。
有n个数字,需要比较n-1趟
空间复杂度:O(1)
平均时间复杂度:O(n²)
最坏情况下时间复杂度:即每次都需要交换 O(n²),需要比较的次数是(n-1)+(n-2)+...+1 = n*(n-1)/2
最好情况下时间复杂度:0(n)
稳定性:稳定
public static void sort(int[] a) { //外层循环控制比较的次数 for (int i = 0; i < a.length - 1; i++) { //内层循环控制到达位置 for (int j = 0; j < a.length - i - 1; j++) { /前面的元素比后面大就交换 if (a[j] > a[j + 1]) { int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } }
2.简单选择排序:每次从没有排列过的序列中选择最小的数字放在开头,以此重复此操作。
稳定性:不稳定
平均时间复杂度 最好情况 最坏情况 空间复杂度
O(n²) O(n²) O(n²) O(1)
总结:即使序列基本有序,选择排序也需要花费n²/2次遍历来确认一遍
O(n²) O(n²) O(n²) O(1)
总结:即使序列基本有序,选择排序也需要花费n²/2次遍历来确认一遍
public static void sort(int[] a) { for (int i = 0; i < a.length; i++) { int min = i; //选出之后待排序中值最小的位置 for (int j = i + 1; j < a.length; j++) { if (a[j] < a[min]) { min = j; } } //最小值不等于当前值时进行交换 if (min != i) { int temp = a[i]; a[i] = a[min]; a[min] = temp; } } }
3.插入排序
插入排序有点类似于我们玩的扑克牌,假设第一张已经排好序,然后第二个和第一个进行比较,如果比他小,则放在第一个前面,如果比他大,则放在后面。第三个元素同理
/** * 通过交换进行插入排序,借鉴冒泡排序 * * @param a */ public static void sort(int[] a) { for (int i = 0; i < a.length - 1; i++) { for (int j = i + 1; j > 0; j--) { if (a[j] < a[j - 1]) { int temp = a[j]; a[j] = a[j - 1]; a[j - 1] = temp; } } } } /** * 通过将较大的元素都向右移动而不总是交换两个元素 * * @param a */ public static void sort2(int[] a) { for (int i = 1; i < a.length; i++) { int num = a[i]; int j; for (j = i; j > 0 && num < a[j - 1]; j--) { a[j] = a[j - 1]; } a[j] = num; } }
平均时间复杂度 最好情况 最坏情况 空间复杂度
O(n²) O(n²) O(n²) O(1)
插入排序总结:适合用于小规模的数据,或者基本有序的数据
O(n²) O(n²) O(n²) O(1)
插入排序总结:适合用于小规模的数据,或者基本有序的数据
前三种排序方式进行总结:是我们比较常见的三种排序方式,他们的评价时间复杂度都是O(n²) ,空间复杂度都是O(1),除了冒泡排序最好的情况下时间复杂度是O(1)以外,其他两个排序,简单选择,直接插入。不管最好和最坏情况下,时间复杂度都是O(n²)
4.希尔排序:其实是插入排序的一种改进方法。也称为递减增量排序算法。
第一次选择的步长是数组长度的一半。之后依次减半,直至为1.
根据步长分为不同序列的组,然后在不同序列内进行排序。
平均时间复杂度 最好情况 最坏情况 空间复杂度
| O(n^1.3) | O(nlogn) | O(n²) | O(1) |
5.归并排序:归并排序其实分为两步:分解,合并
分解:序列进行对半分解,直至1个为止。然后将两两比较,小的放前面。
合并:将分解后的序列进行合并
平均时间复杂度 最好情况 最坏情况 空间复杂度
O(nlog₂n) O(nlog₂n) O(nlog₂n) O(n)
注意:归并排序的空间复杂度为O(n)
O(nlog₂n) O(nlog₂n) O(nlog₂n) O(n)
注意:归并排序的空间复杂度为O(n)
6.快速排序
挑一个数字为基准,从后往前进行比较,大的放后面,小的放前面。最后相遇的位置放基准元素
平均时间复杂度 最好情况 最坏情况 空间复杂度
O(nlog₂n) O(nlog₂n) O(n²) O(1)(原地分区递归版)
这三种方式进行总结:除了归并排序外,其他两种排序,希尔排序,快速排序空间复杂度都是1。
7.基数排序
筒子排序,从0-9进行的排序
8.堆排序
大顶堆和小顶堆。
平均时间复杂度 最好情况 最坏情况 空间复杂度
O(nlog2n) O(nlog2n) O(nlog2n) O(1)
O(nlog2n) O(nlog2n) O(nlog2n) O(1)
堆排序和归并排序是除了空间复杂度不一样,其他都一样。
排序类型 平均情况 最好情况 最坏情况 辅助空间 稳定性
冒泡排序 O(n²) O(n) O(n²) O(1) 稳定
选择排序 O(n²) O(n²) O(n²) O(1) 不稳定
直接插入排序 O(n²) O(n) O(n²) O(1) 稳定
折半插入排序 O(n²) O(n) O(n²) O(1) 稳定
希尔排序 O(n^1.3) O(nlogn) O(n²) O(1) 不稳定
归并排序 O(nlog₂n) O(nlog₂n) O(nlog₂n) O(n) 稳定
快速排序 O(nlog₂n) O(nlog₂n) O(n²) O(nlog₂n) 不稳定
堆排序 O(nlog₂n) O(nlog₂n) O(nlog₂n) O(1) 不稳定
计数排序 O(n+k) O(n+k) O(n+k) O(k) 稳定
桶排序 O(n+k) O(n+k) O(n²) O(n+k) (不)稳定
基数排序 O(d(n+k)) O(d(n+k)) O(d(n+kd)) O(n+kd) 稳定
冒泡排序 O(n²) O(n) O(n²) O(1) 稳定
选择排序 O(n²) O(n²) O(n²) O(1) 不稳定
直接插入排序 O(n²) O(n) O(n²) O(1) 稳定
折半插入排序 O(n²) O(n) O(n²) O(1) 稳定
希尔排序 O(n^1.3) O(nlogn) O(n²) O(1) 不稳定
归并排序 O(nlog₂n) O(nlog₂n) O(nlog₂n) O(n) 稳定
快速排序 O(nlog₂n) O(nlog₂n) O(n²) O(nlog₂n) 不稳定
堆排序 O(nlog₂n) O(nlog₂n) O(nlog₂n) O(1) 不稳定
计数排序 O(n+k) O(n+k) O(n+k) O(k) 稳定
桶排序 O(n+k) O(n+k) O(n²) O(n+k) (不)稳定
基数排序 O(d(n+k)) O(d(n+k)) O(d(n+kd)) O(n+kd) 稳定
查看22道真题和解析