冒泡排序
在平常的學習中用到了冒泡排序,這篇博客對冒泡排序算法進行了詳細的代碼實現,並且進行了兩次優化,供大家一起參考學習。
冒泡排序是一種最基礎的交換排序。冒泡排序就像水冒泡,小(大)的元素經過不斷的交換由水底慢慢的浮到水的頂端。
冒泡排序算法的思想:我們從左把相鄰的兩個數兩兩做比較,當一個元素大於右側與它相鄰的元素時,交換它們之間位置,反之,它們之間的位置不發生變化,冒泡排序是一種穩定的排序算法。
時間複雜度 | 空間複雜度 |
---|---|
O(n^2) | O(1) |
代碼實現
public class BubbleSort1 {
public static void main(String[] args) {
System.out.println("輸入要排序的值,輸入的每個值用逗號隔開:");
Scanner input = new Scanner(System.in);
String str = input.nextLine();
// 將字符串按照","拆分成字符串數組
String[] strArray = str.split(",");
// 新建數組用來存儲拆分出來的每個值
int[] array = new int[strArray.length];
// 給數組循環遍歷賦值
for (int i = 0; i < strArray.length; i++) {
array[i] = Integer.parseInt(strArray[i]);
}
System.out.println("排序前的數組:" + Arrays.toString(array));
// 排序
sort(array);
System.out.println("排序後的數組:" + Arrays.toString(array));
}
/**
* 用冒泡排序算法對數組進行排序
* @param array
*/
private static void sort(int[] array) {
// array.length - 1是因爲最後一輪不需要排序
for (int i = 0; i < array.length - 1; i++) {
System.out.println("第" + (i + 1) + "趟");
// array.length - i是因爲每一輪都能確定排序好一個數
for (int j = 0; j < array.length - 1 - i; j++) {
int temp = 0;
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
System.out.println(" 第" + (j + 1) + "次:" + Arrays.toString(array));
}
}
}
}
算法執行結果:
輸入要排序的值,輸入的每個值用逗號隔開:
6,9,8,3,2,11,15,16,18,19
排序前的數組:[6, 9, 8, 3, 2, 11, 15, 16, 18, 19]
第1趟
第1次:[6, 9, 8, 3, 2, 11, 15, 16, 18, 19]
第2次:[6, 8, 9, 3, 2, 11, 15, 16, 18, 19]
第3次:[6, 8, 3, 9, 2, 11, 15, 16, 18, 19]
第4次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第5次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第6次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第7次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第8次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第9次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第2趟
第1次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第2次:[6, 3, 8, 2, 9, 11, 15, 16, 18, 19]
第3次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第4次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第5次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第6次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第7次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第8次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第3趟
第1次:[3, 6, 2, 8, 9, 11, 15, 16, 18, 19]
第2次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第4次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第5次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第6次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第7次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第4趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第2次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第4次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第5次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第6次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第5趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第2次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第4次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第5次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第6趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第2次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第4次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第7趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第2次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第8趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第2次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第9趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
排序後的數組:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
從上圖中的運行結果可以看出,第5趟排序後就已經是有序的了,可是算法還是進行了後面的排序。
因此對算法進行以下的第一次優化:
增加一個標記(flag),每次發生交換,就進行標記,如果某次循環完沒有標記,則說明已經完成排序,數組有序,剩下的幾趟排序就不需要再去執行了,可以提前結束排序。
public class BubbleSort2 {
public static void main(String[] args) {
System.out.println("輸入要排序的值,輸入的每個值用逗號隔開:");
Scanner input = new Scanner(System.in);
String str = input.nextLine();
// 將字符串按照","拆分成字符串數組
String[] strArray = str.split(",");
// 新建數組用來存儲拆分出來的每個值
int[] array = new int[strArray.length];
// 給數組循環遍歷賦值
for (int i = 0; i < strArray.length; i++) {
array[i] = Integer.parseInt(strArray[i]);
}
System.out.println("排序前的數組:" + Arrays.toString(array));
// 排序
sort(array);
System.out.println("排序後的數組:" + Arrays.toString(array));
}
/**
* 用冒泡排序算法對數組進行排序
*
* @param array
*/
private static void sort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
System.out.println("第" + (i + 1) + "趟");
// 優化冒泡排序,增加判斷位,有序標記,每一輪的初始是true
boolean flag = true;
for (int j = 0; j < array.length - 1 - i; j++) {
// 找最小數,如果前一位比後一位大,則交換位置
int temp = 0;
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
// 有元素交換,所以不是有序,標記變爲false
flag = false;
}
System.out.println(" 第" + (j + 1) + "次:" + Arrays.toString(array));
}
// 說明上面內層for循環中,沒有交換任何元素,直接跳出外層循環
if (flag) {
break;
}
}
}
}
算法執行結果:
輸入要排序的值,輸入的每個值用逗號隔開:
6,9,8,3,2,11,15,16,18,19
排序前的數組:[6, 9, 8, 3, 2, 11, 15, 16, 18, 19]
第1趟
第1次:[6, 9, 8, 3, 2, 11, 15, 16, 18, 19]
第2次:[6, 8, 9, 3, 2, 11, 15, 16, 18, 19]
第3次:[6, 8, 3, 9, 2, 11, 15, 16, 18, 19]
第4次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第5次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第6次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第7次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第8次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第9次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第2趟
第1次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第2次:[6, 3, 8, 2, 9, 11, 15, 16, 18, 19]
第3次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第4次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第5次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第6次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第7次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第8次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第3趟
第1次:[3, 6, 2, 8, 9, 11, 15, 16, 18, 19]
第2次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第4次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第5次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第6次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第7次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第4趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第2次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第4次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第5次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第6次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第5趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第2次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第3次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第4次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第5次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
排序後的數組:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
從第一次優化後的結果可以看出,在每趟排序中,右面的許多元素已經是有序的結果了,可算法還是進行後面數值的排序。
因此進行第二次優化:
定義arrBoundary 是無序數組的邊界,每次比較比到這裏爲止,不需要進行後面的排序了。
public class BubbleSort3 {
public static void main(String[] args) {
System.out.println("輸入要排序的值,輸入的每個值用逗號隔開:");
Scanner input = new Scanner(System.in);
String str = input.nextLine();
// 將字符串按照',"拆分成字符串數組
String[] strArray = str.split(",");
// 新建數組用來存儲拆分出來的每個值
int[] array = new int[strArray.length];
// 給數組循環遍歷賦值
for (int i = 0; i < strArray.length; i++) {
array[i] = Integer.parseInt(strArray[i]);
}
System.out.println("排序前的數組:" + Arrays.toString(array));
// 排序
sort(array);
System.out.println("排序後的數組:" + Arrays.toString(array));
}
/**
* 用冒泡排序算法對數組進行排序
*
* @param array
*/
private static void sort(int[] array) {
// 用來交換的臨時數
int temp = 0;
// 最後一次交換的下標
int lastSwapIndex = 0;
// 無序數組的邊界,每次比較比到這裏爲止
int arrBoundary = array.length - 1;
for (int i = 0; i < array.length - 1; i++) {
System.out.println("第" + (i + 1) + "趟");
// 優化冒泡排序,增加判斷位,有序標記,每一輪的初始是true
boolean flag = true;
for (int j = 0; j < arrBoundary; j++) {
// 找最小數,如果前一位比後一位大,則交換位置
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
// 有元素交換,所以不是有序,標記變爲false
flag = false;
// 最後一次交換元素的位置
lastSwapIndex = j;
}
System.out.println(" 第" + (j + 1) + "次:" + Arrays.toString(array));
}
// 把最後一次交換元素的位置賦值給無序數組的邊界
arrBoundary = lastSwapIndex;
// 說明上面內層for循環中,沒有交換任何元素,直接跳出外層循環
if (flag) {
break;
}
}
}
}
算法執行結果:
輸入要排序的值,輸入的每個值用逗號隔開:
6,9,8,3,2,11,15,16,18,19
排序前的數組:[6, 9, 8, 3, 2, 11, 15, 16, 18, 19]
第1趟
第1次:[6, 9, 8, 3, 2, 11, 15, 16, 18, 19]
第2次:[6, 8, 9, 3, 2, 11, 15, 16, 18, 19]
第3次:[6, 8, 3, 9, 2, 11, 15, 16, 18, 19]
第4次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第5次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第6次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第7次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第8次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第9次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第2趟
第1次:[6, 8, 3, 2, 9, 11, 15, 16, 18, 19]
第2次:[6, 3, 8, 2, 9, 11, 15, 16, 18, 19]
第3次:[6, 3, 2, 8, 9, 11, 15, 16, 18, 19]
第3趟
第1次:[3, 6, 2, 8, 9, 11, 15, 16, 18, 19]
第2次:[3, 2, 6, 8, 9, 11, 15, 16, 18, 19]
第4趟
第1次:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]
第5趟
排序後的數組:[2, 3, 6, 8, 9, 11, 15, 16, 18, 19]