图解算法--查找算法

news2024/11/26 0:46:16

目录

查找算法

一、顺序查找

二、二分法查找

三、插值查找法

四、斐波那契查找法


查找算法

查找算法根据数据量的大小,可以将其分为以下两种

  1. 内部查找:内部查找是指在内存或内部存储器中进行查找操作的算法。内部查找适用于数据量较小、存储在内存中或者访问速度较快的情况。常见的内部查找算法有顺序查找、二分法查找、插值查找等。
  2. 外部查找:外部查找是指在大规模数据集合或存储在外部磁盘等辅助存储介质中进行查找操作的算法。

查找的表格或数据是否变动分为以下两种

  1. 静态查找:静态查找是指在不改变被查找数据的情况下进行的查找操作。即被查找的表格或数据在查找过程中保持不变。静态查找适用于对静态或只读数据进行查找的场景。一旦建立好索引或者表格,就可以反复进行查找操作而不需要修改数据。常见的静态查找算法有顺序查找、二分法查找、插值查找等。
  2. 动态查找:动态查找是指在查找过程中可能会修改被查找数据的情况下进行的查找操作。即被查找的表格或数据在查找过程中可能被增加、删除或更新。动态查找适用于对动态数据进行查找的场景,需要实时地对数据变动做出响应。常见的动态查找算法有二叉搜索树、AVL树、红黑树等,这些树结构可以实现高效的查找同时支持动态数据的插入、删除。

一、顺序查找

图解:

算法原理:顺序查找,也称线性查找,是一种基本的查找算法。它逐个地从待查找的元素序列中进行比较,直到找到目标元素或遍历完整个序列为止。具体步骤如下:

  • 从序列的第一个元素开始,依次与目标元素进行比较。
  • 若当前元素等于目标元素,则查找成功,并返回相应的位置。
  • 若当前元素不等于目标元素,则继续下一个元素进行比较。
  • 若遍历完整个序列仍未找到目标元素,则查找失败。

案例代码:

public class javaDemo1 {

    public static void main(String[] args) {
        int data[] = new int[100];
        int Target = 99;
        int TargetIndex = -1;
        Random random = new Random();

        for (int i=0;i< data.length;i++){
            data[i] = random.nextInt(100);
        }

//        循序查找
        for (int j=0;j< data.length;j++){
            if (data[j] == Target){
                TargetIndex = j;
                break;
            }
        }
        System.out.println(Arrays.toString(data));
        if (TargetIndex!= -1){
            System.out.println("找到数据啦,在第"+(TargetIndex+1)+"个数据处");
        }else {
            System.out.println("抱歉,并没有找到目标数据 喵");
        }

    }
}

算法总结:顺序查找的时间复杂度为O(n),其中n为待查找序列的长度。由于其简单直观的特点,适用于小规模数据或者无序的数据集合。


二、二分法查找

图解:

算法原理:二分法查找,也称折半查找,是一种高效的查找算法,要求待查找的序列必须是有序的。它通过不断缩小查找范围来快速定位目标元素。具体步骤如下:

  • 将有序序列的首元素和尾元素分别作为左右边界。
  • 计算中间位置mid,取得序列中间的元素。
  • 若中间元素等于目标元素,则查找成功,并返回相应的位置。
  • 若中间元素大于目标元素,则目标元素可能在左半部分,缩小范围为左边界到mid-1的序列。
  • 若中间元素小于目标元素,则目标元素可能在右半部分,缩小范围为mid+1到右边界的序列。
  • 重复以上步骤,直到找到目标元素或查找范围为空。

案例代码:

public class javaDemo2 {

    public static void main(String[] args) {
        int data[] = new int[10];
//        目标值与目标值对应的下角标
        int Target = 3;
        int TargetIndex = -1;

//        二分法的下界与上界
        int low = 0;
        int high = data.length-1;
        int middle;
        Random random = new Random();

        for (int i=0;i< data.length;i++){
            data[i] = random.nextInt(10);
        }
//        形成有序数组
        Arrays.sort(data);
//        二分法查找
        while (low<=high){
            middle = (low+high)/2;
            if (data[middle]>Target){
                high = middle-1;
            }else if (data[middle]<Target){
                low = middle + 1;
            }else {
                TargetIndex = middle;
                break;
            }
        }

        System.out.println(Arrays.toString(data));
        System.out.println("目标值为"+Target);
        if (TargetIndex!= -1){
            System.out.println("找到数据啦,在第"+(TargetIndex+1)+"个数据处");
        }else {
            System.out.println("抱歉,并没有找到目标数据 喵");
        }

    }
}

