图解算法--查找算法

目录

查找算法

一、顺序查找

二、二分法查找

三、插值查找法

四、斐波那契查找法


查找算法

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

  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.mfbz.cn/a/96893.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mysql的page,索引,Explain Type等基本常识

Mysql的基本问题 Mysql 为什么建议使用自增id&#xff1f; 因为id&#xff08;主键&#xff09;是自增的话&#xff0c;那么在有序的保存用户数据到页中的时候&#xff0c;可以天然的保存&#xff0c;并且是在聚集索引&#xff08;id&#xff09;中的叶子节点可以很好的减少插…

Java自定义捕获异常

需求分析 ElectricalCustomerVO electricalCustomerVO new ElectricalCustomerVO(); electricalCustomerVO.setElcNumber(chatRecordsLog.getDeviceNumber()); List<ElectricalCustomerVO> electricalCustomerlist electricalCustomerMapper.selectElectricalCustomer…

Git中smart Checkout与force checkout

Git中smart Checkout与force checkout 使用git进行代码版本管理,当我们切换分支有时会遇到这样的问题&#xff1a; 这是因为在当前分支修改了代码&#xff0c;但是没有commit,所以在切换到其他分支的时候会弹出这个窗口&#xff0c; 提示你选force checkout或者smart checko…

海外ios应用商店优化排名因素之视频预览与截图

当我们找到感兴趣的应用程序并转到该应用程序的页面时&#xff0c;首先引起注意的是预览视频。视频旨在以更具吸引力的方式展示应用程序的用户体验和UI。视频长度最多为30秒&#xff0c;其中前5秒最为重要&#xff0c;一定要让它尽可能引人注目。 1、关于优化预览视频的提示。…

改进YOLOv8系列:原创改进创新点 SIoU-NMS,EIoU-NMS,DIoU-NMS,CIoU-NMS,GIoU-NMS改进

💡该教程为属于《芒果书》📚系列,包含大量的原创首发改进方式, 所有文章都是全网首发原创改进内容🚀 💡本篇文章为YOLOv8独家原创改进:原创改进创新点 DIoU-NMS,SIoU-NMS,EIoU-NMS,CIoU-NMS,GIoU-NMS改进。 💡对自己数据集改进有效的话,可以直接当做自己的原创改…

前端需要理解的设计模式知识

设计模式的原则&#xff1a;1. 单一职责原则&#xff08;一个对象或方法只做一件事&#xff09; 2. 最少知识原则&#xff08;尽可能少的实体或对象间互相作用&#xff09; 3. 开放封闭原则&#xff08;软件实体具有可扩展且不可修改&#xff09; 设计模式是通过代码设计经验总…

理论转换实践之keepalived+nginx实现HA

背景&#xff1a; keepalivednginx实现ha是网站和应用服务器常用的方法&#xff0c;之前项目中单独用nginx实现过负载均衡和服务转发&#xff0c;keepalived一直停留在理论节点&#xff0c;加之最近工作编写的一个技术文档用到keepalived&#xff0c;于是便有了下文。 服务组件…

学习笔记|认识数码管|控制原理|数码管实现0-9的显示|段码跟位码|STC32G单片机视频开发教程(冲哥)|第九集:数码管静态显示

文章目录 1.认识数码管2.控制原理十进制转换为任意进制其它进制转十进制 3.数码管实现0-9的显示1.用数组定义0-9的内码段码跟位码的区别2.尝试用延时实现0-9的循环显示3.用按键控制数字的加或者减。 总结课后练习&#xff1a; 1.认识数码管 数码管按段数可分为七段数码管和八段…

【触动精灵】IDE 连接设备

文章目录 1. 安装 TSStudio2. 下载 蒲公英VPN使用方法后台管理设备 3. 下载 雷电模拟器雷电设置安装蒲公英安装触动精灵 4. IDE 连入设备 1. 安装 TSStudio 登录触动官网&#xff0c;注册触动账号。 左下角开发工具&#xff0c;选择下载 IDE 触动脚本编辑器界面如下&#xff…

计算机毕设之Python的高校成绩分析(含文档+源码+部署)

