一、冒泡排序原理
基本概念
假设数组arr,长度是N,升序排序。每轮循环总能找到一个最大值。
第0轮循环:第一个数与第二个数比较,若第二个数小于第一个数,则交换顺序;否则不变;
第二个数与第三个数比较,若第三个数小于第二个数,则交换顺序,否则不变;
。。。。
第九个数与第十个数比较,若第十个数小于第九个数,则交换顺序,否则不变;
第一轮循环结束,共比较9次,最大的数字在arr[9]。
第1轮循环:第一个数与第二个数比较,若第二个数小于第一个数,则交换顺序;否则不变;
第二个数与第三个数比较,若第三个数小于第二个数,则交换顺序,否则不变;
。。。。
第八个数与第九个数比较,若第九个数小于第八个数,则交换顺序,否则不变;
第二轮循环结束,共比较8次,最大的数字在arr[8]。
。。。。
第8轮循环:第一个数与第二个数比较,若第二个数小于第一个数,则交换顺序;否则不变;
第一轮循环结束,共比较1次,最大的数字在arr[1],此时arr[1]~arr[9]是顺序的,也就可知arr[0]也找到了自己的顺序。
性能分析
冒泡排序性能取决于原始数据的顺序,外层循环要执行N-1次,内层循环要执行最多N-1,最少执行1次,平均执行(N+1)/2次数。
平均执行次数是(N-1)(N+1)/2,时间复杂度是O(N*N)。
二、实现思路
标准版
二重循环中,外层循环i(i < N-1):0 ~ N-1,外层循环j(j < N-1-i):0,1,2,N-1-j
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {2, 6, 8, 1, 4, 5, 9, 3, 7, 0};
sort(arr);
}
private static void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
//递增排序
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] + arr[j + 1];
arr[j+1] = arr[j] - arr[j + 1];
arr[j] = arr[j] - arr[j + 1];
}
}
System.out.println(Arrays.toString(arr));
// [2, 6, 1, 4, 5, 8, 3, 7, 0, 9]
// [2, 1, 4, 5, 6, 3, 7, 0, 8, 9]
// [1, 2, 4, 5, 3, 6, 0, 7, 8, 9]
// [1, 2, 4, 3, 5, 0, 6, 7, 8, 9]
// [1, 2, 3, 4, 0, 5, 6, 7, 8, 9]
// [1, 2, 3, 0, 4, 5, 6, 7, 8, 9]
// [1, 2, 0, 3, 4, 5, 6, 7, 8, 9]
// [1, 0, 2, 3, 4, 5, 6, 7, 8, 9]
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
System.out.println(Arrays.toString(arr));
//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
优化版
当第一次循环结束之后,数组已经有序,就不需要继续进行第二次、第三次循环。
//int[] arr = {9,1,2,3,4,5,6};
private static void improveSort(int[] arr) {
boolean isSwap = false;
for (int i = 0; i < arr.length - 1; i++) {
isSwap = false;
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] + arr[j + 1];
arr[j+1] = arr[j] - arr[j + 1];
arr[j] = arr[j] - arr[j + 1];
isSwap = true;
}
}
if (!isSwap) {
break;
}
System.out.println(i + " " + Arrays.toString(arr));
}
}