算法总结:二分法查找的时间复杂度为O(log n),其中n为待查找序列的长度。由于每次都将查找范围缩小一半,因此效率较高。


三、插值查找法

图解:

算法原理:插值查找法是一种基于二分法的优化查找算法,它在有序序列中根据目标元素的估计位置进行查找,从而提高了查找速度。具体步骤如下:

  • 计算目标元素相对于首尾元素的估计位置,即通过公式(target - arr[left]) / (arr[right] - arr[left]) * (right - left) + left 计算出插值位置mid。
  • 若插值位置mid超出数组范围,或目标元素小于首元素或大于尾元素,则说明目标元素不存在。
  • 若插值位置mid处的元素等于目标元素,则查找成功,并返回相应的位置。
  • 若插值位置mid处的元素大于目标元素,则目标元素可能在左半部分,缩小范围为左边界到mid-1的序列。
  • 若插值位置mid处的元素小于目标元素,则目标元素可能在右半部分,缩小范围为mid+1到右边界的序列。
  • 重复以上步骤,直到找到目标元素或查找范围为空。

案例代码:

public class InsertSerach {
    public static void main(String[] args) {
        int data[] = new int[10];
        int Target = 9;
        int TargetIndex = -1;

        int low = 0;
        int high = data.length-1;
        int middle;

        Random random = new Random();

        for (int i= 0;i< data.length;i++){
            data[i] = random.nextInt(10);
        }
//        实现数组排列有序
        Arrays.sort(data);
//        插入查找
        while (low<=high){
            middle = low + (high - low) * (Target - data[low]) / (data[high] - data[low]);
            if (data[middle]<Target){
                low = middle +1;
            }else if (data[middle]>Target){
                high= middle -1;
            }else {
                TargetIndex = middle;
                break;
            }
        }
        System.out.println(Arrays.toString(data));
        if (TargetIndex!= -1){
            System.out.println("找到数据啦,在第"+(TargetIndex+1)+"个数据处");
        }else {
            System.out.println("抱歉,并没有找到目标数据 喵");
        }
    }
}

算法总结:插值查找法的时间复杂度为O(log log n),其中n为待查找序列的长度。它适用于分布均匀的有序序列,但对于分布不均匀的序列效果可能不理想。


四、斐波那契查找法

图解:

算法原理:斐波那契查找法是一种改进的二分查找算法,它利用了黄金分割原理进行查找。首先,需要创建一个斐波那契数列,该数列中的每个元素都是前两个元素之和。

在使用斐波那契查找法时,首先要确定一个斐波那契数列的长度,使得该长度不小于待查找数组的长度。然后,根据斐波那契数列的长度确定两个斐波那契数值——F(k)-1和F(k-2)-1。

接着,在待查找的有序数组中,以F(k)-1位置的元素作为中间值进行比较:

  • 若目标值等于中间值,则查找成功,并返回相应的位置。
  • 若目标值小于中间值,则在中间值的左半部分继续斐波那契查找。
  • 若目标值大于中间值,则在中间值的右半部分继续斐波那契查找。

每次比较后,根据查找范围的缩小情况,选择新的中间值进行下一次的比较,直到找到目标值或者查找范围为空。

案例代码:

public class FibonacciSearch {
    public static void main(String[] args) {
        int data[] = new int[10];
        int Target = 9;
        int TargetIndex = -1;

        int low = 0;
        int high = data.length - 1;
        int middle = 0;

        Random random = new Random();

        for (int i = 0; i < data.length; i++) {
            data[i] = random.nextInt(10);
        }

        Arrays.sort(data);

        // 生成斐波那契数列
        int[] fibonacci = generateFibonacci(data.length);

        // 根据斐波那契数列确定数组长度的最接近值
        int length = getClosestFibonacciNumber(data.length);

        // 扩展数组长度至斐波那契数列长度
        int[] extendedData = Arrays.copyOf(data, length);
        for (int i = data.length; i < extendedData.length; i++) {
            extendedData[i] = extendedData[data.length - 1];
        }

        while (low <= high) {
            int k = fibonacci[middle - 1];

            if (Target < extendedData[middle]) {
                high = middle - 1;
                middle = low + k - 1;
            } else if (Target > extendedData[middle]) {
                low = middle + 1;
                middle = low + k;
            } else {
                TargetIndex = Math.min(middle, high);
                break;
            }
        }

        System.out.println(Arrays.toString(data));
        if (TargetIndex != -1) {
            System.out.println("找到数据啦,在第" + (TargetIndex + 1) + "个数据处");
        } else {
            System.out.println("抱歉,并没有找到目标数据 喵");
        }
    }

