【第六节】C/C++静态查找算法

目录

前言

一、搜索查找

二、查找算法

1. 线性查找(Linear Search)

2. 二分查找(Binary Search)

3. 插值查找(Interpolation Search)

4. 哈希查找(Hash Search)

5. Fibonacci查找


前言

        静态查找算法是在一个静态的数据结构(如数组或列表)中查找特定的元素。这些算法在执行查找操作时不会修改原始数据结构。以下是一些常见的静态查找算法:

顺序查找(Linear Search)
顺序查找是最简单的查找算法。它从数据结构的一端开始,逐个检查每个元素,直到找到所需的元素或到达数据结构的另一端。这种算法的时间复杂度为O(n),其中n是数据结构的长度。

二分查找(Binary Search)
二分查找是一种在有序数组中进行查找的高效算法。它首先将数组的中间元素与目标值进行比较,如果它们相等,则查找成功;如果目标值小于中间元素,则在数组的左半部分继续查找;如果目标值大于中间元素,则在数组的右半部分继续查找。这个过程递归地进行,直到找到目标值或搜索区间为空。二分查找的时间复杂度为O(log n)。

插值查找(Interpolation Search)
插值查找是对二分查找的一种改进,它根据元素的分布情况来调整搜索区间的大小,而不是每次都取中间元素。这种方法在数据分布均匀的情况下比二分查找更高效。

斐波那契查找(Fibonacci Search)
斐波那契查找也是基于二分查找的一种优化算法。它利用了斐波那契数列的性质来划分搜索区间。这种算法适用于均匀分布的数据集,其性能在某些情况下可能优于二分查找。

        在选择静态查找算法时,需要考虑数据的特点、规模以及查找的频繁程度。例如,如果数据是静态的且已经排好序,二分查找通常是最有效的选择。如果数据分布不均匀或数据量很大,插值查找或斐波那契查找可能更合适。然而,如果数据量较小或查找不频繁,顺序查找由于实现简单,可能也是一个可行的选择。

一、搜索查找

在数据集合之中,搜索具有特定关键字的结点通常可以根据不同的搜索场景和数据结构分为多种类型。

静态搜索表

  • 定义:当集合中的结点总数是固定的,或者变化非常少时,我们称之为静态搜索表。
  • 数据结构:静态搜索表可以是无序的,或者组织成有序表(如数组或有序链表)。
  • 搜索策略:对于无序的静态搜索表,通常使用线性搜索;对于有序的静态搜索表,则可以使用二分搜索或其他高效的搜索算法。

动态搜索表

  • 定义:当集合中的结点总数经常发生变化时,我们称之为动态搜索表。
  • 数据结构:动态搜索表通常组织成树形结构,如二叉搜索树(BST)、平衡二叉搜索树(如AVL树、红黑树)或B树/B+树等,以适应频繁的插入和删除操作。
  • 搜索策略:在树形结构中,搜索通常从根节点开始,根据关键字与节点值的比较结果决定向左子树还是右子树进行搜索,直到找到目标节点或确定不存在为止。

在内存中进行的搜索

  • 重点:由于内存访问速度相对较快,搜索的主要目标是减少比较或查找的次数,以提高搜索效率。
  • 评价标准:平均搜索长度(ASL),即从搜索开始到找到目标节点所需比较的平均次数。

在外存中进行的搜索

  • 重点:由于外存(如磁盘)的访问速度远慢于内存,搜索的主要目标是减少访问外存的次数,以降低I/O开销。
  • 数据结构:常用的数据结构包括索引文件、倒排索引等,它们通过特定的组织方式将数据与存储位置相关联,以便快速定位数据。
  • 评价标准:读盘次数,即从外存中读取数据的次数。由于每次读盘操作都涉及到I/O等待时间,因此减少读盘次数是优化外存搜索性能的关键。

二、查找算法

        静态搜索结果采用静态向量(或数组)。

        查找算法是计算机科学中一个基础且重要的主题,广泛应用于数据处理和信息检索。本文将介绍几种常见的查找算法,并使用C/C++语言展示它们的实现。

1. 线性查找(Linear Search)

        线性查找是最简单的查找算法,适用于未排序的数据集。它逐一检查数据集中的每个元素,直到找到目标值或遍历完所有元素。

#include <stdio.h>int linearSearch(int arr[], int n, int x) {for (int i = 0; i < n; i++) {if (arr[i] == x) {return i; // 返回找到的元素的索引}}return -1; // 如果没有找到,返回-1
}int main() {int arr[] = {2, 3, 4, 10, 40};int n = sizeof(arr) / sizeof(arr[0]);int x = 10;int result = linearSearch(arr, n, x);(result == -1) ? printf("元素不在数组中") : printf("元素在索引 %d", result);return 0;
}

