好程式設計師Java學習路線分享氣泡排序及最佳化
好程式設計師Java學習路線分享氣泡排序及最佳化,氣泡排序是一定典型的交換排序,如排序規則是升序,有如下數列:
A[0] A[1] A[2] A[3] ...... A[n]
將A[0]和A[1]比較,如果A[0]>A[1] ,則交換兩個元素的位置,否則不變, 再繼續比較A[1]和A[2],直到A[n-1]和A[n]。即比較相鄰的兩個元素,如果前一個大,就交換(否則不交換),再繼續比較後面的元素,每一輪比較之後,最大的元素會移動到最後(完成一輪冒泡);再開始第二輪冒泡,本次會選出第二大的元素。重複冒泡的過程,直到沒有相鄰的元素需要交換,則排序完成,像碳酸飲料中的氣泡,故而稱為氣泡排序。
簡化過程,設定一個簡單的陣列,在程式設計中,元素的索引從0開始:
[5, 3, 1, 4, 2]
```
int[] nums = {5, 3, 1, 4, 2};
//要比較n次,n是陣列中數字的個數
for (int i = 0; i < nums.length; i++) {
//比較j和j+1位置的元素,每比較完一次,最大的元素會移動到末尾
for (int j = 0; j < nums.length - 1; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j + 1];
nums[j + 1] = nums[j];
nums[j] = temp;
}
}
}
```
第一輪比較,經過這一輪比較,最大的元素在末尾
[<font color="red">5, 3</font>, 1, 4, 2] 比較第0和1個元素 ,**交換** [<font color="red">3, 5</font>, 1, 4, 2]<br/>
[3,<font color="red"> 5, 1</font>, 4, 2] 比較第1和2個元素 ,**交換** [3, <font color="red">1, 5</font>, 4, 2]<br/>
[3, 1, <font color="red">5, 4</font>, 2] 比較第2和3個元素 ,**交換** [3,1, <font color="red"> 4, 5</font>, 2]<br/>
[3, 1, 4, <font color="red">5, 2</font>] 比較第3和4個元素 ,**交換** [3, 1, 4, <font color="red">2, 5</font>] 最大的元素在末尾<br/>
第二輪比較,經過這輪比較,最大的兩個元素在末尾
[<font color="red">3, 1</font>, 4, 2, 5] 比較第0和1個元素 ,**交換** [<font color="red">1, 3</font>, 4, 2, 5]<br/>
[1, <font color="red">3, 4</font>, 2, 5] 比較第1和2個元素 ,不動 [1, <font color="red">3, 4</font>, 2, 5]<br/>
[1, 3, <font color="red">4, 2</font>, 5] 比較第2和3個元素 ,**交換** [1, 3, <font color="red">2, 4</font>, 5]<br/>
[1, 3, 2, <font color="red">4, 5</font>] 比較第3和4個元素 ,不動 [1, 3, 2, <font color="red">4, 5</font>] 這次比較是多餘的,因為第1輪過後,最大的元素在末尾<br/>
第三輪比較,經過這輪比較,最大的三個元素在末尾
[<font color="red">1, 3</font>, 2, 4, 5] 比較第0和1個元素 ,不動 [<font color="red">1, 3</font>, 2, 4, 5]<br/>
[1, <font color="red">3, 2</font>, 4, 5] 比較第1和2個元素 ,**交換** [1, <font color="red">2, 3</font>, 4, 5]<br/>
[1, 2,<font color="red"> 3, 4</font>, 5] 比較第2和3個元素 ,不動 [1, 2, <font color="red">3, 4</font>, 5] 這次比較多餘的<br/>
[1, 2, 3, <font color="red">4, 5</font>] 比較第3和4個元素 ,不動 [1, 2, 3, <font color="red">4, 5</font>] 這次比較是多餘的<br/>
第四輪比較,經過這輪比較,最大的四個元素在末尾
[<font color="red">1, 2</font>, 3, 4, 5] 比較第0和1個元素 ,不動 [<font color="red">1, 2</font>, 3, 4, 5]<br/>
[1, <font color="red">2, 3</font>, 4, 5] 比較第1和2個元素 ,不動 [1, <font color="red">2, 3</font>, 4, 5] 這次比較是多餘的<br/>
[1, 2,<font color="red"> 3, 4</font>, 5] 比較第2和3個元素 ,不動 [1, 2, <font color="red">3, 4</font>, 5] 這次比較是多餘的<br/>
[1, 2, 3, <font color="red">4, 5</font>] 比較第3和4個元素 ,不動 [1, 2, 3, <font color="red">4, 5</font>] 這次比較是多餘的<br/>
第五輪比較,經過這輪比較,排序完成
[<font color="red">1, 2</font>, 3, 4, 5] 比較第0和1個元素 ,不動 [<font color="red">1, 2</font>, 3, 4, 5] 這次比較是多餘的<br/>
[1, <font color="red">2, 3</font>, 4, 5] 比較第1和2個元素 ,不動 [1, <font color="red">2, 3</font>, 4, 5] 這次比較是多餘的<br/>
[1, 2, <font color="red">3, 4</font>, 5] 比較第2和3個元素 ,不動 [1, 2, <font color="red">3, 4</font>, 5] 這次比較是多餘的<br/>
[1, 2, 3, <font color="red">4, 5</font>] 比較第3和4個元素 ,不動 [1, 2, 3, <font color="red">4, 5</font>] 這次比較是多餘的<br/>
可以看到氣泡排序每次都從頭比較,比較到末尾,但實際
第一輪比較後,最後1個數是最大的,下一輪不需要參與比較
第二輪比較後,最後2個數是最大的,下一輪不需要參與比較
第三輪比較後,最後3個數是最大的...
所以第n輪比較的時候,可以排除掉末尾已經排序好的元素,即末尾n-1個元素
```java
int[] nums = {5, 3, 1, 4, 2};
//要比較n次,n是陣列中數字的個數
for (int i = 0; i < nums.length; i++) {
//比較j和j+1位置的元素,每比較完一次,最大的元素會移動到末尾
//最後i個元素不參與本次比較
for (int j = 0; j < nums.length - 1 - i; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j + 1];
nums[j + 1] = nums[j];
nums[j] = temp;
}
}
}
```
執行結果:
第一輪比較,經過這一輪比較,最大的元素在末尾
[<font color="red">5, 3</font>, 1, 4, 2] 比較第0和1個元素 ,**交換** [<font color="red">3, 5</font>, 1, 4, 2]<br/>
[3,<font color="red"> 5, 1</font>, 4, 2] 比較第1和2個元素 ,**交換** [3, <font color="red">1, 5</font>, 4, 2]<br/>
[3, 1, <font color="red">5, 4</font>, 2] 比較第2和3個元素 ,**交換** [3,1, <font color="red"> 4, 5</font>, 2]<br/>
[3, 1, 4, <font color="red">5, 2</font>] 比較第3和4個元素 ,**交換** [3, 1, 4, <font color="red">2, 5</font>] 最大的元素在末尾<br/>
第二輪比較,經過這輪比較,最大的兩個元素在末尾
[<font color="red">3, 1</font>, 4, 2, 5] 比較第0和1個元素 ,**交換** [<font color="red">1, 3</font>, 4, 2, 5]<br/>
[1, <font color="red">3, 4</font>, 2, 5] 比較第1和2個元素 ,不動 [1, <font color="red">3, 4</font>, 2, 5]<br/>
[1, 3, <font color="red">4, 2</font>, 5] 比較第2和3個元素 ,**交換** [1, 3, <font color="red">2, 4</font>, 5]<br/>
第三輪比較,經過這輪比較,最大的三個元素在末尾
[<font color="red">1, 3</font>, 2, 4, 5] 比較第0和1個元素 ,不動 [<font color="red">1, 3</font>, 2, 4, 5]<br/>
[1, <font color="red">3, 2</font>, 4, 5] 比較第1和2個元素 ,**交換** [1, <font color="red">2, 3</font>, 4, 5]<br/>
第四輪比較,經過這輪比較,最大的四個元素在末尾
[<font color="red">1, 2</font>, 3, 4, 5] 比較第0和1個元素 ,不動 [<font color="red">1, 2</font>, 3, 4, 5]<br/>
上面的演算法,可以減少重複比較的次數,比較的次數是固定的。但如果本來陣列中的元素就相對有序,則會出現如下狀況:
初始陣列是:[3, 1, 2, 4, 5]
第一輪
[<font color="red">3, 1</font>, 2, 4, 5]比較第0和1個元素,交換[<font color="red">1, 3</font>, 2, 4, 5]<br/>
[1,<font color="red"> 3, 2</font>, 4, 5]比較第1和2個元素,交換[1, <font color="red">2, 3</font>, 4, 5]<br/>
[1, <font color="red">2, 3</font>, 4, 5]比較第2和3個元素,不動[1, 2, <font color="red">3, 4</font>, 5]<br/>
[1, 2, <font color="red">3, 4</font>, 5]比較第3和4個元素,不動[1, 2, 3, <font color="red">4, 5</font>]<br/>
第二輪
[<font color="red">1, 2</font>, 3, 4, 5]比較第0和1個元素,不動[<font color="red">1, 2</font>, 3, 4, 5]<br/>
[1, <font color="red">2, 3</font>, 4, 5]比較第1和2個元素,不動[1, <font color="red">2, 3</font>, 4, 5]<br/>
[1, 2, <font color="red">3, 4</font>, 5]比較第2和3個元素,不動[1, 2, <font color="red">3, 4</font>, 5]<br/>
第三輪
[<font color="red">1, 2</font>, 3, 4, 5]比較第0和1個元素,不動[<font color="red">1, 2</font>, 3, 4, 5]<br/>
[1,<font color="red">2, 3</font>, 4, 5]比較第1和2個元素,不動[1, <font color="red">2, 3</font>, 4, 5]<br/>
第四輪
[<font color="red">1, 2</font>, 3, 4, 5]比較第0和1個元素,不動[1, 2, <font color="red">3, 4</font>, 5]<br/>
實際上陣列中的元素,開始的時候只有數字3的位置需要移動,其它元素相對都是有序的。當3移動完成後,其它的元素不需要一定。所以在第二輪發現沒有任何元素交換之後,就表示排序已經完成,第三輪和第四輪是多餘的。
對於氣泡排序的最佳化,如果某一輪比較中沒有發生任何交換,則代表排序已經完成,不需要再進行排序了:
```java
int[] nums = {3, 1, 2, 4, 5};
boolean flag;//是否交換的標誌
//要比較n次,n是陣列中數字的個數
for (int i = 0; i < nums.length; i++) {
// 每次遍歷標誌位都要先置為false,才能判斷後面的元素是否發生了交換
flag = false;
//比較j和j+1位置的元素,每比較完一次,最大的元素會移動到末尾
//最後i個元素不參與本次比較
for (int j = 0; j < nums.length - 1 - i; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j + 1];
nums[j + 1] = nums[j];
nums[j] = temp;
flag = true; //表示本輪發生了交換
}
}
// 如果為false,代表本輪沒有交換,元素已經有序
if(!flag) break;
}
}
```
初始陣列是:[3, 1, 2, 4, 5]
第一輪
[<font color="red">3, 1</font>, 2, 4, 5]比較第0和1個元素,交換[<font color="red">1, 3</font>, 2, 4, 5]<br/>
[1,<font color="red"> 3, 2</font>, 4, 5]比較第1和2個元素,交換[1, <font color="red">2, 3</font>, 4, 5]<br/>
[1, <font color="red">2, 3</font>, 4, 5]比較第2和3個元素,不動[1, 2, <font color="red">3, 4</font>, 5]<br/>
[1, 2, <font color="red">3, 4</font>, 5]比較第3和4個元素,不動[1, 2, 3, <font color="red">4, 5</font>]<br/>
第二輪
[<font color="red">1, 2</font>, 3, 4, 5]比較第0和1個元素,不動[<font color="red">1, 2</font>, 3, 4, 5]<br/>
[1, <font color="red">2, 3</font>, 4, 5]比較第1和2個元素,不動[1, <font color="red">2, 3</font>, 4, 5]<br/>
[1, 2, <font color="red">3, 4</font>, 5]比較第2和3個元素,不動[1, 2, <font color="red">3, 4</font>, 5]<br/>
在上面的排序中,3是最後一個移動的元素。3之後的元素都是有序的。所以只要比較3之前的元素即可。最後一次發生交換的元素,它後面的元素都是有序的,不需要再參與比較
```java
int[] nums = {3, 1, 2, 4, 5};
boolean flag;//是否交換的標誌
int lastExchangeIndex =0;//最後一次交換的位置
int sortBorder = nums.length - 1;
//要比較n次,n是陣列中數字的個數
for (int i = 0; i < nums.length; i++) {
// 每次遍歷標誌位都要先置為false,才能判斷後面的元素是否發生了交換
flag = false;
//比較j和j+1位置的元素,每比較完一次,最大的元素會移動到末尾
//最後i個元素不參與本次比較
for (int j = 0; j < sortBorder ; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j + 1];
nums[j + 1] = nums[j];
nums[j] = temp;
flag = true; //表示本輪發生了交換
lastExchangeIndex =j;//記錄最後一次發生交換的位置
}
}
// 如果為false,代表本輪沒有交換,元素已經有序
sortBorder = lastExchangeIndex;
if(!flag) break;
}
```
執行結果:
第一輪
[<font color="red">3, 1</font>, 2, 4, 5]比較第0和1個元素,交換[<font color="red">1, 3</font>, 2, 4, 5]<br/>
[1,<font color="red"> 3, 2</font>, 4, 5]比較第1和2個元素,交換[1, <font color="red">2, 3</font>, 4, 5]<br/>
[1, <font color="red">2, 3</font>, 4, 5]比較第2和3個元素,不動[1, 2, <font color="red">3, 4</font>, 5]<br/>
[1, 2, <font color="red">3, 4</font>, 5]比較第3和4個元素,不動[1, 2, 3, <font color="red">4, 5</font>]<br/>
第二輪
[<font color="red">1, 2</font>, 3, 4, 5]比較第0和1個元素,不動[<font color="red">1, 2</font>, 3, 4, 5]
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2652969/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 好程式設計師Java學習路線分享SpringCloud程式設計師JavaSpringGCCloud
- 好程式設計師Java學習路線分享5分鐘瞭解計數排序程式設計師Java排序
- 好程式設計師Java學習路線分享實戰Tomcat效能最佳化程式設計師JavaTomcat
- 好程式設計師Java學習路線分享mybatis對映程式設計師JavaMyBatis
- 好程式設計師Java學習路線分享MyBatis之執行緒最佳化程式設計師JavaMyBatis執行緒
- 好程式設計師Java學習路線分享5分鐘瞭解基數排序程式設計師Java排序
- 好程式設計師Java學習路線分享Java框架怎麼搭建程式設計師Java框架
- 好程式設計師Java學習路線分享Java-String常用方法程式設計師Java
- 好程式設計師Java學習路線分享原生Ajax的使用程式設計師Java
- 好程式設計師Java學習路線分享finalize()方法詳解程式設計師Java
- 好程式設計師Java學習路線分享JVM相關概念程式設計師JavaJVM
- 好程式設計師Java學習路線分享MyBatis之Spring整合程式設計師JavaMyBatisSpring
- 好程式設計師Java學習路線分享Redis快速入門程式設計師JavaRedis
- 好程式設計師Java學習路線分享MyBatis之基本使用程式設計師JavaMyBatis
- 好程式設計師Java學習路線分享maven是什麼程式設計師JavaMaven
- 好程式設計師Java學習路線分享SpringMVC之MVC概述程式設計師JavaSpringMVC
- 好程式設計師Java學習路線分享Java中的位移運算程式設計師Java
- 好程式設計師Java學習路線分享三大特性之多型程式設計師Java多型
- 好程式設計師Java學習路線分享Dubbo架構介紹程式設計師Java架構
- 好程式設計師Java學習路線分享多執行緒概念程式設計師Java執行緒
- 好程式設計師Java學習路線分享MySQL目錄結構程式設計師JavaMySql
- 好程式設計師Python學習路線分享實現快速排序演算法程式設計師Python排序演算法
- 好程式設計師Java學習路線之集程式設計師Java
- 好程式設計師Java學習路線JSP物件程式設計師JavaJS物件
- 好程式設計師Java學習路線分享Java弱引用的理解與使用程式設計師Java
- 好程式設計師Java學習路線分享Java案例-封裝JDBC工具類程式設計師Java封裝JDBC
- 好程式設計師Java學習路線分享怎麼理解Java物件導向程式設計師Java物件
- 好程式設計師Java學習路線分享SpringMVC之請求和響應程式設計師JavaSpringMVC
- 好程式設計師Java學習路線分享如何處理中文引數程式設計師Java
- 好程式設計師Java學習路線分享MyBatis之關聯查詢程式設計師JavaMyBatis
- 好程式設計師Java學習路線分享JVM類載入機制程式設計師JavaJVM
- 好程式設計師Java學習路線分享Spring常見面試題程式設計師JavaSpring面試題
- 好程式設計師大資料學習路線分享MAPREDUCE程式設計師大資料
- 好程式設計師大資料學習路線分享SparkSQl程式設計師大資料SparkSQL
- 好程式設計師大資料學習路線分享Hbase指令學習程式設計師大資料
- 好程式設計師Java學習路線分享Spring建立Bean的3種方式程式設計師JavaSpringBean
- 好程式設計師Java學習路線分享JavaScript基本資料型別分析程式設計師JavaScript資料型別
- 好程式設計師Java學習路線分享JavaEE的13種核心技術程式設計師Java