計算機算法與實現:二進制搜索(二分法)


二進制搜索聽起來很計算機,它有個接地氣的名字叫二分法,是否瞬間清楚很多呢,顧名思義,二分法就是講查找的東西分成兩半后查找。

我們都用過新華字典,我使用的方法如下(比如查找“我”字):

  1. 將字典大約分成兩個相同的部分;
  2. 看打開的位置是哪個字母的部分(這里我們假設打開的是T字母的部分);
  3. 判斷打開的位置是在W前面還是后面;(我明確知道W在T的后面)
  4. 丟棄不需要的部分(前半部分)
  5. 重復上述動作直到找到W部分
  6. 在W部分中重復上述動作找到O,最終找到WO

我可以這么做的首要原因是我知道新華字典是按英文字母表排序的,我這么做的過程就是二進制搜索算法的實現過程。閑話少說,來個實例說明吧。

二進制搜索前提條件:1. 已排序的數據內容;2. 數據長度。

我們來試試描述一下按查新華字典的方式查找30的過程,假設最小索引位f,最大索引為l,中間索引為m,則中間索引m=(f+l)/2,如下圖所示:

我們找到了數據的中間點m=(16+0)/2=8,成功的將數據分成兩個相同長度的部分,索引8對應的數據為27,27明顯不是30,而30>27,也就是說,我們需要找的30位於數據的右邊部分,左邊部分可以丟棄咯,得到新的數據搜索區域的f=m+1=8+1=9、l不變、m=(f+l)/2=(9+16)/2=12(為什么等於12應該都清楚吧),如下圖所示:

 

搜索區域已經變成了原來的一半,此時中間點m=(9+16)/2=12(為什么25/12等於12都懂的吧),索引12對應的數據是40,40明顯不是30,而30<40,也就是說,我們需要找的30位於數據的左邊部分,右邊部分可以丟棄,得到新的搜索區域的f不變、l=m-1=12-1=11、m=(f+l)/2=(9+11)/2=10,如下圖所示:

搜索區域更小了哦,重復上面的步驟,索引10對應的數據是31,30<31,因此繼續丟棄右邊的部分,如下圖所示:

 

中間點索引對應的數據就是30,嘿嘿,找到了!搜索結束,算法完成!

讓我們嘗試找一下27。

中間點索引8對應的數據就是27,嘿嘿,一次就可以找到!好運!

讓我們嘗試查找一個數據中並不存在的數據25,看看會發生什么情況?是否很期待算法崩潰掉?

同樣的,我們先找到f、l和m。

判斷中間點數據27,25<27,因此丟棄右邊部分。

判斷中間點數據11,25>11,因此丟棄左邊部分。

判斷中間點數據18,25>18,因此丟棄左邊的部分。

判斷中間點數據22,25>22,因此丟棄左邊部分。

呃……現在怎么辦?讓我們繼續,判斷中間點數據24,25>24,因此丟棄左邊部分,f=m+1=8,f>l,最小索引大於最大索引,錯誤(表示搜索失敗,無法找到搜索的數字)!

 以上的部分以文字圖表方式說明了二進制搜索算法的整個過程,為了讓大家更好的理解和使用,下面附上代碼示例,希望有所幫助:

function binarySearch(array, target){
  // Define Start and End Index
  let startIndex = 0;
  let endIndex = array.length - 1;
  // While Start Index is less than or equal to End Index
  while(startIndex <= endIndex) {
    // Define Middle Index (This will change when comparing )
    let middleIndex = Math.floor((startIndex + endIndex) / 2);
    // Compare Middle Index with Target for match
    if(target === array[middleIndex) {
      return console.log("Target was found at index " + middleIndex);
    }
    // Search Right Side Of Array
    if(target > array[middleIndex]) {
      console.log("Searching the right side of Array")
      // Assign Start Index and increase the Index by 1 to narrow search
      startIndex = middleIndex + 1;
    }
    // Search Left Side Of Array
    if(target < array[middleIndex]) {
      // Assign End Index and increase the Index by 1 to narrow search
      console.log("Searching the left side of array")
      endIndex = middleIndex - 1;
    }
    // Not found in this iteration of the loop. Looping again.
    else {
      console.log("Not Found this loop iteration. Looping another iteration.")
    }
  }
  // If Target Is Not Found
  
console.log("Target value not found in array");
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM