氣泡排序的最優演算法
阿新 • • 發佈:2019-01-29
氣泡排序是一種交換類排序的演算法,比較常用,這裡討論下演算法的優化。
// 待排序陣列,升序排序
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 + "次");
}
執行結果: