二分查找算法(折半查找算法)

二分查找又称折半查找、二分搜索、折半搜索等,是在分治算法基础上设计出来的查找算法,对应的时间复杂度为O(logn)。

二分查找算法仅适用于有序序列,它只能用在升序序列或者降序序列中查找目标元素。

二分查找算法的实现思路

在有序序列中,使用二分查找算法搜索目标元素的核心思想是:不断地缩小搜索区域,降低查找目标元素的难度。

以在升序序列中查找目标元素为例,二分查找算法的实现思路是:

初始状态下,将整个序列作为搜索区域(假设为 [B, E]);

找到搜索区域内的中间元素(假设所在位置为 M),和目标元素进行比对。如果相等,则搜索成功;如果中间元素大于目标元素,表明目标元素位于中间元素的左侧,将 [B, M-1] 作为新的搜素区域;反之,若中间元素小于目标元素,表明目标元素位于中间元素的右侧,将 [M+1, E] 作为新的搜素区域;
重复执行第二步,直至找到目标元素。如果搜索区域无法再缩小,且区域内不包含任何元素,表明整个序列中没有目标元素,查找失败。

举个简单的例子,在下图所示的升序序列中查找元素 31。

二分查找算法的具体实现过程为:

  1. 初始状态下,搜索区域是整个序列。找到搜索区域内的中间元素。指定区域内中间元素的位置可以套用如下公式求出:

Mid = ⌊ Begin + (End - Begin) / 2 ⌋

End 表示搜索区域内最后一个元素所在位置,Begin 表示搜索区域内第一个元素所在的位置,Mid 表示中间元素所在的位置。

图 1 中,所有元素的位置分别用 0~9 表示,中间元素的位置为 ⌊ 0 + (9 - 0) / 2 ⌋ = 4,如下图所示:

中间元素 27 < 31,可以断定 [0, 4] 区域内绝对没有 31,目标元素只可能位于 [5, 9] 区域内,如下图所示:

  1. 在 [5, 9] 区域内,中间元素的位置为 ⌊ 5 + (9 - 5) / 2 ⌋ = 7,如下图所示:

中间元素 35 > 31,可以断定 [7, 9] 区域内绝对没有 31,目标元素只可能位于 [5,6] 中,如下图所示:

  1. 在 [5, 6] 区域内,中间元素的位置为 ⌊ 5 + (6- 5) / 2 ⌋ = 5,中间元素就是 31,成功找到目标元素。

二分查找算法的具体实现

如下用伪代码给大家展示了二分查找算法的具体实现过程:

输入 arr[]                                // 输入有序序列
binary_search( arr , begin , end , ele):  // [begin,end] 指定搜索区域,ele 为要搜索的目标元素if begin > end:                       // [begin,end] 不存在时,返回一个错误值(比如 -1)return -1mid <- ⌊ begin+(end-begin)/2 ⌋        // 找到 [begin,end] 区域内中间元素所在位置的下标if ele == arr[mid]:                  // 递归的出口,即 ele 和中间元素的值相等return midif ele < arr[mid]:                  // 比较 ele 和中间元素的值,进一步缩小搜索区域return binary_search(arr , begin , mid-1 , ele)else:return binary_search(arr , mid+1 , end , ele)

结合伪代码,如下是用二分查找算法在 {10, 14, 19, 26, 27, 31, 33, 35, 42, 44} 升序序列中查找元素 31 的 C 语言程序:

#include <stdio.h>
//实现二分查找算法,ele 表示要查找的目标元素,[p,q] 指定查找区域
int binary_search(int *arr,int p,int q,int ele) {int mid = 0;//如果[p,q] 不存在,返回 -1if (p > q) {return -1;}// 找到中间元素所在的位置mid = p + (q - p) / 2;//递归的出口if (ele == arr[mid]) {return mid;}//比较 ele 和 arr[mid] 的值,缩小 ele 可能存在的区域if (ele < arr[mid]) {//新的搜索区域为 [p,mid-1]return binary_search(arr, p, mid - 1, ele);}else {//新的搜索区域为 [mid+1,q]return binary_search(arr, mid + 1, q, ele);}
}
int main()
{int arr[10] = { 10,14,19,26,27,31,33,35,42,44 };//输出二叉查找元素 31 所在位置的下标printf("%d", binary_search(arr, 0, 9, 31));return 0;
}

如下是用二分查找算法在 {10, 14, 19, 26, 27, 31, 33, 35, 42, 44} 升序序列中查找元素 31 的 Java 程序:

public class Demo {// 实现二分查找算法,ele 表示要查找的目标元素,[p,q] 指定查找区域public static int binary_search(int[] arr, int p, int q, int ele) {// 如果[p,q] 不存在,返回 -1if (p > q) {return -1;}// 找到中间元素所在的位置int mid = p + (q - p) / 2;// 递归的出口if (ele == arr[mid]) {return mid;}// 比较 ele 和 arr[mid] 的值,缩小 ele 可能存在的区域if (ele < arr[mid]) {// 新的搜索区域为 [p,mid-1]return binary_search(arr, p, mid - 1, ele);} else {// 新的搜索区域为 [mid+1,q]return binary_search(arr, mid + 1, q, ele);}}public static void main(String[] args) {int[] arr = new int[] { 10, 14, 19, 26, 27, 31, 33, 35, 42, 44 };// 输出二叉查找元素 31 所在位置的下标int add = binary_search(arr, 0, 9, 31);System.out.print(add);}
}

如下是用二分查找算法在 {10, 14, 19, 26, 27, 31, 33, 35, 42, 44} 升序序列中查找元素 31 的 Python 程序:

