1. 程式人生 > >演算法 - 二分法查詢

演算法 - 二分法查詢

什麼是二分法查詢

二分法查詢主要是為了快速查詢給定陣列內,期待值在陣列中的位置(下標)

二分法查詢通過對整個陣列取中間值,判斷期待值所在的範圍並縮小範圍,每次查詢範圍折半,直到範圍的邊界重合,得出期待值的位置,如果找不到返回null

二分法有一個先決條件是:陣列內元素必須是有序的

簡單圖解

給定一個包含1,3,5,7,8,9這一個元素的有序陣列,求得期待值7所在的位置,下邊用綠塊表示指標所在位置

若是按照直接遍歷的方式,綠塊會從陣列的第一個下標開始比較,直到7所在的下標得到結果,遍歷需要4次,下邊演示下二分法的圖示

第一次,取值範圍為整個陣列,取陣列長度中間值(0+5)/2取整2作為下標

取中間值初始以陣列的第一個下標與最後一個下標相加取中間值,如果不為整,捨去小數部分

比較期待值與下標為2的值大小,發現5<7,7這個值應在中間值的右側

縮小查詢範圍為中間值+1與最大下標

第二次,範圍縮小為原陣列的一半,下標不變,取中間值(3+5)/2=4

下標4對應的值8,大於7,所以向左取範圍最小下標3,最大下標4-1=3

第三次,取中間值(3+3)/2=3,下標3上的值恰好與期待值相等,返回下標3

雖然看起來只少了一次,原因在陣列的長度小,另外就是期待值設定的小,

再舉個長一點的例子,這裡有1-100的陣列,100個元素,期待值為100

簡單遍歷次數最大為元素的個數n次,本例中100次

使用二分查詢只需要log2n次,本例中17次!

二分法查詢的Java實現

package binarysearch;

/**
 * 二分查詢:求得期待值在有序陣列中的位置
 * @author hellxz
 */
public class MyBinarySearch {

    /**
     * 二分查詢演算法實現
     * @param orderedArray 有序陣列
     * @param expect 期待數值
     * @return 期待值在陣列中的下標,如果期待數值不在陣列中,返回null
     */
    public static Integer binarySearch(int[] orderedArray, int expect) {
        //low與high構成動態的陣列下標範圍
        //初始low下標為0,high為陣列長度-1
        int low = 0;
        int high = orderedArray.length - 1;

        //當陣列範圍存在時,有兩種情況:最小邊界值小於最大邊界值 或 兩個邊界值相等;
        //最小邊界值不大於最大邊界值是有意義的,表示範圍的存在,如果範圍不存在了,說明陣列中無此元素
        while (low <= high) {
            //取兩個邊界下標的中間下標與中間值,作為下標時會自動取整
            int middle = (low + high) / 2;
            int middleVal = orderedArray[middle];
            //中間值與期待值相等,說明中間值的下標就是我們要找的期待數的下標
            if (middleVal == expect) {
                return middle;
            }
            //中間值小於期待值,我們需要將最小邊界下標移到中間下標的下一位
            //此時,最大邊界不變,最小邊界變大,範圍縮小原來一半
            if (middleVal < expect) {
                low = middle + 1;
            }
            //中間值大於期待值,說明最大邊界應小於中間下標
            if (middleVal > expect) {
                high = middle - 1;
            }
        }

        //迴圈結束未返回下標說明陣列中不存在期待元素,返回null
        return null;
    }

    public static void main(String[] args) {
        int[] arr = { 2, 4, 5, 6, 10, 18, 19,22, 25, 70};
        int expectVal = 25;
        System.out.printf("當前期待的值為%d,其所在的下標為%d", expectVal, binarySearch(arr, expectVal));
    }
}

最後

本人不是科班出身,很多知識都在學習中,演算法與資料結構系列將不定時更新(學會哪個更哪個