常见的查找算法以及分块搜索算法的简明教程

news/2024/4/29 3:03:06/文章来源:https://blog.csdn.net/everything_study/article/details/132950198

顺序查找

最基本的查找算法

举例

    // 顺序查找public static int searchSequence(int[] arr, int target) {int i = 0;for (int arr2 : arr) {if (arr2 == target) {return i;}i++;}return -1;}

二分查找

[! warning]
值得注意的是这个二分查找算法只对无重复元素的递增或递减的数组有效, 所以我们使用的时候要保证这个数组是有序的, 我们可以利用 Arrays.sort 来对这个数组进行排序,sort 的默认排序是递增排序

最简单的二分查找算法
举例

    // 二分查找,只能对排序算法使用,使用前我们需要先对这个数组进行排序public static int searchBinary(int[] arr, int target) {Arrays.sort(arr);int left = 0;int right = arr.length - 1;while (left <= right) {int mid = (left + right) / 2;if (arr[mid] == target) {return mid;} else if (target < arr[mid]) {right = mid - 1;} else if (target > arr[mid]) {left = mid + 1;}}return -1;}

二分查找的扩展插值查找

二分算法的优化, 通过逼近来实现这个查找
关键代码是
int mid = left + (target - a[left]) / (a[right] - a[left]) * (right - left);
这个与二分搜索算法类似, 本质上就是中值不太一样,

二分查找的扩展斐波那契查找

利用 0.618 的分割比进行查找这个数字
关键代码是
int mid =(int)((right - left) * (1.0 / 1.618) + left) ;

三种二分查找算法的优缺点是什么

二分查找算法

二分搜索算法(Binary Search)是一种在有序数组中查找特定元素的常用算法。它通过将数组不断分割为两半,并比较目标值与中间元素的大小关系来确定目标值所在的区间,从而逐步缩小搜索范围。以下是二分搜索算法的优缺点:
优点:
1. 效率高:二分搜索算法的时间复杂度为 O(log n),其中 n 是数组的长度。由于每次搜索都将搜索范围减半,因此它相对于线性搜索具有更高的效率。
2. 简单:二分搜索算法的实现相对简单,只需递归地分割数组并进行比较即可。
缺点:
1. 仅适用于有序数组:二分搜索算法要求数组是有序的,如果数组未排序,则需要先进行排序操作。
2. 需要额外的空间:二分搜索算法通常需要递归调用,因此可能需要额外的函数调用栈空间。
3. 不适用于插入或删除操作:二分搜索算法用于查找特定元素,但不适用于在数组中插入或删除元素。每次插入或删除操作后,数组可能会被改变,导致结果不准确。

插值搜索算法

插值搜索算法(Interpolation Search)是一种在有序数组中根据目标值的估计位置进行搜索的算法,它不是简单地将数组分割为两半,而是根据目标值与数组中元素的关系来动态计算估计位置。以下是插值搜索算法的优缺点:
优点:
1. 更快的平均搜索时间:插值搜索算法通过根据目标值的估计位置来确定搜索范围,因此平均情况下比二分搜索算法更快。
2. 在数据分布均匀时效果好:当数组中元素分布均匀且接近线性时,插值搜索算法的效果最佳。
缺点:
1. 对数据分布敏感:插值搜索算法对于数据分布不均匀的情况下效果可能很差,甚至可能比二分搜索算法更慢。
2. 可能导致不必要的比较:由于插值搜索算法根据估计位置来确定搜索范围,如果估计位置不准确,可能会导致不必要的比较操作。

斐波那契数列算法

斐波那契查找算法(Fibonacci Search)是一种在有序数组中进行查找的算法,它使用了斐波那契数列来确定搜索范围。与二分搜索和插值搜索相比,斐波那契查找算法有以下优缺点:
优点:
1. 更好的适应性:斐波那契查找算法对于分布不均匀且未知的数据集更具适应性。在某些情况下,它比二分搜索和插值搜索算法更快。
2. 减少比较次数:在某些情况下,斐波那契查找算法的平均比较次数较少,因为它动态调整搜索区间。
缺点:
1. 需要额外的空间:斐波那契查找算法需要预先计算斐波那契数列,这可能需要额外的空间来存储数列。
2. 对于小规模数据不如二分搜索:当数据规模较小时,斐波那契查找算法的性能可能不如简单的二分搜索算法。
3. 不适用于插入和删除操作:与二分搜索和插值搜索一样,斐波那契查找算法也不适用于在数组中执行插入或删除操作。

总结

