解题思路
1.数组下标为0的数先与右边的数进行比较,如果下标为0的数更大,则交换两数,如果右边的数更大,则不变。
2.以此类推,右边的数再与右边+1的数进行比较,把更大的数交换到右侧来,直至数组最后一个数为最大值。
3.至此,最大的数已经到右边来了,依次循环把次大数冒泡到右边,每次循环次数少1。
/**
* @author Wengong lin
* @date 2023/4/19 12:34
* @description 冒泡排序
*/
public class BubbleSort {
private static int COMPARE_NUMBER = 0;
private static int SWAP_NUMBER = 0;
public static void main(String[] args) {
int [] arr = {5,3,8,1,6,9,7,2,4};
System.out.println("排序前:");
printArr(arr);
bubbleSort(arr);
System.out.println("排序后:");
printArr(arr);
System.out.println("比较次数:" + COMPARE_NUMBER);
System.out.println("交换次数:" + SWAP_NUMBER);
}
public static void bubbleSort(int []arr) {
for (int i = arr.length-1; i > 1; i--) {
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j+1]) swap(arr,j,j+1);
COMPARE_NUMBER++;
}
}
}
public static void swap(int[] arr, int i, int minIndex) {
SWAP_NUMBER ++;
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
public static void printArr(int [] arr) {
for (int item : arr) {
System.out.print(item + " ");
}
System.out.println();
}
}
运行样例
代码优化
优化思路:如果一轮冒泡比较下来,没有发生交换,则说明数列已经是有序的,则不用继续循环比较下去
/**
* @author Wengong lin
* @date 2023/4/19 13:02
* @description 冒泡排序优化
* 优化思路:如果一轮冒泡比较下来,没有发生交换,则说明数列已经是有序的,则不用继续循环比较下去
*/
public class BubbleSortOpt {
private static int COMPARE_NUMBER = 0;
private static int SWAP_NUMBER = 0;
public static void main(String[] args) {
int [] arr = {5,3,8,1,6,9,7,2,4};
System.out.println("排序前:");
printArr(arr);
bubbleSortOpt(arr);
System.out.println("排序后:");
printArr(arr);
System.out.println("比较次数:" + COMPARE_NUMBER);
System.out.println("交换次数:" + SWAP_NUMBER);
}
public static void bubbleSortOpt(int []arr) {
for (int i = arr.length-1; i > 0; i--) {
boolean flag = true;
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j+1]) {
swap(arr,j,j+1);
flag = false;
}
COMPARE_NUMBER++;
}
if (flag) break;;
}
}
public static void swap(int[] arr, int i, int minIndex) {
SWAP_NUMBER ++;
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
public static void printArr(int [] arr) {
for (int item : arr) {
System.out.print(item + " ");
}
System.out.println();
}
}
运行样例
对数器测试
import java.util.Arrays;
import java.util.Random;
/**
* @author Wengong lin
* @date 2023/4/19 10:56
* @description 对数器
*/
public class DataChecker {
public static int[] generateRandomArray() {
Random random = new Random();
int[] arr = new int[10000];
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(10000);
}
return arr;
}
public static void check1() {
int[] arr1 = generateRandomArray();
int[] arr2 = new int[arr1.length];
System.arraycopy(arr1,0, arr2,0, arr2.length);
Arrays.sort(arr1);
BubbleSort.bubbleSort(arr2);
boolean flag = true;
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
flag = false;
break;
}
}
System.out.println(flag ? "right" : "wrong");
}
public static void check2() {
int[] arr1 = generateRandomArray();
int[] arr2 = new int[arr1.length];
System.arraycopy(arr1,0, arr2,0, arr2.length);
Arrays.sort(arr1);
BubbleSortOpt.bubbleSortOpt(arr2);
boolean flag = true;
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
flag = false;
break;
}
}
System.out.println(flag ? "right" : "wrong");
}
public static void main(String[] args) {
check1();
check2();
}
}
测试结果
时间复杂度
一般情况下,经过两次循环,每次循环把最大的数冒泡到右侧,时间复杂度为n^2。
最好的情况下,数组本身为有序,循环对比一次后发现不需要进行交换,直接退出循环,时间复杂度为n。
稳定性
左相邻的两个数进行比较,不发生跳跃性交换,算法稳定。