Java實現二分查找算法

二分查找(binary search),也稱折半搜索,是一種在 有序數組查找某一特定元素 的搜索算法。搜索過程從數組的中間元素開始,若是中間元素正好是要查找的元素,則搜索過程結束;若是某一特定元素大於或者小於中間元素,則在數組大於或小於中間元素的那一半中查找,並且跟開始同樣從中間元素開始比較。若是在某一步驟數組爲空,則表明找不到。這種搜索算法每一次比較都使搜索範圍縮小一半。html

  • 時間複雜度:折半搜索每次把搜索區域減小一半,時間複雜度爲O(log n)。(n表明集合中元素的個數)
  • 空間複雜度: O(1)。雖以遞歸形式定義,可是尾遞歸,可改寫爲循環。

動圖演示

binary-search
二分查找

代碼描述

遞歸

int binarysearch(int array[], int low, int high, int target) {
    if (low > high) return -1;
    int mid = low + (high - low) / 2;
    if (array[mid] > target)
        return binarysearch(array, low, mid - 1, target);
    if (array[mid] < target)
        return binarysearch(array, mid + 1, high, target);
    return mid;
}
複製代碼

非遞歸

int bsearchWithoutRecursion(int a[], int key) {
    int low = 0;
    int high = a.length - 1;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (a[mid] > key)
            high = mid - 1;
        else if (a[mid] < key)
            low = mid + 1;
        else
            return mid;
    }
    return -1;
}
複製代碼

二分查找中值的計算

這是一個經典的話題,如何計算二分查找中的中值?你們通常給出了兩種計算方法:java

  • 算法一: mid = (low + high) / 2
  • 算法二: mid = low + (high – low)/2

乍看起來,算法一簡潔,算法二提取以後,跟算法一沒有什麼區別。可是實際上,區別是存在的。算法一的作法,在極端狀況下,(low + high)存在着溢出的風險,進而獲得錯誤的mid結果,致使程序錯誤。而算法二可以保證計算出來的mid,必定大於low,小於high,不存在溢出的問題。算法

二分查找法的缺陷

二分查找法的O(log n)讓它成爲十分高效的算法。不過它的缺陷卻也是那麼明顯的。就在它的限定之上:必須有序,咱們很難保證咱們的數組都是有序的。固然能夠在構建數組的時候進行排序,但是又落到了第二個瓶頸上:它必須是數組。數據庫

數組讀取效率是O(1),但是它的插入和刪除某個元素的效率倒是O(n)。於是致使構建有序數組變成低效的事情。數組

解決這些缺陷問題更好的方法應該是使用二叉查找樹了,最好天然是自平衡二叉查找樹了,既能高效的(O(n log n))構建有序元素集合,又能如同二分查找法同樣快速(O(log n))的搜尋目標數。ide

參考資料spa

  1. 二分查找法的實現和應用匯總
  2. 二分查找(Binary Search)須要注意的問題,以及在數據庫內核中的實現
相關文章
相關標籤/搜索