当前位置: 首页 > article >正文

分块查找详解

1、原理

分块查找(Block Search)是一种结合顺序查找与索引查找的算法,适用于数据分块存储且块内无序但块间有序的场景。它通过“分块-建立索引-逐层定位”提高查找效率。

分块查找的核心思想

  1. 数据分块
    将数据集划分为若干块(子表),每个块内的元素可以无序,但块与块之间需满足有序性(例如:第1块的最大值 ≤ 第2块的最小值)。
  2. 建立索引表
    记录每块的最大值(或区间)和对应块的起始-结束索引,索引表本身有序。
  3. 两步查找
    • 定位块:先在索引表中确定目标值所在的块(顺序查找或二分查找)。
    • 块内查找:在对应的块内进行顺序查找。

分块查找的实现步骤

1. 数据分块与索引表构建

假设数组为 [12, 8, 5, 20, 25, 15, 18, 28, 32, 10],按最大块值分块:

  • 分块示例

    块1: [12, 8, 5] → 最大值 12

    块2: [20, 25, 15] → 最大值 25

    块3: [18, 28, 32, 10] → 最大值 32

  • 索引表

    块最大值

    起始索引

    结束索引

    12

    0

    2

    25

    3

    5

    32

    6

    9

2. 查找流程

以查找 28 为例:

  1. 定位块:遍历索引表,找到第一个块最大值 ≥ 28 的块(块3)。
  2. 块内查找:在块3的索引范围(6~9)内遍历,找到 28

2、性能分析

  • 时间复杂度:
    • 定位块:假设块数为 m,时间复杂度为 ( O(m) )(顺序查找)或 ( O(\log m) )(索引表有序时用二分查找)。
    • 块内查找:块内最大元素数为 s,时间复杂度为 O(s)。
    • 总时间复杂度:O(m+s) 或 O(logm+s)。
  • 优化方向

    • 索引表二分查找:若索引表有序,可将定位块的时间优化为对数级。
    • 均匀分块:尽量保证每块元素数量均衡,避免极端情况(如一个块包含绝大多数元素)。

3、适用场景

  • 数据动态增减,插入/删除操作频繁(块内无需完全有序)。
  • 数据量较大且无法完全装入内存时,分块存储在磁盘中。

4、代码实现

Python:

def block_search(arr, block_ranges, key):# 1. 定位块:顺序查找索引表block_idx = -1for i, (max_val, start, end) in enumerate(block_ranges):if key <= max_val:block_idx = ibreakif block_idx == -1:return -1# 2. 在块内顺序查找start, end = block_ranges[block_idx][1], block_ranges[block_idx][2]for i in range(start, end + 1):if arr[i] == key:return ireturn -1# 示例数据与索引表
arr = [12, 8, 5, 20, 25, 15, 18, 28, 32, 10]
block_ranges = [(12, 0, 2),   # 块1:最大值12,索引0~2(25, 3, 5),   # 块2:最大值25,索引3~5(32, 6, 9)    # 块3:最大值32,索引6~9
]# 查找测试
print(block_search(arr, block_ranges, 28))  # 输出:7(索引位置)
print(block_search(arr, block_ranges, 10))  # 输出:9
print(block_search(arr, block_ranges, 99))  # 输出:-1(未找到)

golang(定义 Block 结构体/类,包含最大值、起始索引和结束索引):

package mainimport "fmt"// 定义块索引结构
type Block struct {MaxVal   intStartIdx intEndIdx   int
}// 分块查找函数
func blockSearch(arr []int, blocks []Block, key int) int {// 1. 定位块:顺序查找索引表blockIndex := -1for i, block := range blocks {if key <= block.MaxVal {blockIndex = ibreak}}if blockIndex == -1 {return -1}// 2. 块内顺序查找block := blocks[blockIndex]start, end := block.StartIdx, block.EndIdxfor i := start; i <= end; i++ {if arr[i] == key {return i}}return -1
}func main() {// 示例数据与索引表arr := []int{12, 8, 5, 20, 25, 15, 18, 28, 32, 10}blocks := []Block{{MaxVal: 12, StartIdx: 0, EndIdx: 2}, // 块1{MaxVal: 25, StartIdx: 3, EndIdx: 5}, // 块2{MaxVal: 32, StartIdx: 6, EndIdx: 9}, // 块3}// 测试查找fmt.Println(blockSearch(arr, blocks, 28)) // 输出:7fmt.Println(blockSearch(arr, blocks, 10)) // 输出:9fmt.Println(blockSearch(arr, blocks, 99)) // 输出:-1
}

