算法分析:什麼是冒泡排序?

2011年,C語言老師給咱們講冒泡排序。面試

2014年,聽同窗提及他面試時和麪試官提起冒泡排序。算法

2015年,大學本科剛畢業,開始找工做,我還記得我在筆記中寫了冒泡排序的代碼,結果還真的被問到了。架構

2019年,公司首席架構師跟我提到冒泡排序。spa

 

什麼是冒泡排序呢?3d

冒泡排序,Bubble Sort,經過依次來比較相鄰兩個元素的大小,在每一次的比較的過程當中,兩個元素,經過交換來達到有序的目的。code

  • 若是一組無序的數列想要從小到大排序,那麼兩個元素比較,經過交換來實現,左邊的元素要比右邊的元素要小。
  • 若是一組無序的數列想要從大到小排序,那麼兩個元素比較,經過交換來實現,左邊的元素要比右邊的元素要大。

就像碳酸飲料中的氣泡同樣,從底部一直冒泡到頂部。blog

 

我想經過一組數據來闡述冒泡排序的過程。排序

  • 準備一組無序的數列,從小到大依次排序。

  • 開始排序開始。因爲6>3,所以兩個元素交換。

 

  • 因爲6>2,所以兩個元素交換。

  • 因爲6>1,所以兩個元素交換。

  • 因爲6<8,所以兩個元素不交換。
  • 因爲8<9,所以兩個元素不交換。
  • 因爲9>7,所以兩個元素交換。

  • 因爲9>5,所以兩個元素交換。

  • 第一輪排序結束。此時,元素9處於有序區域。

  • 第二輪排序開始。因爲3>2。所以兩個元素交換。

  • 因爲3>1。所以兩個元素交換。

  • 因爲3<6。所以兩個元素不交換。
  • 因爲6<8。所以兩個元素不交換。
  • 因爲8>7。所以兩個元素交換。

  • 因爲8>5。所以兩個元素交換。

  • 因爲8<9。所以兩個元素不交換。
  • 第二輪排序結束。此時,元素8和9處於有序區域。

  • 第三輪排序開始。因爲2>1。所以兩個元素交換。

 

  • 因爲2<3。所以兩個元素不交換。
  • 因爲3<6。所以兩個元素不交換。
  • 因爲6<7。所以兩個元素不交換。
  • 因爲7>5,所以兩個元素交換。

  • 第三輪排序結束此時,元素7,8和9處於有序區域。

  • 第四輪排序開始。因爲1<2。所以兩個元素不交換。
  • 因爲2<3。所以兩個元素不交換。
  • 因爲3<6。所以兩個元素不交換。
  • 因爲6>5。所以兩個元素交換。

  • 第四輪排序結束。此時,元素6,7,8,9在有序區域內。

 

  • 第五輪排序開始。因爲1<2。所以兩個元素不交換。
  • 因爲2<3。所以兩個元素不交換。
  • 因爲3<5。所以兩個元素不交換。
  • 第五輪排序結束。此時,元素5,6,7,8,9在有序區域內。
  • 第六輪排序開始。因爲1<2。所以兩個元素不交換。
  • 因爲2<3。所以兩個元素不交換。
  • 輪排序結束。此時,元素3,5,6,7,8,9在有序區域內。
  • 第七輪排序開始。因爲1<2。所以兩個元素不交換。
  • 輪排序結束。此時,元素2,3,5,6,7,8,9在有序區域內。
  • 第八輪排序開始
  • 輪排序結束。此時,元素1,2,3,5,6,7,8,9在有序區域內。可見最後一輪沒有必要存在。

 

最後咱們使用Java代碼來展現上述的算法。ast

 1 private static void sort() {  2 
 3         Integer[] data = {6,3,2,1,8,9,7,5};  4 
 5         for(int i=0; i<data.length-1; i++) {  6 
 7             for(int j=0; j<data.length-i-1; j++) {  8 
 9                 if(data[j] > data[j+1]) { 10                     int k = data[j]; 11                     data[j] = data[j+1]; 12                     data[j+1] = k; 13  } 14 
15  } 16  } 17 
18     }

從上述的代碼以及流程圖中。大體的步驟以下:class

  1. 定義一組無序數列。
  2. 第一層循環。第一層循環的次數是(元素個數-1)
  3. 第二層循環。第二層循環的次數是無序區域內,元素1和元素2,元素2和元素3...依次兩兩比較。
  4. 兩個元素比較,根據規則確認元素是否須要交換。
  5. 繼續第二步。直到循環的次數 = (元素個數-1),結束循環,輸出有序數列,結束。

從以上的現象來看,咱們得出結論和思考:

  • 排序的輪數等於元素的個數-1。是否能夠較少輪數,上述的例子中實際上在完成第四輪之後已是一組有序的數列。從上述代碼來看,第5行控制的是輪數,而第7行是每一輪中無序區域中元素的兩兩比較。從本質上來講,咱們須要在發現沒有元素交換的狀況下,就可以說明已經有序,咱們須要儘早在21行結束。代碼以下所示:
 1 private static void sort() {  2 
 3         Integer[] data = {6,3,2,1,8,9,7,5};  4 
 5         for(int i=0; i<data.length-1; i++) {  6 
 7             boolean isSorted = true;  8 
 9             for(int j=0; j<data.length-i-1; j++) { 10 
11                 if(data[j] > data[j+1]) { 12                     int k = data[j]; 13                     data[j] = data[j+1]; 14                     data[j+1] = k; 15 
16                     isSorted = false; 17  } 18  } 19 
20             if(isSorted) { 21                 break; 22  } 23  } 24 
25

從上述的代碼和流程圖中,若是在第一層的循環中第二次始終沒有元素交換,代表數列已經有序,直接輸出

  • 完成每一輪,有序區域的元素個數增長1。是否能夠衝破每一次有序區域只能增長1的僵局?咱們採起在一個大的輪詢中,記錄最後交換的元素的下標,把這個下標做爲無序區域的邊界,用來最大提升有序區域元素數量增長的加速度。
 1 private static void sort() {  2 
 3         Integer[] data = {6,3,2,1,8,9,7,5};  4 
 5         //最後交換的元素的下標
 6         int lastIndexOfSwap = 0;  7         //無序數列邊界元素的下標
 8         int borderIndexOfUnsort = data.length - 1;  9 
10         for(int i=0; i<data.length-1; i++) { 11 
12             boolean isSorted = true; 13 
14             for(int j=0; j<borderIndexOfUnsort; j++) { 15 
16                 if(data[j] > data[j+1]) { 17                     int k = data[j]; 18                     data[j] = data[j+1]; 19                     data[j+1] = k; 20 
21                     isSorted = false; 22 
23                     lastIndexOfSwap = j; 24  } 25  } 26 
27             borderIndexOfUnsort = lastIndexOfSwap; 28 
29             if(isSorted) { 30                 break; 31  } 32 
33  } 34 
35     }

冒泡排序是最簡單的一種排序算法,3個版本演進,也許並無提升多大的效能,更多應該是對於算法的思惟。

相關文章
相關標籤/搜索