十大排序算法性能对比
稳定性:例如[a,b],a和b是相等的,当排完序后a和b的位置互换了就说明不稳定,没有互换就说明稳定。
前言
算法都有优劣,了解算法的性能才能在实践中选择更好的算法,所以了解算法性能十分的必要。
在性能上对比归并排序、快速排序、堆排序是相对来说比较好的排序算法,可以重点理解下这些算法;希尔排序相对于以上三个并不是最好,但也可以重点学习理解,面试过程中考察点突发奇想,冒泡选择插入也说不定会考察。
扩展
在JDK中Array.sort()排序方法中,在数组长度小于286时,使用的是快速排序,而在数组长度小于47时使用的是插入排序。在JDK8中还有一点就是,在数组长度小于286大于47,并且数组具有一定结构,则使用归并排序。
一、选择排序
算法描述:
1、将第一位当成最小值,记录值和下标,用最小值向右进行逐个比较,查找是否有更小的,有则更新最小的值和下标。
2、判断最小值下标是否变动,变动则交换位置,将新的最小值位置赋值为旧的最小值,旧的赋值为新的最小值。
静态图解
动图图解
代码部分
/**
* 选择排序:
* 外层循环的作用:
* 选择排序执行的次数
* 内层循环的作用:
* 将第一位当成最小值,记录值和下标,用最小值向右进行逐个比较,查找是否有更小的,有则更新最小的值和下标。
* 判断语句的作用:
* 判断最小值下标是否变动,变动则交换位置,将新的最小值位置赋值为旧的最小值,旧的赋值为新的最小值。
*/
@Test
public void Test() {
int[] arr = new int[]{
-12, -55, -23, 43, 24, 34, 12};
SelectSortFun(arr);
Arrays.stream(arr).forEach(i -> System.out.print(i + " "));
}
public void SelectSortFun(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
// 选择排序执行的次数
int min = arr[i];
int minIndex = i;
for (int j = i; j < arr.length; j++) {
// 每次遍历确定最左边的一位最小值,所以从i开始。
if (min > arr[j+1]) {
min = arr[j+1];
minIndex = j+1;
}
}
if (i != minIndex) {
// 最小值有变动,不是原来的那个,则交换。
arr[minIndex] = arr[i]; // 查找到的最小值下标赋值为下标i的数
arr[i] = min; // 下标i赋值为最小值
}
}
}
二、冒泡排序
算法描述:两两进行比较,从左开始,5大于2则交换,5大于1则交换,如果有比5大的,则将自身下标设置为更大的值的下标,继续向后比较,直到自身为最大,则确定了数组最右边为第一个最大值,同理逐个确定,直到只剩一个则完成排序。
静态图解
动图图解
代码部分
@Test
public void Test() {
int[] arr = new int[]{
-12, -55, -23, 43, 24, 34, 12};
BubbleSortFun(arr);
Arrays.stream(arr).forEach(i -> System.out.print(i + " "));
}
public void BubbleSortFun(int[] arr) {
boolean flag = true; //优化有序数组多次进行循环,当遇到没交换位置的情况则提前终止循环
for (int i = 0; i < arr.length - 1; i++) {
// 冒泡的次数
for (int j = 0; j < arr.length - i - 1; j++) {
// 每次冒泡确定了最后一位数字,所以减i,防止再次遍历后面的数浪费时间。
if (arr[j] > arr[j + 1]) {
flag = false; // 进去了说明有无序数组则不跳过继续循环,没进去才跳过停止循环
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (flag) {
break;
}
}
}
三、插入排序
算法描述:认为第一个元素已经排序,从第二个元素开始(也就是下标1开始),取出下一个元素,向左扫描,如果取出的元素小于向左扫描的元素,则将扫描到的元素向右移,将取出的元素移动到比他更小的值的前一位。
动图图解
代码部分
@Test
public void Test() {
int[] arr = new int[]{
-12, -55, -23, 43, 24, 34, 12};
insertionSort(arr);
Arrays.stream(arr).forEach(i -> System.out.print(i + " "));
}
public int[] insertionSort(int[] arr) {
int preIndex,current; // pre是下一个需要排序的元素,cur是当前元素的备份值
for (int i = 1; i < arr.length; i++) {
preIndex = i - 1; // 移动的下标
current = arr[i]; // 记录被覆盖的值
while (preIndex >= 0 && arr[preIndex] > current) {
//
arr[preIndex + 1] =