php(使用二维数组表示索引表):

<?php
class BlockSearch {// 分块查找函数public static function search($arr, $blockRanges, $key) {// 1. 定位块:顺序查找索引表$blockIndex = -1;foreach ($blockRanges as $index => $block) {list($maxVal, $start, $end) = $block;if ($key <= $maxVal) {$blockIndex = $index;break;}}if ($blockIndex == -1) return -1;// 2. 块内顺序查找list($maxVal, $start, $end) = $blockRanges[$blockIndex];for ($i = $start; $i <= $end; $i++) {if ($arr[$i] == $key) {return $i;}}return -1;}
}// 示例数据与索引表
$arr = [12, 8, 5, 20, 25, 15, 18, 28, 32, 10];
$blockRanges = [[12, 0, 2],   // 块1:最大值12,索引0~2[25, 3, 5],   // 块2:最大值25,索引3~5[32, 6, 9]    // 块3:最大值32,索引6~9
];// 测试查找
echo BlockSearch::search($arr, $blockRanges, 28) . "\n"; // 输出:7
echo BlockSearch::search($arr, $blockRanges, 10) . "\n"; // 输出:9
echo BlockSearch::search($arr, $blockRanges, 99) . "\n"; // 输出:-1
?>

java(定义 Block 结构体/类,包含最大值、起始索引和结束索引):

