冒泡排序(Bubble Sorting)的基本思想:
通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒,每次冒泡完就会将参与这次冒泡的元素中的最大值或最小值排到最后。
举个栗子:
对9 5 2 10 0从小到大排序
第一趟:比较了4次
9 5 2 10 0
9 5 ……9>5 交换
5 9 2 10 0
9 2 ……9>2 交换
5 2 9 10 0
9 10 ……9<10 不交换
10 0 ……10>0 交换
5 2 9 0 10
第二趟:比较了3次
5 2 9 0 10
5 2 ……5>2 交换
2 5 9 0 10
5 9 ……5<9 不交换
9 0 ……9>0 交换
2 5 0 9 10
第三趟:比较了2次
2 5 0 9 10
2 5 ……2<5 不交换
5 0 ……5>0 交换
2 0 5 9 10
第四趟:比较了1次
2 0 5 9 10
2 0 ……2>0 交换
0 2 5 9 10 排序结果
上面对5个数进行排序,一共冒泡了5-1=4趟,没趟比较了5-当前趟数次。由此可以得到结论:
当对n个数冒泡时,要比较n-1趟,设当前趟数我i,则当前要比较n-i次。
代码实现:
public class BubbleSort {
public static void main(String[] args) {
int[] nums = new int[]{10, 2, 11, 56, 0, 8, 90, 22, 1, 66};
for (int num : nums) {
System.out.print(num + "\t");
}
System.out.println();
bubbleSort(nums);
for (int num : nums) {
System.out.print(num + "\t");
}
System.out.println();
}
public static void bubbleSort(int[] nums) {
int length = nums.length;
for (int i = 0; i < length - 1; i++) { // 比较 n-1 趟
for (int j = 0; j < length - i - 1; j++) { // 每趟比较 n-趟数 次
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
}
}
结果
10 2 11 56 0 8 90 22 1 66
0 1 2 8 10 11 22 56 66 90
助记:外层循环 n-1, 内层循环 n-i-1
代码优化
有时候在排序的过程中就已经成为有序的了,不需在继续进行比较了,这种情况就可以进行优化。
比如举个极端的栗子,直接给你一个有序的数组,那还需要进行一趟一趟的去比较吗,这样根本没意义。
public static void bubbleSort(int[] nums) {
int length = nums.length;
// 定义一个标志,标志每一趟排序有没有交换过数据
boolean flag = false;
for (int i = 0; i < length - 1; i++) { // 比较 n-1 趟
for (int j = 0; j < length - i - 1; j++) { // 每趟比较 n-趟数 次
if (nums[j] > nums[j + 1]) {
// 当进入这个判断后,说明这趟排序有过交换
flag = true;
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
if (!flag) {
// 如果flag还是false,说明这趟排序没有交换过数据
// 数组已经是有序的了,那么久直接退出比较
break;
} else {
// 如果交换过数据,重置flag为false
flag = false;
}
}
}
}
时间复杂度:O(n^2)