【算法详解 | 二分查找】详解二分查找 \ 折半查找高效搜索算法 | 顺序数组最快搜索算法 | 递归循环解决二分查找问题

二分查找

by.Qin3Yu

本文需要读者掌握 顺序表 的操作基础,完整代码将在文章末尾展示。

顺序表相关操作可以参考我的往期博文:
【C++数据结构 | 顺序表速通】使用顺序表完成简单的成绩管理系统.by.Qin3Yu

文中所有代码使用 C++ 举例,且默认已使用部分头文件和 std 命名空间:

#include <iostream>
#include <vector>
using namespace std;

概念速览

二分查找概述

  • 二分查找 算法属于 搜索算法 的一种。它是一种高效的搜索算法,用于在有序数组或列表中查找特定元素的位置。
  • 二分查找的基本思想是通过将目标值与数组中间的元素进行比较,从而将搜索范围缩小一半。如果目标值小于中间元素,则继续在左侧子数组中进行二分查找;如果目标值大于中间元素,则继续在右侧子数组中进行二分查找;如果目标值等于中间元素,则直接返回该位置。通过重复这个过程,最终可以找到目标值或确定其不存在于数组中。
  • 二分查找算法的时间复杂度为 O(log n) ,且不需要额外存储空间。

二分查找通常被使用于符合以下条件的以下场景:

  1. 数组或列表是 有序 的;
  2. 静态 数据结构;
  3. 数据量较
  4. 只需要 快速确定 元素是否存在。

算法详解

逻辑解析

  • 二分查找,就是不断的对搜索范围进行折半,从而缩小搜索范围,我们用下面的数组来进行说明:

在这里插入图片描述

  • 在上面的有序数组中,我们要查找数组内是否存在值 31 ,于是我们可以如下图所示,使用三个指针,一个指向数组的最左端,一个指向数组的最右端,一个指向数组的中间。

在这里插入图片描述

  • 我们使用 leftrightmid 分别表示左、右、中指针,当前 mid 指向的值为 26 ,因为数组是有序数组,所以可以得知,我们要查找的值 31 一定在 26右侧 ,因此,我们将左指针 left 指针指向 mid 的后一位元素,然后重新计算出 mid 指针的位置:

在这里插入图片描述

  • 如图所示,当前 mid 指向的值为 44 ,比 31 小,因此我们要查找的 31 一定在 44 的左侧,因此,我们把右指针 right 指向 mid 的前一位元素,然后重新计算 mid 的位置:

在这里插入图片描述

  • 同理,mid 指向的值 30 小于 31 ,所以我们把 left 移到 mid 的后一位,然后重新计算 mid 的位置:

在这里插入图片描述

注意:在二分查找中,rightleft 重合属于正常现象,表示搜索范围只有一个数字。

  • 此时,我们再检查 mid 所指的值,就是我们要查找的 31,于是我们返回出对应的结果,表示成功查找到元素。
  • 我们在上一步的例子中做出一点修改,假如数组中没有我们要查找的值 31 ,则会产生一种情况,即 left 跑到 right 的右边,代表数组中没有我们要查找的元素:

在这里插入图片描述

代码实现

  • 在下例中,我们使用 vector 顺序表来保存数据,然后使用 binarySearch 方法表示二分搜索:
int main() {vector<int> data = {1,7,9,11,14,19,20,26,29,30,31,44,45,52,59};int target = 31;int result = binarySearch(data, target);
}
  • 首先,我们要声明左右指针,左指针指向数组最前端,即索引为 [0] ,右指针指向数组最右端,即索引为 [长度-1]
int left = 0;
int right = arr.size() - 1;
  • 在上文中我们提到,如果 left 指针移动到了 right 指针右边,则代表数组内没有对应的值,则返回 -1 ,表示没有目标值:
while (left <= right) {...
}
return -1;
  • 接下来,我们要根据左右指针计算出中间指针 mid ,即左指针加上两指针之和除二:
int mid = left + (right - left) / 2;
  • 最后,我们来判断 mid 指针所指值与查找值的关系,如果相等,则返回成功目标值的索引:
if (arr[mid] == target) {return mid;  // 找到目标,返回索引
}
  • 如果 mid 所指值比目标值小,则证明目标值只可能在 mid 右边,我们将 left 指针移到 mid 指针后一位,从右侧子数字开始查找:

