计算机算法与实现:二进制搜索(二分法)


二进制搜索听起来很计算机,它有个接地气的名字叫二分法,是否瞬间清楚很多呢,顾名思义,二分法就是讲查找的东西分成两半后查找。

我们都用过新华字典,我使用的方法如下(比如查找“我”字):

  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