【数据结构与算法】顺序查找、折半查找、分块查找

文章目录

  • 顺序查找
    • 实现
    • 对有序表的顺序查找
  • 二分查找(折半查找)
    • 实现
    • 二分查找判定树
  • 分块查找(索引顺序查找)
    • 最理想的分块情况

顺序查找

顺序查找,又叫线性查找。适用于线性表。它的核心思路是从线性表的一端开始,逐个检查关键字是否满足给定条件。若满足条件,则返回下标。若已经查找到了线性表的另一端,但还没有找到符合给定条件的元素,则返回查找失败。

简述就是,从头到尾扫一遍,有要找的元素就返回下标,没有就返回没有

实现

// C++struct List
{int len;int *items;
};int find(List &list, int aim){for(int i = 0; i< list.len; i++){if(aim == list.items[i]) return i;}return -1;
}

对于顺序查找来说,它的执行时间与线性表的长度 n 有关,时间复杂度为 O(n),空间复杂度为 O(1)。

假设使用顺序查找,查找元素在长度为 n 线性表中的位序为 i。那么找到这个元素需要进行 n - i + 1 次关键字的比较。即 C i = n − i + 1 C_i=n-i+1 Ci=ni+1

那么查找成功时,顺序查找的平均查找长度为 A S L = ∑ i = 1 n P i C i = ∑ i = 1 n P i ( n − i + 1 ) ASL=\sum_{i=1}^nP_iC_i=\sum_{i=1}^nP_i(n-i+1) ASL=i=1nPiCi=i=1nPi(ni+1)

若每个元素查找的概率 P i P_i Pi相同,即 P i = 1 / n P_i=1/n Pi=1/n时,有 A S L = ( n + 1 ) / 2 ASL=(n+1)/2 ASL=(n+1)/2

查找不成功时,平均查找长度为 n + 1。

对有序表的顺序查找

如果一个线性表是有序的,那么我们就可以通过比较来提前终止查找,而不是一定要从头到尾扫一遍线性表。

例如:

  • 如果查找元素小于两端元素或大于两端元素,那么我们可以直接返回失败。因为查找元素在线性表元素区间之外。
  • 在查找的过程中,找到了一个比待查找元素大的元素(按从小到大到的顺序遍历)或找到了一个比待查找元素小的元素(按从大到小的顺序遍历),也可以直接返回。

二分查找(折半查找)

二分查找是在对有序表的顺序查找上进行了扩展,但是只适用于适用顺序存储结构的线性表。因为链式结构的线性表无法在 O(1)的时间内读取到元素。

二分查找的核心思路是,不断地划分区间,直至找到元素或区间不可再划分。

例如:

假设我们在有序顺序表 1 3 5 7 9 11 13 15 中查找元素 3。

那么第一次,判断中位数与关键字的大小,中位数为 7(共有 8 个元素,元素下标为 0 到 7,因为计算机中两个整形数相除还是整形数,可能会丢失精度,所以中位数的下标为 ( 0 + 7 ) / 2 = 3 (0+7)/2=3 (0+7)/2=3,3 号位上的元素为 7),3 比 7 小,所以在下标为[0, 3)这个区间内查找,即在[0,2]区间内查找。

第二次,判断中位数与关键字的大小,中位数的位序为 ( 0 + 2 ) / 2 = 1 (0+2)/2=1 (0+2)/2=1,1 位序上的数为 3,等于查找元素。直接返回位序 1。

实现

int binary_search(List &list, int aim)
{int left = 0, right = list.len - 1; // 初始的左右区间int mid;                            // 中位数while (left <= right){mid = (left + right) >> 1; // 右移一位,等于(left + right)/2if (list.items[mid] == aim)return mid;else if (list.items[mid] > mid)right = mid - 1;elseleft = mid + 1;}
}

如果使用的是 C++且不想自己手写二分,那么可以直接用 C++标准库中提供的二分函数。(对于考研人来说还是不要用了,因为不能保证改卷老师知道 C++标准库里有二分函数)

