排序算法-冒泡排序

假定需要對序列{9,3,8,5,2,7,4,1,6}做排序,最先想到的就是冒泡排序法,因爲最簡單。下面的排序算法使用Java來寫。

最簡單的冒泡排序

最簡單的思路就是每一個關鍵字都和後面的關鍵字進行比較,如果大則交換,這樣第一個位置的關鍵字在一次循環後一定變爲最小值。
代碼如下:

    public static void main(String[] args) {
        Integer[] arrs = {9, 3, 8, 5, 2, 7, 4, 1, 6};
        sort(arrs);
        System.out.println(Arrays.toString(arrs));
    }

    public static void sort(Integer[] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) { // 如果前一個元素比後一個元素大,則替換位置
                    Integer temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }

在這裏插入圖片描述
當i=0 j=1時9比3大,所以替換位置,把3放到第1的位置,然後繼續比較,8、5都比3大,直到下標爲4的2沒有3大,替換位置把2放到第1的位置,同理,最終第一個位置數值爲1,然後按照該方式繼續取第二位的最小數值。

這種方法有個缺陷,可以看到進行到第4個位置進行比較的時候,3和2替換,反而從原本2的位置排到了後面去了。

純正的冒泡排序

    public static void main(String[] args) {
        Integer[] arrs = {9, 3, 8, 5, 2, 7, 4, 1, 6};
        sort(arrs);
        System.out.println(Arrays.toString(arrs));
    }

    public static void sort(Integer[] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = arr.length - 1; j > i; j--) {
                if (arr[j - 1] > arr[j]) { // 如果前一個元素比後一個元素大,則替換位置
                    Integer temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }

該算法從序列的末尾開始,兩兩元素進行比較大小,前者比後者大,則替換位置,直到最後將最小的元素放到第一的位置。如下圖:
在這裏插入圖片描述
進行第二輪比較時,我們可以看到如下的效果,數字4在第一次和第二次的比較時,上升了一個位子,最後數字2上升到了第二的位置。也就是說,除了第2的關鍵字放到了第二的位置,還將第4的關鍵字提升了一個位置。
在這裏插入圖片描述

改進的冒泡排序

如果待排序的序列爲{2,1,3,4,5,6,7,8,9},除了把2和1交換之外,其他的數字都是正常順序的。那也就是說按照上面的算法,還是會進行i=2到8次的循環執行,儘管沒有交換數據。
在這裏插入圖片描述
稍微改進下代碼,增加一個flag變量來標記是否需要繼續執行循環:

    public static void main(String[] args) {
        Integer[] arrs = {2, 1, 3, 4, 5, 6, 7, 8, 9};
        sort(arrs);
        System.out.println(Arrays.toString(arrs));
    }

    public static void sort(Integer[] arr) {
        boolean flag = true; //flag標記是否需要繼續循環
        for (int i = 0; i < arr.length && flag; i++) {//每一輪循環進行flag判斷
            flag = false;
            for (int j = arr.length - 1; j > i; j--) {
                if (arr[j - 1] > arr[j]) { // 如果前一個元素比後一個元素大,則替換位置
                    Integer temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                    flag = true; //有數據交換則將flag置爲true
                }
            }
        }
    }

時間複雜度

按照改進之後的算法,當最好情況序列本身就是正常排序的,需要比較n-1次,沒有數據交換。時間複雜度爲O(n)。最壞的情況是序列爲逆序排列,那麼比較次數爲n(n1)2\frac{n(n-1)}{2}次,所以時間複雜度爲O(n2n^{2})。

發佈了69 篇原創文章 · 獲贊 86 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章