2. 二分查找(Binary Search)

        二分查找是一种高效的查找算法,但要求数据集必须是有序的。它通过反复将查找范围减半来快速定位目标值。

#include <stdio.h>// 二分查找算法
// arr[] 是一个升序排列的数组
// l 是要搜索的范围的左端点
// r 是要搜索的范围的右端点
// x 是要搜索的元素
int binarySearch(int arr[], int l, int r, int x) {while (l <= r) {// 防止 (l + r) 的和超过 int 的最大值int m = l + (r - l) / 2;// 检查中间元素if (arr[m] == x) {return m; // 元素找到,返回索引}// 如果中间元素小于x,忽略左半边if (arr[m] < x) {l = m + 1;} // 如果中间元素大于x,忽略右半边else {r = m - 1;}}return -1; // 元素不在数组中,返回-1
}int main() {int arr[] = {2, 3, 4, 10, 40}; // 输入数组int n = sizeof(arr) / sizeof(arr[0]); // 计算数组中的元素个数int x = 10; // 要查找的元素int result = binarySearch(arr, 0, n - 1, x); // 调用二分查找算法// 输出结果if (result == -1) {printf("元素不在数组中");} else {printf("元素在索引 %d", result);}return 0;
}

3. 插值查找(Interpolation Search)

        插值查找是二分查找的改进版本,适用于均匀分布的有序数据集。它通过估计目标值的位置来减少查找范围。

#include <stdio.h>// 插值查找算法
// arr[] 是一个升序排列的数组
// n 是数组中元素的数量
// x 是要搜索的元素
int interpolationSearch(int arr[], int n, int x) {int lo = 0, hi = (n - 1);// 当待搜索的区段有效,并且目标值在[lo, hi]区间内时,执行搜索while (lo <= hi && x >= arr[lo] && x <= arr[hi]) {// 如果lo和hi相等,只需检查lo位置的元素if (lo == hi) {if (arr[lo] == x) return lo; // 找到目标值return -1; // 没有找到目标值}// 计算可能的位置pos,使用插值公式int pos = lo + (((double)(hi - lo) / (arr[hi] - arr[lo])) * (x - arr[lo]));// 如果找到了目标值,返回其索引if (arr[pos] == x) {return pos;}// 如果目标值大于pos位置的元素,调整loif (arr[pos] < x) {lo = pos + 1;}// 如果目标值小于pos位置的元素,调整hielse {hi = pos - 1;}}return -1; // 如果没有找到目标值,返回-1
}int main() {int arr[] = {2, 3, 4, 10, 40}; // 输入数组int n = sizeof(arr) / sizeof(arr[0]); // 计算数组中的元素个数int x = 10; // 要查找的元素int result = interpolationSearch(arr, n, x); // 调用插值查找算法// 输出查找结果if (result == -1) {printf("元素不在数组中");} else {printf("元素在索引 %d", result);}return 0;
}

4. 哈希查找(Hash Search)

        哈希查找利用哈希表来存储数据,通过计算键的哈希值来快速定位数据。哈希表的实现较为复杂,通常使用标准库中的哈希表数据结构。

#include <iostream>
#include <unordered_map>int main() {// 创建一个unordered_map来存储数组元素和它们的索引std::unordered_map<int, int> hashMap;// 初始化数组int arr[] = {2, 3, 4, 10, 40};// 计算数组中的元素数量int n = sizeof(arr) / sizeof(arr[0]);// 将数组元素及其索引存入哈希表for (int i = 0; i < n; i++) {hashMap[arr[i]] = i;}// 要查找的元素int x = 10;// 在哈希表中查找元素auto it = hashMap.find(x);// 根据查找结果输出信息if (it != hashMap.end()) {// 如果元素在哈希表中,输出它的索引std::cout << "元素在索引 " << it->second << std::endl;} else {// 如果元素不在哈希表中,输出相应信息std::cout << "元素不在数组中" << std::endl;}return 0;
}

5. Fibonacci查找

        Fibonacci查找算法是一种基于Fibonacci数列的查找算法,它类似于二分查找,但使用Fibonacci数列来确定查找范围的分割点。这种算法适用于有序数组,并且可以在某些情况下比二分查找更高效。

