搜索算法系列之三(插值查找)

devtools/2024/9/25 4:29:14/

前言

插值查找仅适用于有序数据、有序数组,和二分查找类似,更讲究数据有序均匀分布。

算法原理

插值查找(interpolation search)是一种查找算法,它与二分查找类似,但在寻找元素时更加智能化。这种算法假设数据集是等距的或者有序的,然后根据要查找的值在数据集中的位置进行估计,而不是简单地将查找范围划分为两半。

插值查找的步骤如下:

  1. 确定查找范围:首先确定要查找的元素在哪个范围内。通常情况下,这是通过比较要查找的值和数据集的第一个和最后一个元素来确定的。

  2. 计算估计位置:通过插值公式计算要查找的值在当前查找范围内的估计位置。插值公式通常是 (value - array[low]) / (array[high] - array[low]) * (high - low) + low,其中 lowhigh 分别是当前查找范围的起始和结束位置。

  3. 检查估计位置:将估计位置与要查找的值进行比较。

    • 如果估计位置上的值等于要查找的值,则找到了目标元素。
    • 如果估计位置上的值大于要查找的值,则在估计位置的左侧继续进行插值查找。
    • 如果估计位置上的值小于要查找的值,则在估计位置的右侧继续进行插值查找。
  4. 重复直到找到目标元素或者确定元素不存在。

插值查找适用于数据集分布比较均匀的情况下,因为它是根据数据集的分布情况进行估计的。在数据集分布不均匀的情况下,插值查找可能会失效,效率不如二分查找。

上述公式说明:

value为查找的值。low、high为数据集首尾下标。array[low]、array[high]为数据集首尾值。

(value-array[low])/(array[high]-array[low])计算查找值在有序队列所处位置的比值。

代码实现(c)

#include <stdio.h>// 插值查找函数
int interpolationSearch(int arr[], int low, int high, int key) {if (low <= high) {// 计算插值的索引int mid = low + (high - low) * (double)((key - arr[low]) / (arr[high] - arr[low]));// 如果元素等于key,返回midif (arr[mid] == key)return mid;// 如果元素小于key,在右侧递归查找if (arr[mid] > key)return interpolationSearch(arr, low, mid - 1, key);// 如果元素大于key,在左侧递归查找return interpolationSearch(arr, mid + 1, high, key);}// 如果数组不存在key,返回-1return -1;
}int main() {int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};int n = sizeof(arr) / sizeof(arr[0]);int key = 7;// 查找元素int index = interpolationSearch(arr, 0, n - 1, key);// 输出结果if (index != -1)printf("元素在数组中的索引为: %d\n", index);elseprintf("元素不在数组中。\n");return 0;
}

 注意计算比例时转double类型,否则会失效。

优点与局限性

优点:

  • 适用于均匀分布的数据集: 插值查找在数据集均匀分布时效果更为显著,能够更准确地估计目标值的位置。
  • 相对于二分查找的改进: 在某些情况下,插值查找的效率较二分查找更高,尤其是对于近似均匀分布的数据。

局限:

  • 对于不均匀分布的数据效果不佳: 当数据分布不均匀时,插值查找的性能可能较差,甚至不如二分查找。
  • 可能导致溢出: 在计算插值位置时,由于分母可能为零,导致除法溢出的风险。​​​

复杂度

插值查找的时间复杂度取决于数据集的分布情况。在理想情况下(即数据集均匀分布),插值查找的时间复杂度可以达到 O(log log n)。这是因为它根据数据集的分布情况进行估计,可以更快地缩小查找范围。

然而,在最坏情况下,插值查找的时间复杂度可以达到 O(n),这通常发生在数据集中存在大量重复元素或者数据集分布不均匀的情况下。在这种情况下,插值查找可能会退化为线性搜索,效率明显下降。

总体来说,插值查找在数据集分布均匀的情况下具有更好的性能,但在数据集分布不均匀或存在大量重复元素时,效率可能不如二分查找等其他查找算法。因此,在实际应用中,需要根据具体情况选择合适的查找算法


http://www.ppmy.cn/devtools/38977.html

相关文章

用 C 语言进行大模型推理:探索 llama2.c 仓库(二)

文章目录 前提如何构建一个Transformer Model模型定义模型初始化 如何构建tokenzier 和 sampler如何进行推理总结 前提 上一节我们介绍了llama2.c中如何对hugging face的权重进行处理&#xff0c;拿到了llama2.c想要的权重格式和tokenizer.bin格式。这一节我们分析下在llama2.…

华为eNSP学习—IP编址

IP编址 IP编址子网划分例题展示第一步:机房1的子网划分第二步:机房2的子网划分第三步:机房3的子网划分IP编址 明确:IPv4地址长度32bit,点分十进制的形式 ip地址构成=网络位+主机位 子网掩码区分网络位和主机位 学此篇基础: ①学会十进制与二进制转换 ②学会区分网络位和…

elementUi中的el-table合计行添加点击事件

elementUi 文档中&#xff0c;合计行并没有点击事件&#xff0c;这里自己实现了合计行的点击事件。 created() {this.propertyList [{ property: order, label: 序号 },{ property: deptName, label: 单位名称 },{ property: contentPublishQuantity, label: 文章数量 },{ pro…

Nanopc T4 使用OpenCV

识别长方形&#xff1a; import cv2 import cv2 as cv import time import platform import os# 获取操作系统类型 os_type platform.system() if os_type "Windows":# Windows系统cap cv.VideoCapture(0) # 使用第零个摄像头 elif os_type "Linux"…

数据结构之单链表之环形链表

1.题目 题目&#xff1a;给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 2.分析 首先&#xff0c;我们应该判断链表是否有环&#xff0c;这个可以根据我的上一篇文章的快慢指针来判断。 bool hasCycle(stru…

现货黄金今日行情分析:昨日高低点法

进行交易之前&#xff0c;投资者要对现货黄金今日行情进行一波分析&#xff0c;我们交易决策应该建立在合理分析的基础之上。那么打开市场交易软件看到现货黄金今日行情之后&#xff0c;该如何着手进行分析呢&#xff1f;下面我们就来讨论一下具体的方法。 要进行现货黄金今日行…

【JavaEE网络】HTTP/HTTPS协议的工作原理与格式详解

目录 HTTP/HTTPSHTTP是什么理解“应用层协议”理解HTTP协议的工作过程HTTP协议格式 HTTP/HTTPS HTTP是什么 应用层&#xff0c;一方面是需要自定义协议&#xff0c;一方面也会用到一些现成的协议 HTTP及HTTPS是应用层重点协议 使用浏览器&#xff0c;打开网站&#xff0c;这…

【StarRocks系列】 Trino 方言支持

我们在之前的文章中&#xff0c;介绍了 Doris 官方提供的两种方言转换工具&#xff0c;分别是 sql convertor 和方言 plugin。StarRocks 目前同样也提供了类似的方言转换功能。本文我们就一起来看一下这个功能的实现与 Doris 相比有何不同。 一、Trino 方言验证 我们可以通过…