氣泡排序的優化方案
阿新 • • 發佈:2018-11-07
為什麼要突然要講這個呢,因為之前被朋友問到的,剛開始一臉矇蔽,寫了那某多次氣泡排序,自己也沒想太多優化的問題。
所以Google了一下,其實優化的核心思想就是減少比較的次數,非常簡單。
普通的氣泡排序如下:
static void BubbleSort1(int[] arr, int size) { int i = 0, j = 0; int count = 0; for (i = 0; i < size - 1; i++)//一共要排序size-1次 { for (j = 0; j < size - 1 - i; j++)//選出該趟排序的最大值往後移動 { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } count++; } } //count計算比較的次數 System.out.println("bubble 1 = "+count); }
氣泡排序的最壞時間複雜度為O(n^2)。
優化方案1:優化外層迴圈
//氣泡排序優化1 static void BubbleSort2(int[] arr, int size) { int i = 0, j = 0; int count = 0; for (i = 0; i < size - 1; i++)//一共要排序size-1次 { //每次遍歷標誌位都要先置為0,才能判斷後面的元素是否發生了交換 int flag = 0; for (j = 0; j < size - 1 - i; j++)//選出該趟排序的最大值往後移動 { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = 1;//只要有發生了交換,flag就置為1 } count++; } //判斷標誌位是否為0,如果為0,說明後面的元素已經有序,就直接return if (flag == 0) { break; } } System.out.println("bubble 2 = "+count); }
在上面給出的演算法中,引入一個標籤flag,在每趟排序開始前,先將其置為0。若排序過程中發生了交換,則將其置為1。各趟排 序結束時檢查flag,若未曾發生過交換,說明此時的陣列已經是有序的了,則終止演算法,不再進行多餘的相鄰比較。
優化方案2:優化內層迴圈
//氣泡排序優化2 static void BubbleSort3(int[] arr, int size) { int i = 0, j = 0; int k = size - 1,pos = 0;//pos變數用來標記迴圈裡最後一次交換的位置 int count = 0; for (i = 0; i < size - 1; i++)//一共要排序size-1次 { //每次遍歷標誌位都要先置為0,才能判斷後面的元素是否發生了交換 int flag = 0; for (j = 0; j <k; j++)//選出該趟排序的最大值往後移動 { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = 1;//只要有發生了交換,flag就置為1 pos = j;//迴圈裡最後一次交換的位置 j賦給pos } count++; } k = pos; //判斷標誌位是否為0,如果為0,說明後面的元素已經有序,就直接return if (flag == 0) { break; } } System.out.println("bubble 3 = "+count); }
方案2 在 方案1的基礎下又進行了一次優化,方案2的演算法在每趟掃描中,記住最後一次交換髮生的位置lastExchange,(該位置之後的相鄰記錄均已有序)。下一趟排序開始時,R[1..lastExchange-1]是無序區,R[lastExchange..n]是有序區。這樣,一趟排序可能使當前無序區擴充多個記錄,因此記住最後一次交換髮生的位置lastExchange,從而減少排序的趟數。
總結
演算法複雜度比較:方案2 <= 方案1 <= 普通冒泡