Java中陣列氣泡排序、選擇排序、二分查詢的詳細分析
前言:儘管在實際開發中,我們通過Arrays工具類就可以便利地對陣列進行排序和查詢的操作,但是掌握氣泡排序、選擇排序、二分法查詢的思想對於程式設計來說還是極其重要的,在很多場景都會用到。希望通過這篇部落格的分析能給大家帶來收穫。
主題:陣列的排序和查詢
1、冒泡法排序:
需求:將陣列 int arr = {2,4,11,0,-4,333,90} 通過冒泡法進行排序,下面以升序排列進行分析。
① 思路分析:
第1次比較:先讓陣列中的第1個元素和第2個元素進行比較,如果第1個元素的值如果比第2個元素的大,那麼就交換位置。接著再讓第2個元素和第3個元素進行比較...直到比到最後一個元素。第1次比較完,陣列中的最大值就出現在陣列最大索引處。
第2次比較:因為最大索引處已經放上了陣列中的最大值,不需要再進行比較。再次讓經過第1次比較後陣列中的第1個元素和第2個元素比較,如果第1個元素的值如果比第2個元素的大,那麼就交換位置...(重複第1次比較中的操作)。第2次比較完,陣列中的第2大的值就出現在陣列倒數第二個位置。
第3次比較、第4次比較、第5次比較、第6次比較都是同樣的思路。
② 思路圖解:
③ 光看思路圖解可能還不詳細,我們可以看看冒泡法的具體比較過程:
值得留意的細節是:陣列中一共7個元素,共比較了6次,對應了外迴圈中 i 從 1 變化到 6(即7-1); 而每次比較的次數也在逐漸變少,對應著內迴圈中 j 從 0 變化到 arr.length - i(即第1次比較了6次,第2次比較了5次,第3次比較了4次...也就是第 i 次比較的次數是 7- i);
④ 程式碼實現:
/** * 氣泡排序 * @param arr * @param isAsc為true進行升序排列,為false進行降序排列 */ public static void bubbleSort(int[] arr, boolean isAsc) { // 遍歷比較次數=陣列長度-1 for (int i = 1; i < arr.length; i++) { // 每次遍歷比較的次數:陣列長度-當前遍歷的次數 for (int j = 0; j < arr.length - i; j++) { if (isAsc) { // 升序排列 if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } else { // 降序排列 if (arr[j] < arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } }//內迴圈 }//外迴圈 }//方法
2、選擇法排序
需求:將陣列 int arr = {2,4,11,0,-4,333,90} 通過選擇法進行排序,我們以降序排列進行分析。
① 思路分析:選擇法和冒泡法排序的不同在於,選擇法排序不是前後相鄰元素進行比較,而是在每次比較中選定指定索引的陣列元素和其餘的元素進行比較。
第1次比較:先讓陣列中索引為1的元素和索引為2的元素進行比較,如果第1個元素的值如果比第2個元素的小,那麼就交換位置。接著讓索引為1的元素和索引為3的元素進行比較...直到比到陣列中最後一個元素。第1次比較完,陣列中的最大值出現在陣列中索引為1的地方。
第2次比較:因為索引為1的地方已經放上了陣列中的最大值,不需要再進行比較。第2次比較時,讓經過第1次比較後陣列索引為2的元素同索引為3的元素進行比較,如果第2個元素的值如果比第3個元素的小,那麼就交換位置...(重複第1次比較中的操作)。第2次比較完,陣列中的第2大的值就出現在陣列中索引為2的位置。
第3次比較、第4次比較、第5次比較、第6次比較都是同樣的思路。
② 思路圖解
③ 同樣的,我們來看看具體的比較過程:
值得留意的細節是:陣列中一共7個元素,同樣比較了6次,對應了外迴圈中 i 從 0 變化到 5(即7-1-1); 而每次比較的次數也在逐漸變少,對應著內迴圈中 j 從 i +1 變化到 arr.length (即第1次比較的過程是選中的元素從第2個元素開始比較,比較了6次;第2次從第3個元素開始比較,比較了5次;第3次從第4個元素開始比較,比較了4次...也就是第 i 次比較是從第 i + 1個元素開始比較);
④ 程式碼實現
/**
* 選擇排序
* @param arr
* @param isAsc為true進行升序排列,為false進行降序排列
*/
public static void selectSort(int[] arr, boolean isAsc) {
// 外面的迴圈是控制當前沒有確定最值的索引
for (int i = 0; i < arr.length-1; i++) {
// 裡面的迴圈是控制前面元素和剩餘元素進行比較
for (int j = i+1; j < arr.length; j++) {
if (isAsc) {
// 升序:拿著前面的元素值和後面的元素值進行比較,發現小的往前放
if (arr[i] > arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
} else {
// 降序:拿著前面的元素值和後面的元素值進行比較,發現大的往前放
if (arr[i] < arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}//內迴圈
}//外迴圈
}//方法
3、二分法查詢:
① 思路
② 具體查詢過程
③ 程式碼實現
* 二分查詢法
*
* @param arr
* @param key
* @return 要查詢元素在陣列中的索引,若返回值為-1說明沒有要查詢的元素,
*/
public static int binarySearch(int[] arr, int key) {
// 在不斷縮小範圍的過程中,可以
// 返回-1則說明找不到這個數
// 定義起始、終點、中間索引,目標key值索引
int start = 0;
int end = arr.length - 1;
// 在陣列中找要找的數,因為不一定會一下子找到,所以這應該是一個重複尋找的過程,即會用到迴圈
while (start <= end) {// 看出start不斷增大,end不斷縮小;如果當start和end相等時都還找不到,start會繼續增加,end繼續變小,此時這已經不是一個正常的陣列,結束迴圈
int middle = (start + end) / 2;
int value = arr[middle];
// 讓中間索引對應的值value與要查詢的值key進行比較
if (key == value) {
// 如果相等,即找到,則返回中間索引,並跳出迴圈
return middle;
} else if (key > value) { // key > value
if (arr[0] < arr[1]) { // 升序
start = middle + 1;
} else { // 降序
end = middle - 1;
}
} else { // key < value
if (arr[0] < arr[1]) { // 升序:end = middle - 1
end = middle - 1;
} else {// 降序:start = middle + 1
start = middle + 1;
}
}
} // while括號
return -1;
}