#include <algorithm>int binary_search(List &list, int aim)
{int index = std::lower_bound(list.items, list.items + list.len, aim) - list.items;if(list.items[index] == aim) return index;else return -1;
}

二分查找判定树

二分查找的过程可以用树来表示,这个树称为判定树。

例如:

假设我们在有序顺序表 1 3 5 7 9 11 13 15 中查找元素,那么它的判定树是这样的

1
3
5
7
9
11
13
15

这里有个空结点是因为 markdown 画不出来二叉树的形状,因此这里用个空站位,实际上是没有这个结点的

通过判定树,我们可以直观地了解到,二分查找的比较次数与判定树的高度 h 有关。

由于二分查找的判定树是一棵接近满二叉树的平衡二叉树。结点个数为 n 的满二叉树的树高为 l o g 2 ( n + 1 ) log_2(n+1) log2(n+1)。所以折半查找的时间复杂度近似为 O ( l o g 2 n ) O(log_2n) O(log2n)

分块查找(索引顺序查找)

分块查找结合了顺序查找和二分查找。它的核心是划分区间、添加索引。

当然,如果分区和添加索引是在查找开始时进行的,那么时间开销巨大,因此,分块查找实际上是对一种类似于跳表的数据结构进行的查找。

分块查找要求:

  • 索引的值为每个块中的最大元素,索引指向块中的第一个元素。
  • 索引的值必须是有序的,块内元素的值可以是无序的。

分块查找的过程分为两部:

  1. 使用顺序查找或二分查找在索引表中查找记录所在的块。
  2. 在块内进行顺序查找、

例如:现在有待查找序列 24 , 21 , 6 , 11 , 8 , 22 , 32 , 31 , 54 , 72 , 61 , 78 , 88 , 83 {24,21,6,11,8,22,32,31,54,72,61,78,88,83} 24,21,6,11,8,22,32,31,54,72,61,78,88,83

我们拟建立分块:

区间块内元素索引的值索引
[1,6]24, 21, 6, 11, 8, 22241
[7, 9]32, 31, 54547
[10, 12]72, 61, 787810
[13, 14]88, 838813

在使用分块查找的时候先在索引列表里找到符合条件的区间,再到对应的区间里去找有没有符合条件的值。

假设我们要找32这个元素,那么从索引里找,发现32在 (24, 54]这个区间内。

所以,按照索引,从第7号元素开始执行顺序查找,第7号元素就是32,找到了返回下标。


在现实中,直接使用分块查找算法的情况并不多。但是分块的思想使用得非常多。例如大数据处理的时候,我们常常会将数据按照时间分块来提高处理速度。

最理想的分块情况

将长度为n的查找表均分为b块,每块有s个记录。设分块查询查找索引的平均查找长度为 L i L_i Li,块内查找的平均查找长度为 L s L_s Ls

在等概率的情况下,若在块内和块间均采用顺序查找,则平均查找长度

A S L = L i + L s = ( b + 1 ) / 2 + ( s + 1 ) / 2 = ( s 2 + 2 s + n ) / 2 s = ( s + n / s + 2 ) / 2 ASL = L_i + L_s = (b+1)/2 + (s+1)/2 = (s^2+2s+n)/2s = (s + n/s + 2)/2 ASL=Li+Ls=(b+1)/2+(s+1)/2=(s2+2s+n)/2s=(s+n/s+2)/2

由均值不等式可知,在 s = n s=\sqrt{n} s=n 时, ( s + n / s + 2 ) / 2 (s + n/s + 2)/2 (s+n/s+2)/2 最小。

所以,理想状况下,每个分块内的元素个数应为 s = n s=\sqrt{n} s=n

全篇结束,感谢阅读!

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

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

相关文章

Unity的ScrollView滚动视图复用

