前言:
之前介绍了选择,插入以及它们的优化,发下在几乎有序的情况下,插入排序的高效性~
一、冒泡排序
- 数组中第一个元素开始两两比较,前者比后者大就交换一下
- 第一趟的最大值已经排上去后,那么接着从第一个元素开始比较到n-1个数,以此类推~
public static void sort(Comparable[] arr){ int n = arr.length; // n-1和n都可以,因为下面的j还会判断一次 for(int i = 0; i < n-1; i ++){ for(int j = i + 1; j < n; j ++){ if(arr[i].compareTo(arr[j]) > 0) swap(arr, i, j); } } }
1.1 优化
每一趟的Sort都将最大值放在了后面,所以之后的每一趟都可以不用再考虑了,尽管比较简单,但是时间上还有一点点的提高
public static void sort(Comparable[] arr){ int n = arr.length; for(int i = 0; i < n-1; i ++){ for(int j = i + 1; j < n; j ++){ if(arr[i].compareTo(arr[j]) > 0) swap(arr, i, j); } } }
对4w个无序的数组进行测试,可知稍微有一点点的提高~
二、 希尔排序
这是插入排序衍生的,插入排序中每个元素和之前1个元素比较,而希尔是每个元素和t个元素比较,然后t慢慢缩小成1,整个整数从无序慢慢到几乎有序,那么到最后近乎有序,t为1的话就特别快了~ 时间复杂度为O(n^(3/2))
public static void sort(Comparable[] arr){ int n = arr.length; //步长为3 int h = 1; while(h < n/3) h = 3 * h + 1; while(h >= 1){ for(int i = h; i < n; i ++){ // 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序 Comparable e = arr[i]; int j = i; for( ; j >= h && e.compareTo(arr[j-h]) < 0; j -=h ){ arr[j] = arr[j-h]; //swap的优化写法 } arr[j] = e; } h /= 3; } }
四、总结:
- 希尔排序:插入的改进版,肯定是在这4种里最好的~
- 选择排序:简单但是两重循环每次都要完成~效率慢
- 插入排序:复杂度也是O(n^2),但是数组在几乎有序的情况下,效率甚至比 O(n* logn)的还要高,有着重要的实际意义
- 冒泡排序:有许多的换操作,平庸~
附一张O(n^2)排序算法跑数据的图: