思想
- 两两交换,每趟排序冒出两个数,比较后大的放在后面。
- 尾部为有序区,每趟排序后数组尾部多增加一个最大有序数。
经典冒泡排序
public static int[] bubbleSort(int[] arr) {
// System.out.println("in bubble");
long startTime=System.nanoTime();
//外层循环i控制排序的趟数
for (int i = 0; i < arr.length - 1; i++) {
//每次循环后,尾部有序区多增加一个元素,内部循环只需比较无序区
//内层循环j控制的是比较次数,也为要比较的数的下标
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
// System.out.println(Arrays.toString(arr));
}
long endTime = System.nanoTime();
System.out.println("bubbleSort take " + (endTime - startTime) + "ns");
return arr;
}
优化后的冒泡排序
假如输入的数组已经是有序数组,或者经过少量趟数后数组已有序,那么此时即使数组已经排序好,程序也会运行到最后一趟。
若我们能在程序排序好的时候跳出循环,就不需要进行后面的无效排序趟数。
所谓排序好的时机就是:一趟比较下来数组的位置并没有发生变化。
代码实现思路
可以设置一个布尔值isChanged,在每趟排序开始时将其置为false,在发生交换操作的时候置为true。当一趟排序完成后,若isChanged还为false,说明数组已有序。
public static int[] bubbleSort(int[] arr) {
// System.out.println("in bubble");
long startTime=System.nanoTime();
System.out.println();
boolean isChanged = true;
//若上一趟遍历数组元素没有发生变化,则不需要再进行排序
for (int i = 0; i < arr.length - 1 && isChanged; i++) {
isChanged = false;
//每次循环后,尾部有序区多增加一个元素,内部循环只需比较无序区
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
//如果进入到if里面,说明发生置换了,数组还没有排序好
isChanged = true;
}
}
// System.out.println(Arrays.toString(arr));
}
long endTime = System.nanoTime();
System.out.println("bubbleSort take " + (endTime - startTime) + "ns");
return arr;
}