发现问题 在游戏开发中有一个常见的需求&#xff0c;就是需要在屏幕显示多个&#xff08;多达上百&#xff09;显示item&#xff0c;然后用户用手指滚动视图可以选择需要查看的item。 现在的情况是在100个data的时候&#xff0c;Unity引擎是直接创建出对应的100个显示item。 …

13个行业数据分析指标体系如何建设100问

提供针对13个行业的数据分析指标体系的全面指南&#xff0c;涵盖各行业的关键指标和分析维度&#xff0c;帮助读者深入了解和构建有效的指标体系。以下是文章的主要内容&#xff1a; 电商行业数据指标体系&#xff1a;包括客户价值、商品、网站流量、整体运营、市场营销活动、市…

若依-前后端分离项目学习

第一天&#xff08;6.24&#xff09; 具体参考视频 b站 楠哥教你学Java 【【开源项目学习】若依前后端分离版&#xff0c;通俗易懂&#xff0c;快速上手】 https://www.bilibili.com/video/BV1HT4y1d7oA/?share_sourcecopy_web&vd_sourcecd9334b72b49da3614a4257…

C++如何实现继承和多态

继承 继承是指一个类&#xff08;子类&#xff09;从另一个类&#xff08;父类&#xff09;继承属性和方法。C支持单继承和多继承。 #include <iostream>// 基类&#xff08;父类&#xff09; class Animal { public:// 基类中的方法void eat() {std::cout << &q…

Elasticsearch Scroll 报错entity content is too long

2024-06-24 15:22:01:568 ERROR [task-31] (ScrollFetcherProduceAction.java:129) 访问ES出错org.apache.http.ContentTooLongException: entity content is too long [112750110] for the configured buffer limit [104857600]at org.elasticsearch.client.HeapBufferedAsync…

一下出来4个面试官,这是要舌战群儒啊

老张昨天下午请假了&#xff0c;我猜他就是面试去了。果不其然&#xff0c;今天来了&#xff0c;我问老张&#xff1a;昨天面试如何&#xff1f;老张很惊讶的问&#xff1a;你怎么知道我面试去了&#xff1f;我迫不及待的说&#xff1a;赶紧说说昨天面试的场景&#xff0c;给我…

智慧安防/边缘计算EasyCVR视频汇聚网关:EasySearch无法探测到服务器如何处理?

安防监控EasyCVR智能边缘网关/视频汇聚网关/视频网关属于软硬一体的边缘计算硬件&#xff0c;可提供多协议&#xff08;RTSP/RTMP/国标GB28181/GAT1400/海康Ehome/大华/海康/宇视等SDK&#xff09;的设备接入、音视频采集、视频转码、处理、分发等服务&#xff0c;系统具备实时…

Redis-事务-watch-unwatch

文章目录 1、监视key2、提交事务 1、监视key 打开两个窗口&#xff0c;第一个窗口先监视key&#xff0c;然后开始事务&#xff0c;然后再打开第二个窗口&#xff0c;修改balance为0 2、提交事务 此时事务被打断

playwright vscode 插件源码解析

Playwright vscode插件主要功能 Playwright是微软开发的一款主要用于UI自动化测试的工具&#xff0c;在vscode中上安装playwright vscode插件&#xff0c;可以运行&#xff0c;录制UI自动化测试。 playwright vscode插件主要包括两块功能&#xff0c;功能一是在Test Explorer中…

探索 Java 死锁:常见原因与解决方案

什么是死锁&#xff1f; 死锁是一种特殊的情况&#xff0c;发生在两个或多个线程彼此等待对方持有的资源&#xff0c;从而陷入无限等待的状态。具体而言&#xff0c;死锁通常涉及以下四个必要条件&#xff1a; 互斥条件&#xff1a;至少有一个资源被一个线程独占。持有并等待…

解决Microsoft Edge浏览器无法使用英文翻译功能

