1. 程式人生 > >氣泡排序的最優演算法

氣泡排序的最優演算法

氣泡排序是一種交換類排序的演算法,比較常用,這裡討論下演算法的優化。

 //  待排序陣列,升序排序
 int[] arr = {2,6,4,5,3,7,8,11,14}; 

演算法一

這是最簡單也是最容易的寫法,兩層for迴圈,前後比較,大的交換。若陣列長度為n,總共需要比較n*(n-1)/2次。

public static void bubbleSort1(int[] arr) {
        int count = 0;

        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0
; j < arr.length-i-1; j++) { // 前面比後面大,則進行交換 if(arr[j] > arr[j+1]) { arr[j] = arr[j] + arr[j+1]; arr[j+1] = arr[j] - arr[j+1]; arr[j] = arr[j] - arr[j+1]; } count++; } } System.out
.println("比較" + count + "次"); }

執行結果:
這裡寫圖片描述

演算法二

這裡我們根據演算法一中的思路進行下優化,我們注意到上述arr陣列中後四個數7,8,11,14是已排好序的,我們遍歷比較一次就已經沒有必要再去比較了。因此,在排序過程中,我們可能會重複的去多次比較已排好的序列,這樣就造成了冗餘,當資料量大時,會明顯的耗時。
為解決這個問題,我們在這裡新增一個lastIndex索引,用於標記最後一次交換的位置(注意,這裡是交換不是比較),當交換到arr陣列中7之前,也就是下標為4的時候,不再交換,說明後面的已經有序,下次就直接比較到下標為4的位置,後面的不再比較。
另外,如果是倒序排正序,則沒有優化,比較n*(n-1)/2次。

int[] arr = {-1,2,6,4,5,3,7,8,11,14};
public static void bubbleSort2(int[] arr) {
    int i = arr.length-1;
    int count = 0; // 計數
    while(i>1){
        int lastChange = 1; // 記錄最後一次交換位置
        for (int j = 1; j < i; j++) {
            // 前面比後面大,則進行交換
            if(arr[j]>arr[j+1]){
                arr[j] = arr[j] + arr[j+1];
                arr[j+1] = arr[j] - arr[j+1];
                arr[j] = arr[j] - arr[j+1];
                lastChange = j; // 每交換一次更新一次
            }
            count++;
        }
        i = lastChange;
    }
    System.out.println(count);
}

執行結果:
這裡寫圖片描述
很明顯,比較的次數減少了。
注意:存放資料時從陣列下標為1的位置開始放,該演算法不比較下標為0位置的數。另外,對於不同的陣列,排序比較的次數可能會不同,比較次數一定滿足count<=n*(n-1)/2。

演算法三

最後,這裡再提供一種一層for迴圈實現的氣泡排序。原理就是在for迴圈內部動態改變下標 i 的值,讓其反覆迴圈。並沒有什麼效能上的優化,只是換了一種形式而已。

public static void bubbleSort3(int[] arr) {
        int count = 0;
        int t = arr.length-1;
        for (int i = 0; i < t; i++) {
            // 前面比後面大,則進行交換
            if(arr[i] > arr[i+1]) {
                arr[i] = arr[i] + arr[i+1];
                arr[i+1] = arr[i] - arr[i+1];
                arr[i] = arr[i] - arr[i+1];
            }
            count++;

            if(i == t-1){
                i = -1;
                t--;
            }
        }

        System.out.println("比較" + count + "次");
    }

執行結果:
這裡寫圖片描述