比較相鄰兩個元素,如果第乙個比第二個大,則交換兩個元素;
從左到右依次比較,直到最大數字於陣列尾端;
重複n-1次1、2步驟,(除去已經排序的最大數)依次將第二,第三。。。第n-1大的數排好位置。
原序列396
5827
4第1趟36
5827
49
第2趟356
2748
9第3趟35
264789
第4趟325
4678
9第5趟23
4567
89第6趟2
3456
789第7趟
2345
6789
如**所示,每一趟都將當前亂序序列中最大的數移到尾端。【小夥伴們從**中看出基本氣泡排序可以優化的地方了嗎?】下面先來基本實現**。
從**中,相信小夥伴已經看出,在第5趟其實已經排好序了,但基本的氣泡排序演算法還會進行第7趟比較,這其實只是進行沒必要的比較,而不會進行元素的交換。(第6趟還是必須要走的,下面會說明)
時間複雜度:由於內外迴圈都發生n次迭代,所以時間複雜度為o(n^2)。並且這個界是精確的。思考最壞的情況,輸入乙個逆序的陣列,則比較次數為:
(n-1)+(n-2)+(n-3)+..+2+1 = n*(n-1)/2 = o(n^2)
空間複雜度:只使用了乙個臨時變數,所以為o(1);
是否穩定:穩定排序
我們換個角度看待這個問題。基本冒泡演算法之所以進行了無用的多餘掃瞄,是因為不知道已經排好了序;所以只要我們在第 i 趟(i小於n-1)就知道序列已經排好序,我們就不用進行之後的掃瞄了。
綜上所述,我們可以增加乙個boolean變數,來標識是否已經排好序。優化**如下:
氣泡排序優化普通版:
private
static
super t>> void
bubblesort
(t nums)
t temp = null;
int length = nums.length;
//用於標識是否已經將序列排好序
boolean isordered = false;
for (int i = 0; i < length - 1; i++)
}//如果當前趟都沒有進行元素的交換,證明前面一趟比較已經排好序
//直接跳出迴圈
if (isordered) }}
注意:雖然第5趟已經排好序,但對於程式來說,它並不知道此趟已經排好序,需要進行下一趟掃瞄來確定上一趟是否已經將原序列排好序。所以第6趟是必須要去掃瞄的。
你以為結束了嗎?哈哈哈,還沒有,這只是第一版優化。
讓我們想一想這樣的情況。對於下列序列,前半部分亂序,後半部分有序。
原序列453
2678
9第一趟43
2567
89第二趟324
5678
9第三趟23
4567
89簡述排序過程:
第一趟:發生交換的是5和3,接著是5和2;隨後5與6比較,不需要換位置,相同地,6與7、7與8、8與9都不需要更換位置。所以第一趟結果為:[4,3,2,5,6,7,8,9]。
第二趟:發生交換的是4與3,接著4與2;隨後4與5、5與6,6與7、7與8都不需要更換位置。【8不需要與9比較,因為第一趟已經將最大的數下沉到尾端】。所以第二趟結果為:[3,2,4,5,6,7,8,9]。
第三趟:發生交換的是3與2;隨後3與4,4與5,5與6,6與7都不需要更換位置。所以第三趟結果為:[2,3,4,5,6,7,8,9]。
大家看出什麼了嗎?其實進行了很多無意義的比較,因為這些都不需要更換位置,而很多趟都會重複比較。根據氣泡排序思想,我們知道,有序序列長度,其實跟排序趟數相等,每一趟就是將當前亂序中的最大值下沉到陣列尾端。但其實序列真正有序的序列長度是大於當前排序趟數的。也就是說,只要我們找到了原序列中無序與有序的邊界,就可以避免再去比較有序序列。
其實最後一次交換的位置,就是無序序列與有序序列的邊界。
從例子中看:
第一趟最後一次交換的位置是元素5與2交換的位置,即陣列下標2的位置;
第二趟最後一次交換的位置是元素4與2交換的位置,即陣列下標1的位置;
第三趟最後一次交換的位置是元素3與2交換的位置,即陣列下標0的位置;
所以,只要我們記錄下當前趟最後一次交換的位置,在下一趟只比較到這個位置即可。
氣泡排序優化加強版:
private
static
super t>> void
bubblesort
(t nums)
t temp = null;
int length = nums.length;
boolean isordered = false;
int lastexchangeindex = 0;
//當前趟無序的邊界
int unorderedborder = length - 1;
for (int i = 0; i < length - 1; i++)
}unorderedborder = lastexchangeindex;
if (isordered) }}
其實,還可以進一步優化, 有興趣的可以去看看雞尾酒排序,我們已經很接近了。
氣泡排序可以通過增加boolean標識是否已經排好序來進行優化;還可以記錄下最後一次交換元素的位置來進行優化,防止無意義的比較。氣泡排序是穩定排序,時間複雜度為o(n^2),空間複雜度為o(1)。
氣泡排序以及如何優化氣泡排序
氣泡排序的基本思想是 通過對待排序序列從前往後 從下標較小的元素開始 依次比較相鄰元素的值,若發現逆序則交換,使值較大的元素逐漸從前移向後部,就像水底下的泡泡一樣逐漸向上冒。測試八萬個資料進行排序,使用優化後的 大致需要20秒 如下 public static void bubblesort int...
Python 如何優化氣泡排序
什麼叫氣泡排序法?相信有接觸過演算法的朋友多少都了解氣泡排序法,那麼什麼是氣泡排序法呢?氣泡排序,英文名稱 bubble sort 是一種基礎的交換排序演算法,在日常工作中經常會用到,例如 頁面資料需按時間先後排序,這本質上也是一種氣泡排序法。喝過可樂的朋友都知道,可樂裡面的氣泡會向上浮,這就是氣泡...
氣泡排序 氣泡排序演算法優化
常用的排序演算法主要包括 1 插入排序 直接插入排序 希爾排序 2 交換排序 氣泡排序 快速排序 3 選擇排序 簡單選擇排序 堆排序快速排序 4 歸併排序其中,氣泡排序算是最簡單的一種排序演算法 public class bubble int temp 0 for int i 0 iarr j 1 ...