#实现二分查找算法,ele 表示要查找的目标元素,[p,q] 指定查找区域
def binary_search(arr,p,q,ele):#如果[p,q] 不存在,返回 -1if p > q:return -1#找到中间元素所在的位置mid = p + int( (q - p) / 2 )#递归的出口if ele == arr[mid]:return mid#比较 ele 和 arr[mid] 的值,缩小 ele 可能存在的区域if ele < arr[mid]:return binary_search(arr,p,mid-1,ele)else:return binary_search(arr,mid+1,q,ele)
arr = [10, 14, 19, 26, 27, 31, 33, 35, 42, 44]
#输出二叉查找元素 31 所在位置的下标
add = binary_search(arr, 0, 9, 31);
print(add)

以上程序的输出结果均为:

5

二分查找算法(折半查找算法)相关推荐

  1. python实现二分查找(折半查找)算法

    python实现二分查找算法 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. 查找又称折半 ...

  2. 数据结构与算法(8-2)有序表查找(折半查找(二分查找)、插值查找)

    目录 一.折半查找(二分查找) 二.插值查找 总代码 一.折半查找(二分查找) 原理:一次次折半,不断向着查找值的位置靠近 . 适用场景:有序(必须) 流程:开始时,min标志首,max标志尾,med ...

  3. php折半查找算法,php二分法查找(也叫折半查找)算法 (数组必须是从小到大的)

    //php二分法查找(也叫折半查找)算法/ 数组必须是从小到大的 $abs=array(1,12,13,114,115,116,117,118); //z查找数组的最大下标 $hight = coun ...

  4. 数据结构之二分查找(折半查找)

    数据结构之二分查找(折半查找) 二分查找又称折半查找,优点是次数比较少,查找速度快,平均性能好,其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先 ...

  5. Java有序表查找:折半查找、二分查找、差值查找和斐波那契查找

    Java有序表查找:折半查找.二分查找.差值查找和斐波那契查找     [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/51 ...

  6. 二分查找的平均查找长度_二分查找(折半查找)代码实现

    整理不易,手有余香请点赞! 折半查找,也称二分查找,在某些情况下相比于顺序查找,使用折半查找算法的效率更高.但是该算法的使用的前提是静态查找表中的数据必须是有序的. 在折半查找之前对查找表按照所查的关 ...

  7. 二分查找(折半查找)总结

    ** 二分查找(折半查找)总结 ** 文章目录 二分查找(折半查找)总结 一.基本概念 二.编写代码 1.二分查找 2.测试代码 三.输出结果 四.总结评价 一.基本概念 二分查找也叫折半查找,是一种 ...

  8. 二分查找(折半查找)简介与代码实现(C++)

    二分查找(折半查找)简介与代码实现 1.简介 2.代码实现(C++) 2.1.写法一(target在左闭右闭区间) 2.2.写法二(target在左闭右开区间) 3.代码检验 1.简介 二分查找的本质 ...

  9. 查找(包括顺序查找和折半查找)

    顺序查找 顺序查找又叫线性查找,主要用于线性表中的查找.顺序查找通常情况下分为对一般无序线性表的查找和对按关键字有序的顺序表的查找.下面进行比较讨论: 1.一般线性表的查找 作为一个直观的查找方法,其 ...

  10. 数据结构之查找-顺序查找,折半查找,分块查找

    文章目录 一.顺序查找 1.1 无序表的顺序查找 1.2 有序表的顺序查找 二.折半查找 三.分块查找 一.顺序查找 顺序查找又称线性查找,主要用于在线性表中进行查找. 1.1 无序表的顺序查找 对无 ...

最新文章

  1. python的for语句用法_python中list循环语句用法实例
  2. 【虚拟机】虚拟机(Vmware)怎么进入BIOS
  3. Superset配置impala数据源
  4. CCIE理论-第七篇-SD-WAN网络(二)
  5. 基于TCP和多线程实现无线鼠标键盘-Socket(1)
  6. ORA-04043: 对象 dba_data_files 不存在 BUG
  7. Script.NET 1.0版本的Tcl+Html界面编程原理
  8. 20220705开发板BL602的SDK编译以及刷机
  9. 逆向序列号生成算法(三)
  10. 苹果亮度自动调节怎么关闭_Redmi K30 Pro自动亮度调节和iPhone基本一致,安卓手机的大进步...
  11. JUnit测试提示java.lang.Exception: No runnable methods
  12. 聊聊CVE漏洞编号和正式公开那些事
  13. 信息安全体系建设☞流量可视化(2)sflow
  14. C语言编程>第十六周 ② 函数fun的功能是:统计长整数test的各位上出现数字5、6、7的次数,并通过外部(全局)变量sum5、sum6、sum7返回主函数。
  15. 离散数学知识点总结(2):命题公式的类型
  16. 打印当前页面指定元素中的内容
  17. xml 操作unity 的文档
  18. python 仪表盘图片读数_opencv+python计算仪表盘读数
  19. python自学第六天之列表增删改查
  20. 汇付聚合支付自助接入解决方案快捷支付接口代码详解

热门文章

  1. Windows常用command line操作
  2. HTTP协议之防盗链与反防盗链
  3. 第十七章——配置SQLServer(1)——为SQLServer配置更多的处理器
  4. ride.py打开失败——默认文件打开方式设置为python
  5. 中国首届杰出数据库工程师评选前10名单
  6. 基于PHP+MySQL公积金在线办理系统的设计与实现
  7. 《Automatic Image-Based WasteClassification》论文笔记
  8. 如何设置活动定时器的时间
  9. 8m照片宽和高是多少_8m x 4.5m 换算成像素是多少
  10. mysql 栅格数据结构_图解Mysql索引的数据结构!看不懂你来找我