一、问题描述 原来我们使用的Microsoft Edge浏览器是可以对英文界面选择翻译为中文的&#xff1b;但是最近该浏览器更新过后右上角的翻译图标找不到了&#xff0c;无法翻译英文界面内容。 二、解决方法 2.1、打开浏览器的设置界面 2.2、选择语言 2.3、将首选语言下除中文外的…

【2024德国工作】蓝卡攻略:人在中国,怎么去德国工作?

德国工作签证解析 外国人只要拥有符合德国劳动法的劳动合同&#xff0c;工资符合当地标准&#xff08;非紧缺专业&#xff0c;税前工资一般需达到49600欧元&#xff09;&#xff0c;并且具备一定的外语能力&#xff0c;就可以申请德国境内工作签证&#xff01;不申请者还需要有…

【electron 5】electron将获取的Uint8Array转为中文

使用protobufjs&#xff1a; 安装&#xff1a; yarn add global protobufjs yarn add global protobufjs-cli// 将项目中的*.proto文件编译成json文件 npx pbjs -t json electron/main/proto/*.proto > electron/main/proto/proto.json可以在src/proto目录下生成一个proto.…

国内Mac安装Homebrew方法

文章目录 前言步骤 参考&#xff1a;https://blog.csdn.net/itwangyang520/article/details/134125435 前言 今天尝试下载git&#xff0c;官方给的建议是使用Homebrew下载&#xff0c;但发现新电脑里没有&#xff0c;于是尝试Homebrew下载&#xff0c;但发现Homebrew不存在&am…

黑曼巴精神不死!Mamba 2 出世,性能狂飙8倍

年前&#xff0c;Mamba 被 ICLR 拒稿的消息曾引起轩然大波。然而&#xff0c;Mamba作者在6月初又发布了 Mamba 2 架构&#xff0c;这次&#xff0c;Mamba-2 顺利地拿下 ICML。就连 Nvidia 都被吸引&#xff0c;都用它重新训练了GPT3模型。 Transformer vs Mamba vs Mamba2 : 比…

一文读懂交换机MAC地址表:五大关键点,图解21步

HCIA 新班开课了华为HCIA课程介绍苏州面授班 | 全国直播班循环开班&#xff0c;免费重学前言 什么是MAC地址表?MAC地址表有什么作用&#xff1f;MAC地址表里面包含了哪些要素&#xff1f;今天带你好好唠唠。 我们以一个案例为例&#xff1a; 如上图&#xff1a;PC1和PC2通…

C#——堆栈和队列详情

堆栈和队列 堆栈 堆栈类表示一个后进先出的对象集合&#xff0c;当需要对项目进行后进先出的访问时&#xff0c;则可以使用堆栈。向堆栈中添加元素称为推入元素&#xff0c;从堆栈中移除元素称为弹出元素。 关键字: Stack stack常用属性 : 属性 描述Count获取堆栈中包含的…

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值&#xff1a;简单的数据即基础数据类型&#xff0c;按值访问。 引用值&#xff1a;由多个值构成的对象即复杂数据类型&#xff0c;按引用访问。 动态属性 对于引用值而言&#xff0c;可以随时添加、修改和删除其属性和方法。 let person new Object(); p…

昇思25天学习打卡营第1天|认识MindSpore

MindSpore 基本介绍 昇思MindSpore是一个全场景深度学习框架&#xff0c;旨在实现易开发、高效执行、全场景统一部署三大目标。 易开发&#xff1a;API友好、调试难度低高效执行&#xff1a;包括计算效率、数据预处理效率和分布式训练效率全场景&#xff1a;框架同时支持云、…

LabVIEW操作系列

目的&#xff1a;初学LabVIEW&#xff0c;做记录 文章目录 前言一、LabVIEW操作界面1.1 新建vi1.2 控件1.3 加法案例 二、编程特点2.1 特点2.2 实现按顺序执行 三、程序结构3.1 平铺式顺序结构3.2 循环结构3.2.1 For循环3.2.2 While循环3.2.3 中途停止For循环3.2.4 中途停止Whi…