二分查找--图文详解

简介: 二分查找--图文详解

1. 什么是二分查找


二分查找也称折半查找,是在一组有序(升序/降序)的数据中查找一个元素,它是一种效率较高的查找方法。


2. 原理


  1. 查找的目标数据元素必须是有序的。没有顺序的数据,二分法就失去意义。
  2. 数据元素通常是数值型,可以比较大小。
  3. 将目标元素和查找范围的中间值做比较(如果目标元素=中间值,查找结束),将目标元素分到较大/或者较小的一组。
  4. 通过分组,可以将查找范围缩小一半。
  5. 重复第三步,直到目标元素=新的范围的中间值,查找结束。


3. 例子


(本文以升序为例进行讲解,降序方法类似)


3.1 当数组长度为奇数

假设有一组数据{1,2,3,4,5,6,7}

094dd9b4ee683eb1f1de38c39217de46_8bfd1ca07e65415ab847855de5bbc9e6.png

是奇数的情况很简单,指向中间的数字也很容易理解


如果要查找的数字是6,因为6大于中间的数字(4),所以舍去左边的数据。

4c30ab8e23a43c0b05641f4dddb5d895_0b6fe7faa2b745eb944739583ae0eb62.png


3.1 当数组长度为偶数

6e459236978bc0981063f405d876bcdd_7580ba52f67b40fabdb48653cd973978.png

当取中间元素,遇到两边数据个数不同时,并不影响我们查找元素,只需要规定是向上或向下取整。


所以数组长度是偶数还是奇数这个并不重要,也不影响怎么排除的问题,无非是多排除一个数字或者少排除一个数字。


3.3 实现过程

在 {1,2,3,4,5,6,7,8,9,10} 中查找元素9。


第一步要找到中间元素,设置两个变量low、high,分别指向数组第一个元素下标和最后一个元素下标,从而控制数组的范围,再根据low和high确定中间元素的下标mid

8e0bf13dc854e5fb19d2582acabccfdf_28e67f6908344e03b9f51ed67bbf561e.png

根据mid锁定的元素,和查找的元素(9)比较,确定新的查找范围、low 和high

733283040d4f4ee290b05f6cd4bc3ce0_d649cb2541f141c5a9e72ba9f99dffb0.png


b5ae677bfd17e825faaf047980ccc253_7a3cf1865f9a476daa4b8bd1b9d79264.png

此时,mid=8,arr[mid]=9,与要查找的元素相同,即已经找到了,并返回其下标。


如果数组中没有要查找的元素,会出现什么情况呢?


假设我们上面要查找的元素是:11

44fd7ddd0a61c119e31ab36f23b17820_7878cede7bd7421bbadd215335c70f97.png


此时low=high=mid=9,arr[mid]=10不等于11,查找了整个数组都没有找到。


根据上述过程编写代码:


定义所需变量:


  int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个初始数组
  int n;//被查找的数
  printf("请输入你要查找的数:");
  scanf("%d", &n);//输入
  int len = sizeof(arr)/sizeof(arr[0]);//计算数组长度
  int low = 0;
  int high=len-1;//数组最后一个元素的下标
  int mid=(low+high)/2;//中间元素的下标

查找过程中,low一直在high的左边,即low


我们用while循环语句控制查找过程

while语句的用法


  while (low <= high)//循环结束条件
  {
    //确定数组范围
    mid = (low + high) / 2;
    if (arr[mid] == n)
    {
      printf("找到了,下标是:%d\n", mid);
      break;
    }
    else if (arr[mid] > n)
    {
      high = mid -1;
    }
    else 
    {
      low = mid + 1;
    }
  }

完整代码:


#include<stdio.h>
int main()
{
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  int n;
  printf("请输入你要查找的数:");
  scanf("%d", &n);
  int len = sizeof(arr)/sizeof(arr[0]);
  int low = 0;
  int high=len-1;
  int mid=(low+high)/2;
  while (low <= high)
  {
    mid = (low + high) / 2;
    if (arr[mid] == n)
    {
      printf("找到了,下标是:%d\n", mid);
      break;
    }
    else if (arr[mid] > n)
    {
      high = mid -1;
    }
    else 
    {
      low = mid + 1;
    }
  }
  if (low > high)
    printf("没找到");
  return 0;
}

降序排列的数组进行二分查找时,只需改变判断条件:


else if (arr[mid] < n)
    {
      high = mid - 1;
    }


4. 顺序查找与二分查找的区别


对数组{1,2,3,4,5,6,7,8,9,10}进行顺序查找:


//在一个有序数组中查找具体的某个数字n
#include<stdio.h>
int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//升序
  int n;
  scanf("%d", &n);
  int i;
  for (i = 0; i < 10; i++)
  {
    if (arr[i] == n)
    {
      printf("找到了,下标是:%d\n", i);
      break;
    }
  }
  if (i == 10)
  {
    printf("没找到\n");
  }
  return 0;
}

