概念(实现思想)
百度解释:它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
**个人理解**: 一次只比较两个数字 (第一个数字依次与后面的数字进行比较,如果大于(小于),则与后面的数字交换位置,保证每一次循环结束,最后一位的数字是最大值(最小值)。第二次将进行i-1次循环)。
时间复杂度为O(N^2),是稳定算法。
举例
原始序列:{10,1,35,61,89,36,55}
第一趟排序:
第一次排序:10和1比较,10大于1,交换位置 [1,10,35,61,89,36,55]
第二趟排序:10和35比较,10小于35,不交换位置 [1,10,35,61,89,36,55]
第三趟排序:35和61比较,35小于61,不交换位置 [1,10,35,61,89,36,55]
第四趟排序:61和89比较,61小于89,不交换位置 [1,10,35,61,89,36,55]
第五趟排序:89和36比较,89大于36,交换位置 [1,10,35,61,36,89,55]
第六趟排序:89和55比较,89大于55,交换位置 [1,10,35,61,36,55,89]
第一趟总共进行了六次比较,排序结果: [1,10,35,61,36,55,89]
第二趟排序:
第一次排序:1和10比较,1小于10,不交换位置 [1,10,35,61,36,55,89]
第二次排序:10和35比较,10小于35,不交换位置 [1,10,35,61,36,55,89]
第三次排序:35和61比较,35小于61,不交换位置 [1,10,35,61,36,55,89]
第四次排序:61和36比较,61大于36,交换位置 [1,10,35,36,61,55,89]
第五次排序:61和55比较,61大于55,交换位置 [1,10,35,36,55,61,89]
第二趟总共进行了5次比较,排序结果: [1,10,35,36,55,61,89]
第三趟排序:
1和10比较,1小于10,不交换位置 [1,10,35,36,55,61,89]
第二次排序:10和35比较,10小于35,不交换位置 [1,10,35,36,55,61,89]
第三次排序:35和36比较,35小于36,不交换位置 [1,10,35,36,55,61,89]
第四次排序:36和61比较,36小于61,不交换位置 [1,10,35,36,55,61,89]
第三趟总共进行了4次比较,排序结果: [1,10,35,36,55,61,89]
代码实现
一、普通代码实现
public static void bubble(int[] arr) {
if(arr==null || arr.length<2) {
return;
}
//外层循环控制排序的趟数
for(int x=arr.length-1;x>0;x--) {
//内层循环控制当前趟数需要比较的次数
for(int i = 0;i<x;i++) {
//当前位置的数与后一位进行比较,如果大于后一位,进行交换
if(arr[i]>arr[i+1]) {
swap(arr,i,i+1);
}
}
}
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
二、优化后的冒泡排序
实现思想: 如果在某躺排序中没有发生交换位置,那么我们可以认为该数组已经排好序了。 这也不难理解,因为 我们每趟排序的目的就是将当前趟最大的数置换到对应的位置上,没有发生置换说明就已经排好序了。
public static void bubble(int[] arrays) {
// 装载临时变量
int temp;
int num = 0;
// 记录是否发生了置换, 0 表示没有发生置换、 1 表示发生了置换
int isChange;
// 外层循环是排序的趟数
for (int i = 0; i < arrays.length - 1; i++) {
// 每比较一趟就重新初始化为0
isChange = 0;
// 内层循环是当前趟数需要比较的次数
for (int j = 0; j < arrays.length - i - 1; j++) {
// 前一位与后一位与前一位比较,如果前一位比后一位要大,那么交换
if (arrays[j] > arrays[j + 1]) {
temp = arrays[j];
arrays[j] = arrays[j + 1];
arrays[j + 1] = temp;
//如果进到这里面了,说明发生置换了
isChange = 1;
}
}
// 如果比较完一趟没有发生置换,那么说明已经排好序了,不需要再执行下去了
if (isChange == 0) {
break;
}
num++;
}
System.out.println(num);
与选择排序的对比
1)冒泡排序是比较相邻位置的两个数,而选择排序是按顺序比较,找最大值或者最小值;
2)冒泡排序每一轮比较后,位置不对都需要换位置,选择排序每一轮比较都只需要换一次位置;
3)冒泡排序是通过数去找位置,选择排序是给定位置去找数。