那些程序猿必會的算法:冒泡排序

冒泡排序
冒泡排序:是一種最基礎的交換排序。冒泡排序就像水冒泡,小(大)的元素經過不斷的交換由水底慢慢的浮到水的頂端。
在這裏插入圖片描述

時間複雜度 空間複雜度
O(n^2) O(1)

====================================================================

代碼實現一:

我們從左邊開始,每次把相鄰的兩個數兩兩做比較,當左側元素大於右側與它相鄰的元素時,則交換它們之間位置,反之,它們之間的位置不發生變化。

public class BubbleSortTest {
    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));
        // 排序
        sort1(array);
        System.out.println("排序後的數組:" + Arrays.toString(array));
    }

    /**
     * 用冒泡排序算法對數組進行排序-基本寫法
     * @param array
     */
    public static void sort1(int[] array) {
    	//array.length-1是因爲最後一輪不需要排序
        for (int i = 0; i < array.length - 1; i++) {
            System.out.println("第" + (i + 1) + "趟");
            //array.length - 1 - i是因爲每一輪都能確定排序好一個數
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    //這樣的交換,不需要創建第三個變量,減少內存開銷
                    array[j + 1] ^= array[j];
                    array[j] ^= array[j + 1];
                    array[j + 1] ^= array[j];
                }
                System.out.println("  第" + (j + 1) + "次:" + Arrays.toString(array));
            }
        }
    }
}

執行結果:

輸入要排序的值,輸入的每個值用逗號隔開:
5,7,3,1,9,14,36,41,57
排序前的數組:[5, 7, 3, 1, 9, 14, 36, 41, 57]
第1趟
  第1次:[5, 7, 3, 1, 9, 14, 36, 41, 57]
  第2次:[5, 3, 7, 1, 9, 14, 36, 41, 57]
  第3次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第4次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第5次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第6次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第7次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第8次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
第2趟
  第1次:[3, 5, 1, 7, 9, 14, 36, 41, 57]
  第2次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第3次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第4次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第5次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第6次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第7次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
第3趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第2次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第3次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第4次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第5次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第6次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
第4趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第2次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第3次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第4次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第5次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
第5趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第2次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第3次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第4次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
第6趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第2次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第3次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
第7趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第2次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
第8趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
排序後的數組:[1, 3, 5, 7, 9, 14, 36, 41, 57]

====================================================================

代碼實現二(繼續優化):

增加一個標記(flag),每次發生交換,就進行標記,如果某次循環完沒有標記,則說明已經完成排序,數組有序,剩下的幾趟排序就不需要再去執行了,可以提前結束排序。

public class BubbleSortTest {
    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));
        //排序
        sort2(array);
        System.out.println("排序後的數組:" + Arrays.toString(array));
    }

    /**
     * 用冒泡排序算法對數組進行排序--優化處理
     * @param array
     */
    public static void sort2(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++) {
                //如果前一位比後一位大,則交換位置
                if (array[j] > array[j + 1]) {
                    //這樣的交換,不需要創建第三個變量,減少內存開銷
                    array[j + 1] ^= array[j];
                    array[j] ^= array[j + 1];
                    array[j + 1] ^= array[j];
                    // 有元素交換,所以不是有序,標記變爲false
                    flag = false;
                }
                System.out.println("  第" + (j + 1) + "次:" + Arrays.toString(array));
            }
            // 說明上面內層for循環中,沒有交換任何元素,直接跳出外層循環
            if (flag) {
                break;
            }
        }
    }
}

運行結果:

輸入要排序的值,輸入的每個值用逗號隔開:
5,7,3,1,9,14,36,41,57
排序前的數組:[5, 7, 3, 1, 9, 14, 36, 41, 57]
第1趟
  第1次:[5, 7, 3, 1, 9, 14, 36, 41, 57]
  第2次:[5, 3, 7, 1, 9, 14, 36, 41, 57]
  第3次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第4次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第5次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第6次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第7次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第8次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
第2趟
  第1次:[3, 5, 1, 7, 9, 14, 36, 41, 57]
  第2次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第3次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第4次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第5次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第6次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
  第7次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
第3趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第2次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第3次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第4次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第5次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第6次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
第4趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第2次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第3次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第4次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
  第5次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
排序後的數組:[1, 3, 5, 7, 9, 14, 36, 41, 57]

====================================================================

代碼實現三(繼續優化):

在上一個基礎上增加一個arrBoundary 是無序數組的邊界,剛開始默認指向數組的最後一個元素,每次比較比到這裏爲止,不需要進行後面的排序了。

public class BubbleSortTest {
    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));
        // 排序
        sort3(array);
        System.out.println("排序後的數組:" + Arrays.toString(array));
    }

    /**
     * 用冒泡排序算法對數組進行排序--繼續優化處理
     *
     * @param array
     */
    public static void sort3(int[] array) {
        //最後一次交換的下標
        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;
            //j < arrBoundary無序數組的邊界,每次比較比到止
            for (int j = 0; j < arrBoundary; j++) {
                //如果前一位比後一位大,則交換位置
                if (array[j] > array[j + 1]) {
                    //這樣的交換,不需要創建第三個變量,減少內存開銷
                    array[j + 1] ^= array[j];
                    array[j] ^= array[j + 1];
                    array[j + 1] ^= array[j];
                    //有元素交換,所以不是有序,標記變爲false
                    flag = false;
                    //最後一次交換元素的位置
                    lastSwapIndex = j;
                }
                System.out.println("  第" + (j + 1) + "次:" + Arrays.toString(array));
            }
            //把最後一次交換元素的位置賦值給無序數組的邊界
            arrBoundary = lastSwapIndex;
            //說明上面內層for循環中,沒有交換任何元素,直接跳出外層循環
            if (flag || lastSwapIndex == 0) {
                break;
            }
        }
    }
}

運行結果:

輸入要排序的值,輸入的每個值用逗號隔開:
5,7,3,1,9,14,36,41,57
排序前的數組:[5, 7, 3, 1, 9, 14, 36, 41, 57]
第1趟
  第1次:[5, 7, 3, 1, 9, 14, 36, 41, 57]
  第2次:[5, 3, 7, 1, 9, 14, 36, 41, 57]
  第3次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第4次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第5次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第6次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第7次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
  第8次:[5, 3, 1, 7, 9, 14, 36, 41, 57]
第2趟
  第1次:[3, 5, 1, 7, 9, 14, 36, 41, 57]
  第2次:[3, 1, 5, 7, 9, 14, 36, 41, 57]
第3趟
  第1次:[1, 3, 5, 7, 9, 14, 36, 41, 57]
排序後的數組:[1, 3, 5, 7, 9, 14, 36, 41, 57]

……
感謝您的閱讀!
所以如有紕漏或者建議,還請讀者朋友們在評論區不吝指出!

個人網站…知識是一種寶貴的資源和財富,益發掘,更益分享…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章