虽然顺序查找法在书写上比二分法查找要简洁,但二分法比顺序查找速度更快


两者在查找前,必须知道将要查找的“值”


查找目的都是该“值”在列表中所在的位置(下标)


注:数据量越大,越能体现出二分法的快速性;相反数据量小的话,两者都可以使用


结束语


掌握了二分法的思想,代码实现就变得简单了。从hello world,到这里,你只要肯付出,就会有回报,加油!



相关文章
|
存储 人工智能 自然语言处理
知识图谱技术在金融领域的分析和应用
知识图谱(Knowledge Graph)是一种将实体、属性及关系等信息通过一定的数学模型进行组织、存储和检索的新型数据结构,它不仅可以实现对实体之间关系的描述,还可以完成对知识的描述。知识图谱由三元组构成:数据(Data)、实体(Entity)和关系(Relational),通过图数据库技术存储。知识图谱中的每一个实体都是一个节点,表示实体之间的关系,它描述了实体之间存在的关系和它们之间的属性。
|
存储 运维 安全
华为的云计算认证和阿里云的云计算认证有什么区别?
作为一个新兴的行业,云计算在最近几年正逐渐提高自己在人们日常生活中的作用,给人们的生活带来了巨大的便利,而且随着科技地不断发展。
|
开发者
微信公众平台开发基本配置
微信公众平台开发基本配置
466 0
|
Kubernetes 调度 Docker
kubernetes核心技术之Volume知识点总结
kubernetes核心技术之Volume知识点总结
180 0
|
存储 分布式计算 监控
揭秘阿里云EMR:如何巧妙降低你的数据湖成本,让大数据不再昂贵?
【8月更文挑战第26天】阿里云EMR是一种高效的大数据处理服务,助力企业优化数据湖的成本效益。它提供弹性计算资源,支持根据需求调整规模;兼容并优化了Hadoop、Spark等开源工具,提升性能同时降低资源消耗。借助DataWorks及Data Lake Formation等工具,EMR简化了数据湖构建与管理流程,实现了数据的统一化治理。此外,EMR还支持OSS、Table Store等多种存储选项,并配备监控优化工具,确保数据处理流程高效稳定。通过这些措施,EMR帮助企业显著降低了数据处理和存储成本。
448 3
|
安全 Linux 开发者
如何根据自己的开发板型号下载和配置交叉编译链
【8月更文挑战第25天】本指南详细介绍了如何为您的开发板下载和配置合适的交叉编译链。首先,需确定开发板的型号及其处理器架构(如ARM、MIPS等)。接着,可通过官方渠道或开源社区寻找适用的交叉编译链。下载时,请确保版本与开发板匹配并验证来源可靠性。配置过程包括解压文件、设置环境变量及验证配置正确性。最后,通过编译并运行简单的测试程序(如“Hello, World!”)来测试交叉编译链的有效性。若过程中遇到困难,建议查阅相关文档或求助于技术论坛。
256 1
|
Ubuntu Linux 数据库
在Linux中,如何进行软件包升级?
在Linux中,如何进行软件包升级?
|
监控 搜索推荐 物联网
不容错过!盘点4款实用的固定资产管理系统!
现如今,市面上的固定资产管理软件层出不穷。本文为大家整理了市面上比较优秀的几款软件,包括草料二维码、金蝶等等。
|
前端开发 JavaScript 开发工具
如何将网页封装成APP:一步步教你在线生成APP
随着移动互联网的发展,APP已经成为用户获取信息和服务的主要渠道,而企业和个人也纷纷加入APP开发的行列。但对于那些没有编程技能的人来说,想要开发一个APP仍然是很困难的事情。本文将介绍一种在线生成APP的方法,将网页封装成APP,无需编程经验,只需简单操作即可生成属于自己的APP。
|
小程序 前端开发 JavaScript
ssm+vue基本微信小程序的购物商城系统
随着互联网的趋势的到来,各行各业都在考虑利用互联网将自己的信息推广出去,最好方式就是建立自己的平台信息,并对其进行管理,随着现在智能手机的普及,人们对于智能手机里面的应用购物平台小程序也在不断的使用,本文首先分析了购物平台小程序应用程序的需求,从系统开发环境、系统目标、设计流程、功能设计等几个方面对系统进行了系统设计。开发出本购物平台小程序,主要实现了管理员后端:首页、个人中心、用户管理、商品分类管理、商品信息管理、订单评价管理、系统管理、订单管理,用户前端:首页、商品信息、商品资讯、我的等功能。总体设计主要包括系统功能设计、该系统里充分综合应用Mysql数据库、JAVA等相关知识。网页界面的
326 0