import java.util.ArrayList;
import java.util.List;class Block {int maxVal;int startIdx;int endIdx;Block(int maxVal, int startIdx, int endIdx) {this.maxVal = maxVal;this.startIdx = startIdx;this.endIdx = endIdx;}
}public class BlockSearch {public static int search(List<Integer> arr, List<Block> blocks, int key) {// 1. 定位块:顺序查找索引表int blockIndex = -1;for (int i = 0; i < blocks.size(); i++) {Block block = blocks.get(i);if (key <= block.maxVal) {blockIndex = i;break;}}if (blockIndex == -1) return -1;// 2. 块内顺序查找Block targetBlock = blocks.get(blockIndex);int start = targetBlock.startIdx;int end = targetBlock.endIdx;for (int i = start; i <= end; i++) {if (arr.get(i) == key) {return i;}}return -1;}public static void main(String[] args) {// 示例数据与索引表List<Integer> arr = new ArrayList<>(List.of(12, 8, 5, 20, 25, 15, 18, 28, 32, 10));List<Block> blocks = new ArrayList<>();blocks.add(new Block(12, 0, 2));   // 块1blocks.add(new Block(25, 3, 5));   // 块2blocks.add(new Block(32, 6, 9));   // 块3// 测试查找System.out.println(search(arr, blocks, 28)); // 输出:7System.out.println(search(arr, blocks, 10)); // 输出:9System.out.println(search(arr, blocks, 99)); // 输出:-1}
}

5、与其他查找算法对比

算法

前提条件

时间复杂度

适用场景

顺序查找

O(n)

小规模无序数据

二分查找

数据有序

O(logn)

静态有序数据

分块查找

块间有序,块内无序

O(m+s)

动态数据,分块存储

哈希查找

哈希函数设计合理

O(1)

快速精确查找,无范围查询

 

相关文章:

分块查找详解

1、原理 分块查找&#xff08;Block Search&#xff09;是一种结合顺序查找与索引查找的算法&#xff0c;适用于数据分块存储且块内无序但块间有序的场景。它通过“分块-建立索引-逐层定位”提高查找效率。 分块查找的核心思想 数据分块 将数据集划分为若干块&#xff08;子…...

leetcode hot100刷题日记——21.不同路径

和20题一样的思路link 题解&#xff1a; class Solution { public:int dfs(int i,int j,vector<vector<int>>&memo){//超过了边界&#xff0c;return 0if(i<0||j<0){return 0;}//从&#xff08;0&#xff0c;0&#xff09;到&#xff08;0&#xff0c;0…...

Elasticsearch 如何实现跨数据中心的数据同步?

实战场景&#xff1a; 双数据中心容灾&#xff0c;要求RPO<5分钟&#xff0c;RTO<30分钟 ‌RPO&#xff08;Recovery Point Objective&#xff09;‌&#xff1a; RPO指的是灾难发生后&#xff0c;系统能够恢复到的数据更新点的时间。简单来说&#xff0c;它衡量的是数据…...

C语言学习笔记三 --- V

文章目录 程序入门设计 --- C 语言第二周 核心语法📝2.1 C 语言笔记 | 注释的使用(让代码会“说话”)💡 **注释的作用**🔍 **注释的两种写法**⚠️ **注释的注意事项**🔧 **注释的实用场景**📌 **本节总结**:📝 2.2 C 语言笔记 | 关键字(保留字)深度解析💡 …...

通过JS模板引擎实现动态模块组件(Vite+JS+Handlebars)

1. 引言 在上一篇文章《实现一个前端动态模块组件(Vite原生JS)》中&#xff0c;笔者通过原生的JavaScript实现了一个动态的模块组件。但是这个实现并不完善&#xff0c;最大的问题就是功能逻辑并没有完全分开。比如模块的HTML&#xff1a; <div class"category-secti…...

梯度消失和梯度爆炸的原因及解决办法

梯度消失和梯度爆炸的原因是什么 问题分析 梯度消失&#xff08;Vanishing Gradient&#xff09;和梯度爆炸&#xff08;Exploding Gradient&#xff09;本质上都是在深层神经网络中反向传播过程中&#xff0c;梯度在多层传播时逐渐缩小或放大的问题&#xff0c;导致模型难以…...

欧拉定理:若 gcd(a,n)=1,则 a^φ(n)≡1(mod n)。

【欧拉定理简介】 欧拉定理&#xff1a;若 gcd(a,n)1&#xff0c;则 a^φ(n)≡1(mod n)。 &#xff08;1&#xff09;例如&#xff0c;a3&#xff0c;n10&#xff0c;gcd(3,10)1&#xff0c;φ(10)4&#xff0c;则 a^φ(n)3^481&#xff0c;81 mod 101&#xff0c;欧拉定理成立…...

fvm install 下载超时 过慢 fvm常用命令、flutter常用命令

Git 配置问题 确保 Git 使用的是 HTTPS&#xff0c;而不是 SSH。如果你有 .gitconfig&#xff0c;确保没有配置奇怪的代理&#xff1a; git config --global --get http.proxy git config --global --get https.proxy如果有代理设置且不需要&#xff0c;取消代理&#xff1a;…...

Python正则表达式:30秒精通文本处理

一、概述 1. 含义 正则表达式是一种记录文本规则的代码工具&#xff0c;用于描述字符串的结构和模式。它广泛应用于字符串的匹配、查找、替换、提取等操作。 2. 特点 语法复杂&#xff1a;符号多、规则灵活&#xff0c;可读性较差。功能强大&#xff1a;可以精确控制字符串…...

Introduction to SQL

目录 SQL特点 ​编辑 Select-From-Where Statements Meaning of Single-Relation Query Operational Semantics * In SELECT clauses Complex Conditions in WHERE Clause PATTERNS NULL Values Three-Valued Logic Multirelation Queries Aggregations NULL’s Ig…...

计算机视觉---YOLOv3

YOLOv3讲解 一、YOLOv3 核心架构与创新 YOLOv3&#xff08;2018年发布&#xff09;在YOLOv2基础上进行了全面升级&#xff0c;通过多尺度预测、更强大的骨干网络和优化的分类损失函数&#xff0c;显著提升了检测精度&#xff0c;尤其是小目标检测能力&#xff0c;同时保持了实…...

#RabbitMQ# 消息队列进阶

目录 消息可靠性 一 生产者的可靠性 1 生产者的重连 2 生产者的确认 (1 Confirm* (2 Return 二 MQ的可靠性 1 数据持久化 2 Lazy Queue* 三 消费者的可靠性 1 消费者确认机制 2 消费失败处理 3 业务幂等性 四 延迟消息 消息可靠性 在消息队列中&#xff0c;可靠性…...

React从基础入门到高级实战:React 核心技术 - React Router:路由管理

React Router&#xff1a;路由管理 在现代 Web 应用开发中&#xff0c;路由管理 是构建多页面或单页应用&#xff08;SPA&#xff09;的核心技术之一。React Router 是 React 生态中最受欢迎的路由管理库&#xff0c;它为开发者提供了强大的工具来实现页面导航、动态路由和权限…...

【深度学习】损失“三位一体”——从 Fisher 的最大似然到 Shannon 的交叉熵再到 KL 散度,并走进 PET·P-Tuning微调·知识蒸馏的实战

一页速览&#xff1a; 1912 Fisher 用最大似然把「让数据出现概率最高」变成参数学习&#xff1b; 1948 Shannon 把交叉熵解释成「最短平均编码长度」&#xff1b; 1951 Kullback-Leibler 用相对熵量化「多余信息」。 三条历史线落到今天深度学习同一个损失——交叉熵。 也…...

5 分钟速通密码学!

让我们开始第一部分&#xff1a;密码学基础 (Cryptography Basics)。 第一部分&#xff1a;密码学基础 (Cryptography Basics) 1. 什么是密码学&#xff1f; 想象一下&#xff0c;在古代战争中&#xff0c;将军需要向远方的部队传递作战指令。如果直接派人送信&#xff0c;信…...

Linux——IP协议

1. 现实意义 • IP协议&#xff1a;提供一种能力&#xff0c;把数据报从主机A跨网络送到主机B • TCP/IP协议&#xff1a;核心功能&#xff0c;把数据100%可靠的从主机A跨网络送到主机B 注&#xff1a;TCP协议负责百分百可靠&#xff0c;通过三次握手、滑动窗口、拥塞控制、延…...

Lua 脚本在 Redis 中的运用-24 (使用 Lua 脚本实现原子计数器)

实践练习:使用 Lua 脚本实现原子计数器 实现原子计数器是许多应用程序中的常见需求,例如跟踪网站访问量、限制 API 请求或管理库存。虽然 Redis 提供了 INCR 命令用于递增整数,但在复杂场景或与其他操作结合时直接使用它可能并不足够。本课程探讨了如何在 Redis 中利用 Lua…...

Linux信号量(32)

文章目录 前言一、POSIX 信号量信号量的基础知识信号量的基本操作 二、基于环形队列实现生产者消费者模型环形队列单生产单消费模型多生产多消费模型 总结 前言 加油&#xff0c;加油&#xff01;&#xff01;&#xff01; 一、POSIX 信号量 信号量的基础知识 互斥、同步 不只…...

技术视界 | 打造“有脑有身”的机器人:ABC大脑架构深度解析(上)

ABC大脑架构&#xff1a;连接大模型与物理世界的具身智能新范式 在具身智能和类人机器人技术快速发展的背景下&#xff0c;如何高效整合“大模型的认知理解能力”与“对真实物理世界的精准控制”&#xff0c;成为当前智能体系统设计中最具挑战性也是最关键的问题之一。尽管大语…...

使用堡塔和XShell

使用堡塔和XShell 一、SSH协议介绍 SSH为SecureShell的缩写&#xff0c;由IETF的网络小组(NetworkWorkingGroup)所制定;SSH为建立在应用层基础上的安全协议。SSH是较可靠&#xff0c;专为远程登录会话和其他网络服务提供安全性的协议。利用SSH协议可以有效防止远程管理过程中…...

软件项目交付阶段,验收报告记录了什么?有哪些标准要求?

软件项目交付阶段&#xff0c;验收报告扮演着至关重要的角色&#xff0c;它相当于一份详尽的“成绩单”&#xff0c;具体记录了项目完成的具体情况以及是否达到了既定的标准。 项目基本信息 该环节将展示软件项目的核心信息&#xff0c;包括项目名称、开发团队构成、项目实施…...

LightGBM的python实现及参数优化

文章目录 1. LightGBM模型参数介绍2. 核心优势3. python实现LightGBM3.1 基础实现3.1.1 Scikit-learn接口示例3.1.2 Python API示例 3.2 模型调优3.2.1 GridSearchCV简介3.2.2 LightGBM超参调优3.2.3 GridSearchCV寻优结果解读 在之前的文章 Boosting算法【AdaBoost、GBDT 、X…...

封装渐变堆叠柱状图组件附完整代码

组件功能 这是一个渐变堆叠柱状图组件&#xff0c;主要功能包括&#xff1a; 在一根柱子上同时显示高、中、低三种危险级别数据使用渐变色区分不同危险级别&#xff08;高危红色、中危橙色、低危蓝色&#xff09;悬停显示详细数据信息&#xff08;包括总量和各级别数据&#…...

分布式项目保证消息幂等性的常见策略

Hello&#xff0c;大家好&#xff0c;我是灰小猿&#xff01; 在分布式系统中&#xff0c;由于各个服务之间独立部署&#xff0c;各个服务之间依靠远程调用完成通信&#xff0c;再加上面对用户重复点击时的重复请求等情况&#xff0c;所以如何保证消息消费的幂等性是在分布式或…...

山东大学软件学院创新项目实训开发日志——第十三周

目录 1.开展prompt工程&#xff0c;创建个性化AI助理&#xff0c;能够基于身份实现不同角度和语言风格的回答。 2.对输出进行格式化&#xff0c;生成特定格式的会议计划文档。 3.学习到的新知识 本阶段我所做的工作 1.开展prompt工程&#xff0c;创建个性化AI助理&#xff…...

如何在sublime text中批量为每一行开头或者结尾添加删除指定内容

打开你的文件&#xff1a;首先&#xff0c;在 Sublime Text 中打开你想要编辑的文件&#xff0c;然后全选 行首插入&#xff1a; 选择所有行的开头&#xff1a; 使用快捷键 Ctrl Shift L&#xff08;Windows/Linux&#xff09;或 Cmd Shift L&#xff08;Mac&#xff09;&…...

Cesium 透明渐变墙 解决方案

闭合路径修复 通过增加额外点确保路径首尾相接 透明渐变效果 使用RGBA颜色模式实现从完全不透明到完全透明的平滑渐变 参数可调性 提供多个可调参数&#xff0c;轻松自定义颜色、高度和圆环尺寸 完整代码实现 <!DOCTYPE html> <html> <head><meta …...

网络原理与 TCP/IP 协议详解

一、网络通信的本质与基础概念 1.1 什么是网络通信&#xff1f; 网络通信的本质是跨设备的数据交换&#xff0c;其核心目标是让不同物理位置的设备能够共享信息。这种交换需要解决三个核心问题&#xff1a; 如何定位设备&#xff1f; → IP地址如何找到具体服务&#xff1f;…...

day022-定时任务-故障案例与发送邮件

文章目录 1. cron定时任务无法识别命令1.1 故障原因1.2 解决方法1.2.1 对命令使用绝对路径1.2.2 在脚本开头定义PATH 2. 发送邮件2.1 安装软件2.2 配置邮件信息2.3 巡检脚本与邮件发送2.3.1 巡检脚本内容2.3.2 制作时任务发送邮件 3. 调取API发送邮件3.1 编写文案脚本3.2 制作定…...

新增 git submodule 子模块

文章目录 1、基本语法2、添加子模块后的操作3、拉取带有submodule的仓库 git submodule add 是 Git 中用于将另一个 Git 仓库作为子模块添加到当前项目中的命令。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录&#xff0c;同时保持它们各自的提交历史独立。 1、基…...