#include <iostream>
#include <algorithm> // 用于std::min函数// 斐波那契查找算法
// arr[] 是一个升序排列的数组
// n 是数组中元素的数量
// x 是要搜索的元素
int fibonacciSearch(int arr[], int n, int x) {// 初始化斐波那契数列int fibMMm2 = 0; // (m-2)'th 斐波那契数int fibMMm1 = 1; // (m-1)'th 斐波那契数int fibM = fibMMm2 + fibMMm1; // m'th 斐波那契数// 找到最小的斐波那契数,该数大于或等于nwhile (fibM < n) {fibMMm2 = fibMMm1;fibMMm1 = fibM;fibM = fibMMm2 + fibMMm1;}// 标记已经检查过的元素的偏移量int offset = -1;// 当还有斐波那契数剩余时,执行查找while (fibM > 1) {// 检查fibMMm2是否为有效位置int i = std::min(offset + fibMMm2, n - 1);// 如果x大于当前位置的元素,剪切数组的后半部分if (arr[i] < x) {fibM = fibMMm1;fibMMm1 = fibMMm2;fibMMm2 = fibM - fibMMm1;offset = i;}// 如果x小于当前位置的元素,剪切数组的前半部分else if (arr[i] > x) {fibM = fibMMm2;fibMMm1 -= fibMMm2;fibMMm2 = fibM - fibMMm1;}// 如果找到了x,返回索引else {return i;}}// 检查最后一个元素是否为xif (fibMMm1 && arr[offset + 1] == x) {return offset + 1;}// 如果未找到元素,返回-1return -1;
}int main() {// 初始化数组int arr[] = {10, 22, 35, 40, 45, 50, 80, 82, 85, 90, 100};// 计算数组中的元素数量int n = sizeof(arr) / sizeof(arr[0]);// 要查找的元素int x = 85;// 调用斐波那契查找算法int result = fibonacciSearch(arr, n, x);// 输出查找结果if (result == -1) {std::cout << "Element not found" << std::endl;} else {std::cout << "Element found at index " << result << std::endl;}return 0;
}
  1. 初始化Fibonacci数列:首先,我们初始化Fibonacci数列的三个连续的Fibonacci数:fibMMm2(第(m-2)个Fibonacci数),fibMMm1(第(m-1)个Fibonacci数),和fibM(第m个Fibonacci数)。

  2. 找到最小的Fibonacci数:我们找到最小的Fibonacci数,该数大于或等于数组的长度n

  3. 缩小查找范围:使用Fibonacci数列来确定查找范围的分割点。如果目标值x大于当前元素,则向右移动Fibonacci数列;如果x小于当前元素,则向左移动Fibonacci数列。

  4. 检查最后一个元素:在循环结束后,检查最后一个元素是否为目标值。

  5. 返回结果:如果找到目标值,返回其索引;否则返回-1。

Fibonacci查找算法在某些情况下可以比二分查找更高效,尤其是在数组长度接近Fibonacci数时。

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

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

相关文章

C++感受12-Hello Object 派生版

不变的功能&#xff0c;希望直接复用原有代码&#xff1b;变化的功能&#xff0c;希望在分开的代码里实现。 派生的基本概念和目的如何定义派生类以及创建派生对象派生对象的生死过程 0. 课堂视频 ff14-HelloObject-派生版 1. 派生的基本概念与目的 编程&#xff0c;或者说软…

vue中的坑·

常规 1.使用watch时&#xff0c;immediate true会在dom挂载前执行 2.使用this.$attrs和props 可以获取上层非原生属性&#xff08;class/id&#xff09; 多层次嵌套引用 设置的时候直接赋值&#xff0c;修改的时候即使用的双向绑定加上$set / nextick / fouceUpdate都不会同步…

HiBit Uninstaller:软件批量卸载,一触即得

名人说&#xff1a;莫道谗言如浪深&#xff0c;莫言迁客似沙沉。 ——刘禹锡《浪淘沙》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、软件介绍1、HiBit Uninstaller2、核心功能 二、下载安装1、下载2、安装 …

山东省安管人员考核报名流程及免冠证件照处理方法

随着《交通运输工程施工单位主要负责人、项目负责人和专职安全生产管理人员安全生产考核管理办法》&#xff08;以下简称《办法》&#xff09;的发布&#xff0c;山东省的安管人员迎来了新的考核要求。本文将为您详细解读山东省安管人员考核的报名流程&#xff0c;并提供免冠证…

【MotionCap】搭建wsl2的pytorch环境

参考大神:wsl2-ubuntu版本 cuda下周cuda11.3 wget https://developer.download.nvidia.com/compute/cuda/11.3.0/local_installers/cuda_11.3.0_465.19.01_linux.run sudo sh cuda_11.3.0_465.19.01_linux.run cuda是开源的么?下15分钟

1、什么是SSD?

概念 SSD&#xff08;Solid State Drive&#xff09;固态硬盘&#xff0c;是以闪存为介质的存储设备&#xff1b;这里突出的重点是闪存。 闪存&#xff0c;也就是常说的flash&#xff0c;分为NOR 和 NAND&#xff1b; NOR的地址线和数据线分开&#xff0c;所以NOR芯片可以像…

“一带一路”再奏强音!秘鲁总统博鲁阿尔特参访苏州金龙

