Java中的冒泡排序
排序的第一種思想:將第一個值與后面的值相比較,如果第一個值比其他值小,那么將較大的值與第一個換位置,然后繼續比較直至所有的數比較完成。這樣就可以保證第一個數是最大數。然后將第二個數再重復進行一遍此操作,不同的是第二個數進行操作時不用與第一個相比,因為已經確定過第一個是最大值。
排序的第二種思想:將兩個相鄰的數比較(第一個值和第二個值;第二個值和第三個值;第三個值和第四個值……),如果第一個值比第二個值小,那么將這兩個值換一個位置,然后后面依次進行此操作,這樣可以保證最小值在最后面。
首先冒泡排序的核心思想就是循環賦值,將兩個值在條件滿足的情況下交換位置。
例如: 3 , 5 如果第一個值小於第二個值則進行交換 → 5 , 3
而在Java中進行換位置的操作我們不能直接交換值,直接交換值的話會將值覆蓋
比如說:
1 package Dome; 2 3 public class Dome1 { 4 5 public static void main(String[] args) { 6 7 int arr[] = { 1, 2, 3, 4, 5 }; 8 9 System.out.println(arr[0] + ":" + arr[1]); 10 11 arr[0] = arr[1]; // 將下標為1的值賦值給下標為0的值 12 13 arr[1] = arr[0]; // 將下標為0的值賦值給下標為1的值 14 15 System.out.println(arr[0] + ":" + arr[1]); 16 17 } 18 19 }
但是這樣交換值的方法是錯誤的:
因為首先進行
arr[0] = arr[1];
此時arr[0]已經被修改為2了也就是arr[1]的值;
再將arr[0]的值賦值給arr[1]的話他們的值就是相同的了;
所以交換值正確的做法為:
1 package Dome; 2 3 public class Dome1 { 4 5 public static void main(String[] args) { 6 7 int arr[] = { 1, 2, 3, 4, 5 }; 8 9 System.out.println(arr[0] + ":" + arr[1]); 10 11 int temp; 12 13 temp = arr[0]; //將下標為0的值賦值給temp 14 15 arr[0] = arr[1]; // 將下標為1的值賦值給下標為0的值 16 17 arr[1] = temp; // 將下標為0的值賦值給下標為1的值 18 19 System.out.println(arr[0] + ":" + arr[1]); 20 21 } 22 23 }
首先定義一個與數組類型相同的變量temp(名字自定義)來儲存數組中的值,先將arr[0]的賦值給temp,然后將arr[1]賦值給arr[0],最后將temp的值賦值給arr[1];通俗的來講有一桶渾水和一桶干凈水,如果想換個水桶裝肯定不能直接將渾水往干凈的水里面倒,則要另一個桶來裝渾水,然后將干凈的水倒入裝渾水的桶里面,然后再將轉移的渾水裝入原來的裝干凈的水的水桶中,所以這里我們就需要多一個桶,也就是變量temp,這個變量的作用就是儲存一個數組中的某個值,以便進行交換,避免覆蓋 ;
而冒泡的核心操作就是循環進行賦值,直到排序完成;
那么我們接下來進行具體的操作(以數組[1,2,3,4,5]為例):
1.開始我們闡述的第一種排序思想(將第一個值依次與后面的相比):
首先進行第一個值的比較:
第一個值與第二個值比較滿足條件進行交換 : 2,1,3,4,5
第一個值與第三個值比較滿足條件進行交換 : 3,1,2,4,5
第一個值與第四個值比較滿足條件進行交換 : 4,1,2,3,5
第一個值與第五個值比較滿足條件進行交換 : 5,1,2,3,4
此時第一個值的比較完成,現在數組中第一個值便是數組中的最大值;
開始進行第二個值的比較:
(第二個值不需要與第一個相比因為在第一輪已經比過了)
第二個值與第三個值比較滿足條件進行交換 : 5,2,1,3,4
第二個值與第四個值比較滿足條件進行交換 : 5,3,1,2,4
第二個值與第五個值比較滿足條件進行交換 : 5,4,1,2,3
此時第二個值的比較完成,現在第二個值為數組中的第二大的值;
開始進行第三個值的比較:
第三個值與第四個值比較滿足條件進行交換 : 5,4,2,1,3
第三個值與第五個值比較滿足條件進行交換 : 5,4,3,1,2
此時第三個值的比較完成。
開始進行第四個值的比較:
第四個值與第五個值比較滿足條件進行交換 : 5,4,3,2,1
至此排序完成。
然后總結一下規律:
我們開始比較的值總共有四個(第一個值,第二個值,第三個值,第四個值)也就是數組的長度減1,而被比較的值是從開始比較的值的下標加1開始的然后自增,例如第一個值比較是是從第二個值開始與第一個值比較,第一輪總共比較了4次,第二輪3次,第三輪2次,第四輪1次。
然后找規律:
外層循環 內層循環開始的下標(下標是從0開始所以要減一) 內層循環次數
1 2-1 4
2 3-1 3
3 4-1 2
4 5-1 1
因為是遍歷數組要使用下標,所以要從0開始所以將外層循環的1,2,3,4改為0,1,2,3
代碼如下:
1 package Dome; 2 3 public class Dome1 { 4 public static void main(String[] args) { 5 int arr[] = { 1, 2, 3, 4, 5 }; 6 int temp; // 定義一個變量儲存數組中的值 7 int x = 0;// 交換的次數 8 9 // 外層循環的次數為數組長度減1 -->arr.length - 1 10 for (int i = 0; i < arr.length - 1; i++) { 11 /** 12 * 因為是下一個值與前面的值比較所以j的下標為i+1 而j的值會隨着i增加第一次為1,第二次為2,第三次為3,第四次為4 13 * 循環的次數為: 4 3 2 1 因為j自增 所以j只需要小於5即數組的長度即可 14 */ 15 for (int j = i + 1; j < arr.length; j++) { 16 if (arr[i] < arr[j]) { 17 // 進行交換 18 temp = arr[i]; 19 arr[i] = arr[j]; 20 arr[j] = temp; 21 22 } 23 x++;// 交換的次數自增+1 24 25 // 查看每次操作過后的組數 26 System.out.print("第" + x + "次交換" + ":\t"); 27 for (int z = 0; z < arr.length; z++) { 28 System.out.print(arr[z] + " "); 29 } 30 System.out.println(); 31 } 32 } 33 } 34 }
運行的結果
發現每次的結果與分析時的一樣。由此排序完成
1.開始我們闡述的第一種排序思想(相鄰的比較):
首先從第一個值開始比較:
第一個值與第二個值比較滿足條件進行交換 : 2,1,3,4,5
第二個值與第三個值比較滿足條件進行交換 : 2,3,1,4,5
第三個值與第四個值比較滿足條件進行交換 : 2,3,4,1,5
第四個值與第五個值比較滿足條件進行交換 : 2,3,4,5,1
這種操作核心原理與第一種相同,但是這種操作的結果是將最小的值往后移,第一次操作完的結果會使最后一位為最小值;
進行第二次比較:
第一個值與第二個值比較滿足條件進行交換 : 3,2,4,5,1
第二個值與第三個值比較滿足條件進行交換 : 3,4,2,5,1
第三個值與第四個值比較滿足條件進行交換 : 3,4,5,2,1
因為確定最后一個數為最小值了所以比較到倒數第二個就可以結束了,此時倒數第二個的值為倒數第二小;
進行第三次比較:
第一個值與第二個值比較滿足條件進行交換 : 4,3,5,2,1
第二個值與第三個值比較滿足條件進行交換 : 4,5,3,2,1
此時倒數第三個數為倒數第三小;
進行第四次比較:
第一個值與第二個值比較滿足條件進行交換 : 5,4,3,2,1
此時倒數第四個數為倒數第四小;第一個數為最大;比較完成
然后總結一下規律:
和第一種相似,外層循環也進行了四次,就是數組的長度減1,內層循環分別進行了4,3,2,1次;不一樣的是這次的比較每次都是從第一個第一個值開始(下標對應的為0),但是循環的次數依次減少,所以我們限制循環的次數的條件要變;
找規律:
外層循環 外層開始的下標 內層開始的下標 內層循環次數
1 0 0 4
2 1 0 3
3 2 0 2
4 3 0 1
因為這次排序中外層循環的下標只用於控制外層循環的次數所以可以不用寫出來;
代碼如下:
1 package Dome; 2 3 public class Dome1 { 4 public static void main(String[] args) { 5 int arr[] = { 1, 2, 3, 4, 5 }; 6 int temp; // 定義一個變量儲存數組中的值 7 int x = 0;// 交換的次數 8 9 // 外層循環的次數為數組長度減1 -->arr.length - 1 10 for (int i = 0; i < arr.length - 1; i++) { 11 /** 12 * 因為是相鄰的值比較,所以只用到了j的下標,i的下標只用來控制循環次數 13 * j每自增一次就是往后面移一次相鄰的兩個數 14 */ 15 for (int j = 0; j < arr.length-1-i; j++) { 16 if (arr[j] < arr[j+1]) { 17 //進行交換 18 temp = arr[j]; 19 arr[j] = arr[j+1]; 20 arr[j+1] = temp; 21 } 22 x++;// 交換的次數自增+1 23 24 // 查看每次操作過后的組數 25 System.out.print("第" + x + "次交換" + ":\t"); 26 for (int z = 0; z < arr.length; z++) { 27 System.out.print(arr[z] + " "); 28 } 29 System.out.println(); 30 } 31 } 32 } 33 }
結果如下:
分析的與結果一致,第二種排序完成;
至此完成了兩種冒泡排序,如有錯誤和建議請在評論留言。
2019-03-25 16:27:55