二分搜索算法在大多数情况下都是一个可靠且高效的选择,特别是对于有序数组的查找操作。插值搜索算法在数据分布均匀的情况下可能会提供更好的性能,但在数据分布不均匀的情况下可能会导致不准确的结果。
斐波那契查找算法在某些情况下可以提供更好的性能,特别是在数据分布不均匀且未知的情况下。然而,它需要更多的空间和计算成本,并且不适用于插入和删除操作

分块查找

分块查找的应用场景

分块查找算法(Block Search)是一种在分块有序表中进行查找的算法。它将数据集划分为若干块(或称为块),每个块内部元素有序,但块与块之间不一定有序。对于一个给定的查找元素,首先确定其所在的块,然后在该块内进行查找。这使得分块查找算法在某些特定的应用场景下具有优势:

  1. 数据集较大且有序:分块查找算法适用于较大的有序数据集。通过将数据划分为块,可以快速缩小查找范围,提高查找效率。
  2. 块内元素相对较少:在每个块内,元素的数量相对较少。这使得块内查找的时间复杂度较低,从而进一步提高了整体查找效率。
  3. 需要频繁的插入和删除操作:分块查找算法相对于二分搜索等其他算法较容易处理插入和删除操作。因为只需要对块内进行相应的插入和删除操作,而不需要改变其他块的顺序。
    分块查找算法常见的应用场景包括:
  • 文件系统:在文件系统中,可以将文件按照某种规则划分为块,利用分块查找算法快速定位所需文件。
  • 图书馆索引:图书馆中的书籍可以按照分类号等信息进行分块,利用分块查找算法进行快速检索。
  • 路由表查找:在网络路由中,可以将路由表按照某种规则划分为块,利用分块查找算法快速查找匹配的路由项。
    需要注意的是,分块查找算法适用于特定场景,对于一般的有序数组查找可能并不是最优选择。因此,在使用分块查找算法时需要根据具体应用场景和问题特点进行合理选择。

分块查找的介绍

就是将数组中的数据划分为几个块, 前一个块的所有数据小于后一个块的所有数据, 我们以每一个块的最大值来进行分割
image.png

image.png

[!example]
下面的这个例子, 其实不太恰当, 只是为了描述这个分块查找的思想, 其实分块查找难点不在于如何查找, 难点在于如何分块, 如何将这个数组划分成满足前一个块的数据小于后一个块的数据. 这才是难点, 我的例子避去了这一点, 只是简单的对这个如何排序做了编辑