6月27日下午&#xff0c;首次访华的秘鲁共和国总统博鲁阿尔特一行到苏州金龙参观访问&#xff0c;受到了苏州金龙总经理黄书平的热情接待。 黄书平&#xff08;左二&#xff09;向博鲁阿尔特&#xff08;右一&#xff09;介绍苏州金龙发展情况 从苏州金龙发展历程、产品技术研…

使用Nginx反向代理KKFileView遇到问题

使用KKFileView 4.0 以上版本 在KKFileView官网上&#xff0c;关于使用Nginx代理&#xff0c;建议配置如下 一、修改Nacos 在Nginx的conf文件夹中修改 nginx.conf ,新加 红框内的IP地址为代理服务器地址&#xff08;即安装KKFileView的服务器地址&#xff09; 二、修改KKFil…

小程序打包

一、manifest.json文件添加小程序id 二、接口校验&#xff0c;后端接口添加正式上线&#xff0c;有域名的地址 然后到微信公众平台-开发管理-服务器域名处配置request合法域名&#xff0c;在 此处能够看到后端的baseUrl 三、项目部署 四、发版 在小程序编辑器里 此处可以在…

Android Studio 2023版本切换DNK版本

选择自己需要的版本下载 根目录下的配置路劲注意切换 build.gradle文件下的ndkVersion也要配好对应版本

Parade接口芯片选型和应用,点击查看!

01 常见数据 / 媒体接口电路 接口电路是电子设备之间&#xff0c;电子设备与外围设备之间&#xff0c;电子设备内部部件之间起连接作用的逻辑电路&#xff0c;接口电路是设备处理器与外部设备进行信息交互的桥梁。 图1&#xff1a;常见高速数据/多媒体接口 1.1 USB接口 从最早…

详细配置SQL Server的链接服务器(图文操作Mysql数据库)

目录 前言1. MySQL ODBC 驱动2. 配置 SQL Server 链接服务器3. 彩蛋前言 此处配置以及安装没有什么理论知识 所以直奔主题,跟着以下步骤配置安装即可 需求:准备在10.197.0.110中链接外部的10.197.0.96的mysql数据源 已默认在10.197.0.96中安装了MySQL数据库并且知道其连接信…

PPT中的文字跟随Excel动态变化,且保留文字格式

今天协助客户解决了一个有趣的问题&#xff0c;这里记录一下&#xff0c;以此共勉。 目录 1. 提出问题2. 此功能的应用场景3. 开始制作4. 注意事项5. 若遇到任何问题 1. 提出问题 PPT的图表是可以引用Excel的&#xff0c;那PPT的文本是否可以引用Excel实现动态更新呢&#xff…

MWCSH 2024丨美格智能亮相上海世界移动通信大会,加速5G+AIoT应用进程

6月26日—28日全球通信领域最具规模和影响力的通信盛事—2024MWC上海世界移动通信大会在上海新国际博览中心隆重举行。MWC上海是亚洲连接生态系统的风向标&#xff0c;本届大会以“未来先行&#xff08;Future First&#xff09;”为主题&#xff0c;聚焦“超越5G”“人工智能经…

Quectel EM05-CE 模块测试

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

HarmonyOS开发实战:加密类组件使用方法-API

加密类组件 模块介绍RSA提RSA供生成密钥加解密验签等系列方法(基于HarmonyOS API)AES提供AES生成密钥加解密等系列方法(基于HarmonyOS API)DES提供3DES生成密钥加解密等系列方法(基于HarmonyOS API)SM2提供SM2生成密钥加解密等系列方法(基于HarmonyOS API)SM3提供SM3生成摘要,…

蜜雪冰城小程序逆向

app和小程序算法一样 小程序是wasm

U-KAN环境搭建推理测试

引子 U-Net的鼎鼎大名&#xff0c;我觉得无需我多言了。图像分割和扩散概率模型的基石。作者探索了KANs在改进视觉任务 Backbone 网络方面的未开发潜力。作者研究、修改并重新设计已建立的U-Net Pipeline &#xff0c;通过在标记化的中间表示上整合专用的KAN层&#xff0c;称之…

无线领夹麦克风可以唱歌吗?推荐多款收音好的无线麦克风

如今是一个短视频营销飞速发展的时代&#xff0c;越来越多自媒体人通过短视频的方式来进行直播带货、生活Vlog、线上K歌等&#xff0c;记录下生活里那美丽的瞬间。不过也有不少新手视频创作者存在疑问&#xff1a;无线领夹麦克风可以唱歌吗&#xff1f; 答案是可以的&#xff0…

SpringMvc 执行原理

当用户请求 会发送到前端控制器&#xff0c;DisptcherServlet根据请求参数生成代理请求&#xff0c;找到对应的实际控制器&#xff0c;控制器处理请求&#xff0c;创建数据模型&#xff0c;访问数据库&#xff0c;将模型响应给中心控制器&#xff0c;控制器使用模型与视图渲染视…