1. 程式人生 > >經典資料查詢--二分查詢(簡單有序陣列的二分查詢)

經典資料查詢--二分查詢(簡單有序陣列的二分查詢)

引言

    博主最近正在學習演算法相關知識,是一個初學者。從初學者的角度來進行了解什麼是二分查詢。

    二分查詢就相當於猜數遊戲。我們小時候經常玩的猜數遊戲中所用的方法一樣。在這個遊戲裡,一個朋友會讓你猜他正想的一個1至100之間的數。當你猜了一個數後,他會告訴你三種選擇中的一個:你猜的比他想的大,或小,或猜中了。

    所以為了能用最小的次數猜中,必須從50開始猜。如果他說你猜的太小,則推出哪個數在51至100之間,所以下一次猜75(50至100的一半)。但如果他說你猜的50有些大,則推出哪個數在1至49之間,下一次猜25。

    每猜一次就會將可能的值劃分成兩部分。最後範圍會縮小到一個數字那麼大,就是答案。

    以往都是從1開始,然後是2,3,4等等,一個個進行線性查詢。而在二分查詢中,每猜測一次都是將可能的值劃分成兩部分,因此猜測的次數大大減少。

    以下就是線性和二次查詢:

/**
 * 有序陣列資料查詢 
 * @author whmAdmin
 *
 */
public class Search {

	private long[] a;	// 查詢的陣列
	private int nElems; // 陣列元素個數
	
	/**
	 * 線性查詢  時間複雜度O(N)
	 * @param searchKey	查詢的數
	 * @return 存在true 不存在 false
	 */
	public boolean linearSearch(long searchKey) {
		int j;
		// 找到停止迴圈
		for (j = 0; j < nElems; j++) {
			if(a[j] == searchKey) {
				break;
			}
		}
		// 判斷下座標
		if(j == nElems) {
			return false;
		}else {
			return true;
		}
	}
	
	/**
	 * 二分查詢有序陣列 時間複雜度O(logN)
	 * @param searchKey
	 * @return
	 */
	public int binarySearch(long searchKey) {
		// 下座標
		int lowerBound = 0;
		// 上座標
		int upperBound = nElems - 1;
		// 中間座標
		int curIn;
		
		while(true) {
			// 獲取中間座標
			curIn = (lowerBound + upperBound) /2;
			// 中間座標位置元素與查詢元素相等
			if(a[curIn] == searchKey) {
				// 返回下座標
				return curIn;
			// 上座標大於下座標
			} else if(lowerBound > upperBound){
				// 返回總位置數
				return nElems;
			} else{
				// 中間位置元素小於查詢元素
				if(a[curIn] < searchKey) {
					// 下座標等於中間座標後一位座標上
					lowerBound = curIn+1;
				}else {
					// 否則 上座標等於中間座標前一位座標上
					upperBound = curIn -1;
				}
			}
		}
	}
	
}
以上二分查詢只適合有序陣列進行查詢,沒有考慮重複值等其他因素。便宜初學者瞭解什麼是二分查詢。