一. 基本思想
通过从左到右不断交换逆序的相邻元素,在一轮的交换之后,可以让未排序的元素上浮到右侧。在一轮循环中,如果没有发生交换,就说明数组已经是有序的,此时可以直接退出。
二. 代码实现
- 版本一
/**
- <br>冒泡排序</br>
*/
public class BubbleSort {
/**
* 外层循环控制比较的轮数,内层循环进行依次相邻元素的比较
* 在第一轮比较中,最大的元素冒泡到了最后的位置;
* 在第二轮比较中,第二大的元素冒泡到了倒数第二个位置;
* 依此类推。
* @param arr
*/
public static void sort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
- 版本二
/**
* <br>冒泡排序</br>
*/
public class BubbleSort2 {
public static void sort(int[] arr) {
int n = arr.length;
boolean swap;
do {
/**
* 这里的swap主要考虑的 如果数组是近乎有序的,
* 那么在某轮比较后,没有产生swap操作,即剩下的
* 未排序的元素已经是有序的了,就不用再比较了。
*/
swap = false;
for (int i = 0; i < n - 1; i++) {
if (arr[i] > arr[i + 1]) {
swap(arr, i, i + 1);
swap = true;
}
}
/**
* 每一趟Bubble Sort都将最大的元素放在了最后的位置
* 所以下一次排序, 最后的元素可以不再考虑
*/
n--;
} while (swap);
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
/**
* <br>冒泡排序优化</br>
*/
public class BubbleSort3 {
/**
* 按照之前升序排列,每轮循环将剩下元素中最大的元素调到最后.
* 考虑这样的情况:假设在前面未排序的元素中,后面靠近尾端的元素已经是有序的了,
* 但是之前的做法还是会每次把这些元素包括进去遍历.
* 例如:原始一组数据: 3,6,2,4,5
* 第一轮排序后:3,2,4,5,6
* 按照之前的思想:接下来的一轮回会在剩下的未排序序列 3,2,4,5中找出最大的元素调到最后,
* 但是4,5本身是有序的,他们在上一轮的遍历中并没有交换位置,所以我们完全可以依据上一轮的遍历设置个记录
* 最后交换顺序的指针,然后只需要遍历这个指针之前的元素.
*
* @param arr
*/
public static void sort(int[] arr) {
int n = arr.length;
int lastSwapIndex;
do {
//重置,清零
lastSwapIndex = 0;
for (int i = 0; i < n - 1; i++) {
if (arr[i] > arr[i+1]){
swap(arr,i,i+1);
// 记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑,注意这里的临界点
lastSwapIndex = i+1;
}
}
n = lastSwapIndex;
} while (lastSwapIndex > 0);
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}