1. 程式人生 > >Java中陣列氣泡排序、選擇排序、二分查詢的詳細分析

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;
	}