    // 生成斐波那契数列
    private static int[] generateFibonacci(int length) {
        int[] fibonacci = new int[length];
        fibonacci[0] = 1;
        fibonacci[1] = 1;
        for (int i = 2; i < length; i++) {
            fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
        }
        return fibonacci;
    }

    // 获取斐波那契数列中与数组长度最接近的数值
    private static int getClosestFibonacciNumber(int n) {
        int a = 0;
        int b = 1;
        while (b <= n) {
            int temp = b;
            b = a + b;
            a = temp;
        }
        return a;
    }
}

算法总结:斐波那契查找法相比传统二分查找法的优点是,它能够更快地逼近目标值,并且避免了二分查找中取中间值时产生的整数溢出问题。但在某些情况下,斐波那契查找法的性能可能不如二分查找法,因此在实际应用中需要根据具体情况选择合适的查找算法。


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

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

相关文章

实时记录开房信息,在线开房记录查询工具

随着社会的高速发展&#xff0c;异地出差人士越来越多&#xff0c;往往全国跑&#xff0c;每每去到一个地区都要开房休息&#xff0c;当开房数量越来越多的时候&#xff0c;往往会把数据混乱&#xff0c;不利于回公司后的出差费用报销&#xff0c;故此发现了一款实时记录实时查…

h3c多系列路由器存在任意用户登录漏洞

该文章来自作者日常学习笔记&#xff0c;也有部分文章是经过作者授权和其他公众号白名单转载&#xff0c;未经授权&#xff0c;严禁转载&#xff0c;如需转载&#xff0c;联系开白。请勿利用文章内的相关技术从事非法测试&#xff0c;如因此产生的一切不良后果与文章作者无关。…

好用的c++11纳米级的测量时间消耗的类

需要包含的头文件及类实现&#xff1a; #include <chrono> #include <thread>class Timer { public:Timer() : m_StartTimepoint(std::chrono::high_resolution_clock::now()) {}~Timer() {Stop();}void Stop() {auto endTimepoint std::chrono::high_resolution…

利用改进的遗传算法(种群隔离与个体迁移)mpi并行解决tsp问题

序 关于tsp问题的概述以及如何使用遗传算法进行求解已经在上一篇文章中说明了&#xff1a;遗传算法解决TSP问题. 但是&#xff0c;作为一种演化算法&#xff0c;遗传算法还存在着许多问题&#xff0c;比如早熟的情况&#xff0c;很容易在算法前期就已经收敛了&#xff0c;大量…

得帆信息CEO张桐接受21世纪财经深度专访,表示AIGC+低代码将带来生产效率的变革

近日&#xff0c;得帆信息创始人兼CEO张桐接受了21世纪财经深度专访&#xff0c;他表示AIGC低代码的黄金组合&#xff0c;将带来生产效率的变革。 眼下&#xff0c;低代码与AI创新的联接才刚刚开始&#xff0c;也必然会带来生产效率的变革。 在AIGC汹涌的浪潮下&#xff0c;聊…

【LNMT与动静分离】

目录 一、LNMT 1.部署tomcat 1.1 单机部署 1.2 多机部署 2.部署nginx 3.部署Mariadb 4.配置Nginx 二、Nginx高级配置 1.location 2.1 应用场景 2.2 书写位置 2.3 重写条目写法 2.4 返回状态码 2.5 案例 三、动静分离 1.修改nginx配置文件 2.测试 一、LNMT 1.…

四层负载均衡的NAT模型与DR模型推导 | 京东物流技术团队

导读 本文首先讲述四层负载均衡技术的特点&#xff0c;然后通过提问的方式推导出四层负载均衡器的NAT模型和DR模型的工作原理。通过本文可以了解到四层负载均衡的技术特点、NAT模型和DR模型的工作原理、以及NAT模型和DR模型的优缺点。读者可以重点关注NAT模型到DR模型演进的原…

linux字符串处理

目录 1 C 截取字符串,截取两个子串中间的字符串2 获取该字符串后面的字符串用 strstr() 函数查找需要提取的特定字符串&#xff0c;然后通过指针运算获取该字符串后面的字符串用 strtok() 函数分割字符串&#xff0c;找到需要提取的特定字符串后&#xff0c;调用 strtok() 传入…

