資料結構之氣泡排序(java)
氣泡排序可以說是最簡單的排序演算法,但不意味著它不重要。
理解氣泡排序,可以帶出以下問題。
1.氣泡排序只有一個基本操作,就是比較和交換相鄰的兩個元素,可以提現將一個複雜問題轉化為簡單問題的疊加的思想。
2.氣泡排序的兩層for迴圈該如何理解。
3.分析時間複雜度簡單,程式碼很短,一眼就能看出是O(n^2)。
4.分析完氣泡排序可以發現,其他O(n^2)級別的演算法或多或少與氣泡排序有共同之處:用O(n)的複雜度來排好一個元素。理解完氣泡排序,之後便於理解其他O(n^2)級別的演算法。
舉個栗子: -->4 3 2 7 1 6 5
第一層for迴圈:e=6,即確定第6個位置的值
第二層for迴圈:i=0,比較a[0]與a[1],4>3,交換a[0]與a[1]的位置,陣列變為:3 4
i=1,比較a[1]與a[2],4>2,交換a[1]與a[2]的位置,陣列變為:3 2 4 7 1 6 5
i=2,比較a[2]與a[3],4<7,不交換
i=3,比較a[3]與a[4],7>1,交換a[3]與a[4]的位置,陣列變為:3 4 2 1 7 6 5
i=4,比較a[4]與a[5],7>6,交換a[0]與a[1]的位置,陣列變為:3 4 2 1 6 7
i=5,比較a[5]與a[6],7>5,交換a[0]與a[1]的位置,陣列變為:3 4 2 7 1 5 7
陣列中的最大數不斷下沉,沉到最後一個位置
之後依次確定倒數第二個位置的數(即次小的數),倒數第三個位置的數,......
氣泡排序實現可以做到穩定性
下面給出氣泡排序的java程式碼:
import java.util.Arrays; public class BubbleSort { public static void bubbleSort(int[] arr) { // 若陣列為空,則直接返回。 if (arr == null || arr.length < 2) { return; } // 將陣列分為未排序區和已排序區。外層for迴圈每迴圈一次,確定已排序區的一個元素。 for (int e = arr.length - 1; e > 0; e--) { for (int i = 0; i < e; i++) { if (arr[i] > arr[i + 1]) { swap(arr, i, i + 1); } } } } // 注意:適用情況:i與j不同 // i代表甲資訊量,j代表乙資訊量 public static void swap(int[] arr, int i, int j) { arr[i] = arr[i] ^ arr[j]; // arr[i] = 甲 ^ 乙 arr[j] = arr[i] ^ arr[j]; // arr[j] = 甲 ^ 乙 ^ 乙 = 甲 (乙與乙異或為0,甲與0異或為甲) arr[i] = arr[i] ^ arr[j]; // arr[i] = 甲 ^ 乙 ^ 甲 ^ 乙 ^ 乙 = 乙;實現交換 } // 比較器 public static void comparator(int[] arr) { Arrays.sort(arr); } // 生成隨機陣列 public static int[] generateRandomArray(int maxSize, int maxValue) { int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; for (int i = 0; i < arr.length; i++) { arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); } return arr; } // 複製陣列 public static int[] copyArray(int[] arr) { if (arr == null) { return null; } int[] res = new int[arr.length]; for (int i = 0; i < arr.length; i++) { res[i] = arr[i]; } return res; } // 判斷兩陣列是否相等 public static boolean isEqual(int[] arr1, int[] arr2) { if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { return false; } if (arr1 == null && arr2 == null) { return true; } if (arr1.length != arr2.length) { return false; } for (int i = 0; i < arr1.length; i++) { if (arr1[i] != arr2[i]) { return false; } } return true; } // 列印陣列 public static void printArray(int[] arr) { if (arr == null) { return; } for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } // 用系統提供的的sort函式執行結果與自己寫的氣泡排序執行結果進行比較,若相等,返回nice public static void main(String[] args) { int testTime = 500000; int maxSize = 100; int maxValue = 100; boolean succeed = true; for (int i = 0; i < testTime; i++) { int[] arr1 = generateRandomArray(maxSize, maxValue); int[] arr2 = copyArray(arr1); bubbleSort(arr1); comparator(arr2); if (!isEqual(arr1, arr2)) { succeed = false; break; } } System.out.println(succeed ? "Nice!" : "Fucking fucked!"); // 列印其中一組。 int[] arr = generateRandomArray(maxSize, maxValue); printArray(arr); bubbleSort(arr); printArray(arr); } }