在这里插入图片描述

else if (arr[mid] < target) {left = mid + 1;  // 继续在右侧子数组中查找
}
  • 相反,如果 mid 所指值比目标值大,则证明目标值只可能在 mid 左边,我们将 right 指针移到 mid 指针前一位,从左侧子数字开始查找:

在这里插入图片描述

else {right = mid - 1;  // 继续在左侧子数组中查找
}
  • 将上述代码做出结合后,便是完整的二分查找代码,具体如下文所示。

完整算法代码

#include <iostream>
#include <vector>
using namespace std;int binarySearch(const vector<int>& arr, int target) {int left = 0;int right = arr.size() - 1;while (left <= right) {int mid = left + (right - left) / 2;  // 防止(left + right)出现溢出if (arr[mid] == target) {return mid;  // 找到目标,返回索引} else if (arr[mid] < target) {left = mid + 1;  // 继续在右侧子数组中查找} else {right = mid - 1;  // 继续在左侧子数组中查找}}return -1;  // 没有找到目标,返回-1
}int main() {vector<int> data = {1,7,9,11,14,19,20,26,29,30,31,44,45,52,59};int target = 31;int result = binarySearch(data, target);if (result != -1) {55cout << "成功查找到对应值!" << result << endl;} else {cout << "找不到对应值。" << endl;}return 0;
}
至此,二分查找的所有内容讲解完毕(=
感谢您的阅读(=
CSDN.by.Qin3Yu

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/663138.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DAO设计模式

概念&#xff1a;DAO(Data Access Object) 数据库访问对象&#xff0c;**面向数据库SQL操作**的封装。 &#xff08;一&#xff09;场景 问题分析 在实际开发中&#xff0c;针对一张表的复杂业务功能通常需要和表交互多次&#xff08;比如转账&#xff09;。如果每次针对表的…

微服务系统设计:横向扩展和纵向扩展的对比

微服务扩展性&#xff1a;水平扩展 vs 垂直扩展 特点水平扩展垂直扩展扩展单位增加微服务实例增加单个实例的资源 (CPU&#xff0c;内存)方向向外&#xff0c;增加节点向上&#xff0c;增加单个节点的资源复杂性随着实例数量的增加&#xff0c;管理难度更大管理更简单&#xf…

聊一聊Tomcat的架构和运行流程,尽量通俗易懂一点

1、Tomcat的架构 这里可以看出 A、一个Tomcat就是一个Server&#xff0c;一个Server下会有多个Service&#xff0c; B、Service只负责封装多个Connector和一个Container&#xff08;Service本身不是容器&#xff0c;可以看做只是用来包装Connector和Container的壳&#xff0c…

基于Springboot的社区疫情防控平台

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 一、项目简介 以往的社区疫情防控管理…

交强险投保日期查询接口返回字段说明

API接口是现代互联网应用中重要的组成部分&#xff0c;通过接口的调用可以实现不同系统之间的数据交互和共享。在汽车保险行业中&#xff0c;交强险投保日期查询接口是非常关键的一个接口&#xff0c;本文将详细介绍该接口的返回字段和使用方法。 接口名称&#xff1a;交强险投…

【Java基础】自定义类型处理器xxxTypeHandler

1. 背景 在处理复杂的数据类型时&#xff0c;我们一般需要提供一种灵活的映射机制&#xff0c;以适应数据库字段和Java实体类之间的差异。 例&#xff1a; dim_bu_info_private_i表中有一个json类型的字段extend_info create table dim_bu_info_private_i (id …

计算机网络(第六版)复习提纲23

第五章&#xff1a;运输层 SS5.1 运输层协议概述 1 进程之间的通信 A 运输层要实现复用和分用&#xff1a; 复用&#xff1a;发送方不同进程都能使用用一个运输层协议传送数据 分用&#xff1a;接收方的运输层在剥去报文首部后能将这些数据交付给正确的应用 B 运输层提供应用进…

17 # 类型检查机制:类型保护

例子&#xff1a; enum Type {Strong,Week }class Java {helloJava(){console.log(hello Java);} }class JavaScript {helloJavaScript(){console.log(hello JavaScript);} }function getLanguage(type: Type){let lang type Type.Strong ? new Java() : new JavaScript();…

算法专题:记忆搜索

参考练习习题总集 文章目录 前置知识练习习题87. 扰乱字符串97. 交错字符串375. 猜数字大小II403. 青蛙过河464. 我能赢吗494. 目标和552. 学生出勤记录II576. 出借的路径数 前置知识 没有什么特别知识&#xff0c;只有一些做题经验。要做这类型的题目&#xff0c;首先写出暴…

C++入坑基础知识点

当学习了C语言之后&#xff0c;很多的小伙伴都想进一步学习C&#xff0c;但两者有相当一部分的内容都是重叠的&#xff0c;不知道该从哪些方面开始入门C&#xff0c;这篇文章罗列了从C到C必学的入门知识&#xff0c;学完就算是踏入C的大门了。 1. 命名空间 写C的时候&#xff…

使用Vue-Grid-Layout实现自定义工作台

前言 当代工作环境要求高度的个性化和定制化&#xff0c;因此&#xff0c;自定义工作台成为了一个热门的需求。Vue-Grid-Layout是一个强大的Vue组件&#xff0c;可以帮助我们实现自定义工作台的功能。在本篇博客中&#xff0c;我将向您介绍如何使用Vue-Grid-Layout来创建一个自…

找不到d3dcompiler_43.dll,无法继续执行代码的原因分析与解决方法

在运行某些软件或游戏时&#xff0c;可能会遇到系统提示找不到 d3dcompiler_43.dll 文件的情况。这个特定的动态链接库文件 (dll) 是 DirectX 3D 编译器组件的一部分&#xff0c;对于许多现代软件游戏的正常运行起着不可或缺的作用。它的主要功能在于将高级着色语言编写的代码转…

零基础学Python之核心基础知识

1.Python入门简介 &#xff08;1&#xff09;什么是Python Life is short, you need Python&#xff01;人生苦短&#xff0c;我用Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言…

MySQL数据库入门(概念+使用)

目录 1. 数据库的概念 1.1 数据库的存储介质 1.2 主流数据库 2. MySQL的基本使用 2.1 链接数据库 2.2 服务器管理 2.3 数据库&#xff0c;服务器和表关系 2.4 简单MySQL语句 3. MySQL架构 4. SQL分类 5. 存储引擎 本篇完。 1. 数据库的概念 数据库是按照数据结构来…

【CSS】页面自适应屏幕宽度(响应式布局媒体查询-@media、弹性布局、网格布局和相对单位-vh/em/%)

【CSS】页面自适应屏幕宽度&#xff08;响应式布局媒体查询-media、弹性布局、网格布局和相对单位-vh/em/%&#xff09; 一、媒体查询&#xff08;media&#xff09;1、媒体类型2、媒体特征3、媒体查询语法4、示例&#xff08;1&#xff09;示例1&#xff08;2&#xff09;示例…

筛选可疑密码

题目描述 情报小组截获了若干个可疑密码&#xff0c;这些密码都是4位数。现在他们获得了一条最新情报&#xff1a;个位数与千位数的和 减去十位数与百位数的和&#xff0c;结果是一个正数。请你帮助情报组筛选目前的可疑密码。 输入 输入两行&#xff0c;第一行是&#xff1…

Codeforces Round 481 (Div. 3)

本场比赛也是没有考察什么算法重点在于思维模式 目录 A. Remove Duplicates B. File Name C. Letters D. Almost Arithmetic Progression E. Bus Video System F. Mentors G. Petyas Exams A. Remove Duplicates 要求我们从右边开始保留数&#xff0c;我们可以考虑的就…

leetcode热题100.二叉树中的最大路径和

Problem: 124. 二叉树中的最大路径和 文章目录 题目解题方法复杂度Code 题目 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 …

c++ 语法函数

函数定义 返回值 函数名(参数列表){ 函数体 return xx } 无返回值 不需要return 返回值类型为 void int sum(int a,int b) {int sum a b;return sum; } int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n"…

pytorch_car_caring 排坑记录

pytorch_car_caring 排坑记录 任务踩坑回顾简单环境问题代码版本问题症状描述解决方法 cuda问题&#xff08;异步问题&#xff09;症状描述解决方法 任务 因为之前那个MPC代码跑出来的效果不理想&#xff0c;看了一天代码&#xff0c;大概看明白了&#xff0c;但要做改进还要有…