package heima_study.day3算法查找排序;import java.util.Objects;
import java.util.Scanner;public class 分块查找 {public static void main(String[] args) {int[] arr = { 16, 5, 9, 12, 21, 18,32, 23, 37, 26, 45, 34,50, 48, 61, 52, 73, 66 };block[] brr = new block[3];brr[0]=new block(21, 5, 0, 5);brr[1]=new block(45, 23, 6, 11);brr[2]=new block(73, 48, 12, 17);int target;Scanner input = new Scanner(System.in);target = input.nextInt();int i = searchBlock(brr, target);if (i != -1) {//查找成功int result = searchAll(arr, target, brr[i].getStart(), brr[i].getEnd());System.out.println(result);} else {System.out.println(-1);}input.close();}public static int searchAll(int[] arr, int target, int start, int end) {for (int i = start; i <= end; i++) {if (arr[i] == target) {return i;}}return -1;}public static int searchBlock(block[] brr,int target){for (int i = 0; i < brr.length; i++) {if (target < brr[i].getMax() && target > brr[i].getMin()) {//说明是在这个块里面return i;}}return -1;}}class block {private int max;private int min;private int start;private int end;public block() {}public block(int max, int min, int start, int end) {this.max = max;this.min = min;this.start = start;this.end = end;}public int getMax() {return this.max;}public void setMax(int max) {this.max = max;}public int getMin() {return this.min;}public void setMin(int min) {this.min = min;}public int getStart() {return this.start;}public void setStart(int start) {this.start = start;}public int getEnd() {return this.end;}public void setEnd(int end) {this.end = end;}@Overridepublic boolean equals(Object o) {if (o == this)return true;if (!(o instanceof block)) {return false;}block block = (block) o;return max == block.max && min == block.min && start == block.start && end == block.end;}@Overridepublic int hashCode() {return Objects.hash(max, min, start, end);}@Overridepublic String toString() {return "{" +" max='" + getMax() + "'" +", min='" + getMin() + "'" +", start='" + getStart() + "'" +", end='" + getEnd() + "'" +"}";}   }

分块查找的补充

在学习这个分块查找的时候, 我对于这个分块查找的原理还不是特别的清楚, 于是我就去网上查找资料,
在分块查找这个网页里面看到了一个较好的解释, 并且它提供了一个个人感觉还是不错的划分块的方法
我在这里不对这个页面的内容过多介绍, 感兴趣的可以自己去了解一下, 我主要是对它代码使用的方法进行一个总结
作者使用的类是

public class BlockSearch {private int[] index;  //索引表private ArrayList[] list; //存放每个块的元素
}

它首先建立了一个索引表

int[] index = { 10, 20, 30 };

这个索引表刚开始看会感觉有点懵, 不知道它是干什么的, 其实这个索引表就是原作者为这个块划分的最大元素, 它自己定义了三个块, 每个块的最大元素由自己决定, 然后不断向里面添加元素

        blockSearch.insert(1);blockSearch.insert(12);blockSearch.insert(22);blockSearch.insert(9);blockSearch.insert(18);blockSearch.insert(23);……………………

添加的元素通过二分搜索法确定这个元素所属的块

    private int binarySearch(int data) {int start = 0;int end = index.length;int mid = -1;while (start <= end) {mid = (start + end) / 2;if (index[mid] > data) {end = mid - 1;} else {// 如果相等,也插入在后面start = mid + 1;}}return start;}

举个例子:如果大于 10 小于 20 就属于第二个块, 返回 1, 然后向 list[1]里添加元素
通过这样的一个巧妙方法, 就实现了这个分块
不过这种分块方式也有自己的缺点, 就是这个大小你要自己调整, 同时块的数量也要自己去定义.
不过我感觉这个真的是已经很好了. 感觉很适合新手去理解这个分块搜索算法

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

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

相关文章

Webpack 热更新原理

什么是热更新 模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新所有类型的模块&#xff0c;而无需完全刷新 一般的刷新我们分两种&#xff1a; 一种是页面刷新&#xff0c;不保留页面状态&#xff0c;就是简单粗暴&#xf…

python装13的一些写法

一些当你离职后&#xff0c;让老板觉拍大腿的代码 1. any(** in ** for ** in **) 判断某个集合元素&#xff0c;是否包含某个/某些元素 代码&#xff1a; if __name__ __main__:# 判断 list1 中是否包含某个/某些元素list1 [1,2,3,4]a any(x in [5,4] for x in list1) 输…

基于微信小程序的音乐播放器设计与实现(源码+lw+部署文档+讲解等)

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…

RocketMQ 源码分析——Producer

文章目录 消息发送代码实现消息发送者启动流程检查配置获得MQ客户端实例启动实例定时任务 Producer 消息发送流程选择队列默认选择队列策略故障延迟机制策略*两种策略的选择 技术亮点:ThreadLocal 消息发送代码实现 下面是一个生产者发送消息的demo&#xff08;同步发送&#…

Unity丨移动相机朝向目标并确定目标在摄像机可视范围内丨摄像机注释模型丨摄像机移动丨不同尺寸模型优化丨

文章目录 问题描述功能展示技术细节小结 问题描述 本文提供的功能是摄像机朝向目标移动&#xff0c;并确定整个目标出现在摄像机视角内&#xff0c;针对不同尺寸的模型优化。 功能展示 提示&#xff1a;这里可以添加技术名词解释 技术细节 直接上代码 using UnityEngine;…

【Linux】【网络】传输层协议:UDP

文章目录 UDP 协议1. 面向数据报2. UDP 协议端格式3. UDP 的封装和解包4. UDP 的缓冲区 UDP 协议 UDP传输的过程类似于寄信。 无连接&#xff1a;知道对端的IP和端口号就直接进行传输&#xff0c;不需要建立连接。不可靠&#xff1a;没有确认机制&#xff0c;没有重传机制&am…

基于微信小程序的超市售货管理平台设计与实现(源码+lw+部署文档+讲解等)

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…

面向面试知识--MySQL数据库与索引

面向面试知识–MySQL数据库与索引 优化难点与面试点 什么是MySQL索引&#xff1f; 索引的MySQL官方定义&#xff1a;索引是帮助MySQL快速获取数据的数据结构。 动力节点原文&#xff1a; MysQL官方对于索引的定义:索引是帮助MySQL高效获取数据的数据结构。 MysQL在存储数据之…

【Unity实战】从零手戳一个库存背包系统

文章目录 前言素材开始一、绘制背包UI二、背包开启关闭三、初始化背包网格四、 添加物品五、 拖拽交换功能物品六、 物品拆分七、 物品堆叠八、 拖拽还原九、 引入字典存储数据十、 拾取物品十一、 丢弃物品 最终效果源码完结 前言 库存背包系统是大多数游戏的关键部分&#x…

python项目2to3方案预研

目录 官方工具2to3工具安装参数解释基本使用工具缺陷 future工具安装参数解释基本使用工具缺陷 python-modernize工具安装参数解释基本使用工具缺陷 pyupgrade工具安装参数解释基本使用工具缺陷 对比 官方工具2to3 2to3 是Python官方提供的用于将Python 2代码转换为Python 3代…

解决qml编译时出现错误ninja: build stopped: subcommand failed.

qml编译时出现错误ninja: build stopped: subcommand failed. 如下图&#xff1a; 解决这个编译错误其实很简单&#xff0c;我把Window写错了&#xff0c;写成了window, 如果有类似的报错&#xff0c;可以检查一下qml代码是否有问题。当然在Qt Creator里也没有错误提示&#x…

Canal实现Mysql数据同步至Redis、Elasticsearch

文章目录 1.Canal简介1.1 MySQL主备复制原理1.2 canal工作原理 2.开启MySQL Binlog3.安装Canal3.1 下载Canal3.2 修改配置文件3.3 启动和关闭 4.SpringCloud集成Canal4.1 Canal数据结构![在这里插入图片描述](https://img-blog.csdnimg.cn/c64b40c2231a4ea39a95aac81d771bd1.pn…

重装系统(配置环境)

这里写目录标题 0.重装系统1.python1.1 anaconda1.2 pycharm1.3 深度学习环境配置 2.java2.1.安装JDK2.2.配置JDK环境变量2.3IDEA2.4 Maven 3.大数据3.1 虚拟机3.2 Hadoop平台3.3 存储3.4 采集3.5 计算3.6 查询3.7 可视化 0.重装系统 // An highlighted block var foo bar;1.…

【性能优化下】组织结构同步优化二,全量同步/增量同步,断点续传实现方式

看到这一篇文章的 xdm &#xff0c;应该对组织结构同步有一些想法了吧&#xff0c;如果没有&#xff0c;可以看前面两篇文章&#xff0c;可以通过如下地址查看一下&#xff1a; 【性能优化上】第三方组织结构同步优化一&#xff0c;你 get 到了吗&#xff1f; 坑爹&#xff0c…

UE5读取json文件

一、下载插件 在工程中启用 二、定义读取外部json文件的函数&#xff0c;参考我之前的文章 ue5读取外部文件_艺菲的博客-CSDN博客 三、读取文件并解析为json对象 这里Load Text就是自己定义的函数&#xff0c;ResourceBundle为一个字符串常量&#xff0c;通常是读取的文件夹…

数据预处理方式合集

删除空行 #del all None value data_all.dropna(axis1, howall, inplaceTrue) 删除空列 #del all None value data_all.dropna(axis0, howall, inplaceTrue) 缺失值处理 观测缺失值 观测数据缺失值有一个比较好用的工具包——missingno&#xff0c;直接传入DataFrame&…

【Html】用CSS定义咖啡 - 咖啡配料展示

显示效果 代码 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>CodePen - For The Love Of Coffee</title><link rel"stylesheet" href"./style.css">&l…

Jenkins结合Gitlab,实现镜像构建及推送

docker-compose jenkins的docker-compose目录为为/home/jenkins&#xff0c;这个后面写脚本的时候需要对应上 version: 3 services:docker_jenkins:restart: alwaysimage: jenkins/jenkins:ltscontainer_name: docker_jenkinsprivileged: true ports:- 8080:8080- 50000:5000…

MyBatis基础之执行SQL

文章目录 执行 SQL 语句1. 增删改操作insert 元素insert 过程中的主键回填delete 元素 和 update 元素 2. getMapper 方法3. 查操作select 元素select 与 聚合函数 4. 传递多个参数使用 Map 传递多参数使用 JavaBean 传递多参使用注解方式传递多参数 执行 SQL 语句 Mapper 是 …

(2) Java 8 实战第二版——补充 收集数据、并行数据处理能力与性能

第6章 用Collectors类创建和使用收集器将数据流归约为一个值汇总&#xff1a;归约的特殊情况数据分组和分区开发你的自定义收集器 对一个交易列表按货币分组&#xff0c;获得该货币的所有交易额总和&#xff08;返回一个Map<Currency, Integer>&#xff09;。将交易列表…