本系统阐述的是一个高校成绩分析系统的设计与实现&#xff0c;对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计&#xff0c;描述&#xff0c;实现和分析与测试方面来表明开发的过程。开发中使用了 django框架和MySql数据库技术搭建系统的整体架构。…

[Android]JNI的基础知识

目录 1.什么是JNI 2.配置JNI开发环境NDK 3.创建Native C类型的项目 4. 了解CMakeLists.txt 文件 5.了解native-lib.cpp 文件 6.在 Android 的 MainActivity 中调用 native-lib.cpp 中实现的本地方法 1.什么是JNI JNI&#xff08;Java Native Interface&#xff09;是一…

Stable Diffusion 提示词入门指南

前言 本文主要讲解 Stable Diffusion &#xff08;下文简称 SD&#xff09;提示词的用法&#xff0c;帮助大家生成更高质量的图片 本章节主要讲解文生图&#xff0c;其他类型读者可以自行探索。同时本文主要是以 Stable Diffusion Discard 的形式生成图片 如果各位对于图片隐…

vulhub之MinIO信息泄露漏洞(CVE-2023-28432)

文章目录 0x01 前言0x02 漏洞描述0x03 影响范围0x04 漏洞复现1.启动环境2.查看端口3.构造POC 0x05 修复建议 0x01 前言 本次测试仅供学习使用&#xff0c;如若非法他用&#xff0c;与本文作者无关&#xff0c;需自行负责&#xff01;&#xff01;&#xff01; 0x02 漏洞描述 …

AR地图微信小程序:数字化时代下地图应用的新突破

随着数字化时代的到来&#xff0c;地图应用成为人们日常生活中不可或缺的工具。而随着增强现实&#xff08;AR&#xff09;技术的快速发展&#xff0c;AR地图微信小程序应运而生&#xff0c;为用户提供了一种全新的地图导航体验。本文将深入探讨AR地图微信小程序的专业性和思考…

茶凳浅谈-使用QCA7006AQ 让电动汽车成为智慧电网的一环

前言: 智慧电网一词相信大家都已经耳熟能详。智能电网是指采用先进的电力技术和设备、信息与通信技术&#xff0c;系统地实现电网的智能型监测、分析和决策控制&#xff0c;支持新型能源发电和灵活优质用电&#xff0c;具有高自动化水平&#xff0c;并有一定自愈、互动功能的安…

爬虫逆向实战(二十六)--某某学堂登录

一、数据接口分析 主页地址&#xff1a;某某学堂 1、抓包 通过抓包可以发现数据接口是Account/LoginPost 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现pass是加密参数 请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 无co…

C#,《小白学程序》第六课:队列(Queue)的应用,《实时叫号系统》

医院里面常见的叫号系统怎么实现的&#xff1f; 1 文本格式 /// <summary> /// 下面定义一个新的队列&#xff0c;用于演示《实时叫号系统》 /// </summary> Queue<Classmate> q2 new Queue<Classmate>(); /// <summary> /// 《小白学程序》第…

Java稀疏数组

目录 1.稀疏数组 2.稀疏数组的使用 2.1 二维数组转换为稀疏数组 2.2 稀疏数组转换为二维数组 1.稀疏数组 稀疏数组&#xff08;Sparse Array&#xff09;&#xff1a;当一个数组中的大部分元素为相同的值&#xff0c;可使用稀疏数组来保存该数组&#xff0c;可以将稀疏数组…

eslint和prettier格式化冲突

下载插件 ESLint 和 Prettier ESLint 进入setting.json中 setting.json中配置 {"editor.tabSize": 2,"editor.linkedEditing": true,"security.workspace.trust.untrustedFiles": "open","git.autofetch": true,"…

【Vue3+Ts】项目启动准备和配置项目代码规范和css样式的重置

项目启动准备 创建项目&#xff08; 使用Vite 构建工具创建项目模板&#xff09;目录介绍插件安装创建别名编译说明项目配置配置icon和标题配置项目别名配置ts.config.json检测vscode的插件是否配置 配置项目代码规范集成editorconfig配置prettier工具库ESLint检测配置 CSS样式…