c语言六子棋(Alpha-Beta剪枝算法)

c语言Alpha-Beta剪枝算法六子棋介绍 Alpha-Beta剪枝算法是一种用于优化博弈树搜索的算法&#xff0c;可以在搜索过程中减少不必要的计算&#xff0c;从而提高搜索效率。该算法常用于博弈游戏&#xff0c;如六子棋。 六子棋是一种类似于五子棋的棋类游戏&#xff0c;在一个六边形…

C#: Json序列化和反序列化,集合为什么多出来一些元素?

如下面的例子&#xff0c;很容易看出问题&#xff1a; 如果类本身的无参构造函数&#xff0c; 就添加了一些元素&#xff0c;那么在序列化&#xff0c;再反序列化&#xff0c;会导致元素增加。 如果要避免&#xff0c;必须添加&#xff1a; new JsonSerializerSettings() { …

目标检测(凑字数,凑字数,为什么标题一定要五个字)

写在最前&#xff1a; 昨天七夕&#xff0c;一个人躲在家里打游戏&#xff0c;不敢出门&#xff0c;怕被喂狗粮。 一个即将步入中年的老男人&#xff0c;弱小&#xff0c;无助&#xff0c;单身&#xff0c;肥胖&#xff0c;贫穷。但是怀揣着一丢丢情怀和梦想&#xff0c;妄图吃…

运算符(个人学习笔记黑马学习)

算数运算符 加减乘除 #include <iostream> using namespace std;int main() {int a1 10;int a2 20;cout << a1 a2 << endl;cout << a1 - a2 << endl;cout << a1 * a2 << endl;cout << a1 / a2 << endl;/*double a3 …

github加速方式

windows系统访问github加速方式 第一步&#xff1a;查询dns地址第二步&#xff1a;host文件添加dns映射第三步&#xff1a;刷新dns 第一步&#xff1a;查询dns地址 查询工具&#xff1a;https://coding.tools/cn/nslookup 依次将以下网址的ip查询出来&#xff1a; github.com …

javaee之黑马乐优商城1

问题1&#xff1a;整体的项目架构与技术选型 技术选型 开发环境 域名测试 如何把项目起来&#xff0c;以及每一个目录结构大概是什么样子 通过webpack去启动了有个项目&#xff0c;这里还是热部署&#xff0c;文件改动&#xff0c;内容就会改动 Dev这个命令会生成一个本地循环…

睿趣科技:抖音开网店卖玩具怎么样

近年来&#xff0c;随着社交媒体平台的飞速发展&#xff0c;抖音作为一款短视频分享应用也迅速崭露头角。而在这个充满创业机遇的时代背景下&#xff0c;许多人开始探索在抖音平台上开设网店&#xff0c;尤其是卖玩具类商品&#xff0c;那么抖音开网店卖玩具究竟怎么样呢? 首先…

Vue2(状态管理Vuex)

目录 一&#xff0c;状态管理Vuex二&#xff0c;state状态三&#xff0c;mutations四&#xff0c;actions五&#xff0c;modules最后 一&#xff0c;状态管理Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并…

Qt应用开发(基础篇)——对话框窗口 QDialog

一、前言 QDialog类继承于QWidget&#xff0c;是Qt基于对话框窗口(消息窗口QMessageBox、颜色选择窗口QColorDialog、文件选择窗口QFileDialog等)的基类。 QDialog窗口是顶级的窗口&#xff0c;一般情况下&#xff0c;用来当做用户短期任务(确认、输入、选择)或者和用户交流(提…

Royal TSX for Mac:苹果电脑远程桌面,轻松管理,完美兼容版

Royal TSX for Mac是一款功能强大、易于使用且安全稳定的远程连接管理软件。无论您是IT专业人士还是普通用户&#xff0c;它都能满足您对远程工作的需求。在一个直观友好的界面下&#xff0c;Royal TSX提供了广泛的远程连接支持&#xff0c;并具备灵活性和扩展性。无论是作为个…

xxl-job学习(一遍文章解决)

前言&#xff1a;学习xxl-job需要有git&#xff0c;springboot的基础&#xff0c;学起来就很简单 xxl-job是一个分布式的任务调度平台&#xff0c;其核心设计目标是&#xff1a;学习简单、开发迅速、轻量级、易扩展&#xff0c;现在已经开放源代码并接入多家公司的线上产品线&a…