Java的查找算法和排序算法

Java的查找算法和排序算法

  • 一、查找算法
    • 1. 基本查找
      • a. 示例
    • 2. 二分查找
      • a. 示例
    • 3. 插值查找
    • 4. 斐波那契查找
    • 5. 分块查找
      • a. 示例
  • 二、排序算法
    • 1. 冒泡排序
      • a. 示例
    • 2. 选择排序
      • a. 示例
    • 3、插入排序
      • a. 示例
    • 4. 快速排序(效率最高)
      • a. 示例

一、查找算法

1. 基本查找

  • 基本查找也叫顺序查找。
  • 核心:从0索引开始挨个往后查找。

a. 示例

  • 需求:定义一个方法,查询元素在数组中的索引值。
import java.util.ArrayList;

public class Demo2 {
    public static void main(String[] args) {
        int[] arr = {131, 127, 147, 81, 103, 23, 7, 79, 81};
        System.out.println(searchNumber(arr, 81));
    }
    public static ArrayList<Integer> searchNumber(int[] arr, int number){
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == number) {
                list.add(i);
            }
        }
        return list;
    }
}

在这里插入图片描述

2. 二分查找

  • 二分查找又称折半查找。
  • 前提条件:数组中的数据必须是有序的。
    • 如果数据是乱的,必须先排序。
    • 只能确定当前key在数组中是否存在,不能确定其索引值。
  • 核心:每次排除一半的查找范围。
  • 过程:
    • 定义min和max表示当前要查找的范围
    • 定义中间索引mid(min和max中间的索引)
    • 如果key在mid的左边,缩小范围时,min不变,max等于mid减1
    • 如果key在mid的右边,缩小范围时,max不变,min等于mid加1

a. 示例

public class Demo3 {
    public static void main(String[] args) {
        int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};
        System.out.println(BinarySearch(arr, 127));
    }
    public static int BinarySearch(int[] arr, int number){
        // 定义范围
        int min = 0;
        int max = arr.length;
        while (true) {
            if (min > max) {
                return -1;
            }
            // 定义中间索引
            int mid = (min + max) / 2;
            // 核心代码
            if (arr[mid] > number) {
                max = mid - 1;
            } else if (arr[mid] < number) {
                min = mid + 1;
            } else if (arr[mid] == number) {
                return mid;
            }
        }
    }
}

在这里插入图片描述

3. 插值查找

  • 插值查找在二分查找的基础上改进。

  • 前提条件:数据尽可能的分布均匀。

  • 核心: m i d = m i n + k e y − a r r [ m i n ] a r r [ m a x ] − a r r [ m i n ] × ( m a x − m i n ) mid = min + \dfrac{key-arr[min]}{arr[max]-arr[min]}\times(max-min) mid=min+arr[max]arr[min]keyarr[min]×(maxmin)

    • mid值是key在数组中的百分比位置。
    • mid = 偏移量 + 左距离 ÷ 总距离 × (最大值-最小值)

4. 斐波那契查找

  • 斐波那契查找在二分查找的基础上改进。
  • 根据黄金分割点来计算mid索引。
  • mid = min + 黄金分割点左半边长度 - 1。

5. 分块查找

  • 原则
    • 前一块中的最大数据,小于后一块中所有的数据(块内无序,块间有序)
    • 块数数量一般等于元素个数开根号。比如:16个元素一般分为4块左右。
  • 核心:先确定要查找的元素在哪一块,然后再块内挨个查找。
    在这里插入图片描述

a. 示例

  • 定义一个数组 {16, 5, 9, 12, 21, 18, 32, 23, 37, 26, 45, 34, 50, 48, 61, 52, 73, 66},查询数字是否在数组中。
package day18.search;

public class Demo4 {
    public static void main(String[] args) {
        int[] arr = {16, 5, 9, 12, 21, 18, 32, 23, 37, 26, 45, 34, 50, 48, 61, 52, 73, 66};

        // 块对象
        Block b1 = new Block(21, 0, 5);
        Block b2 = new Block(45, 6, 11);
        Block b3 = new Block(73, 12, 17);

        Block[] blockArr = {b1, b2, b3};
        int number = 66;
        // 现确定在哪一块
        int index = getIndex(blockArr, arr, number);
        // 在块中查找
        System.out.println(index);
    }

    private static int getIndex(Block[] blockArr, int[] arr, int number) {
        int indexBlock = findIndexBlock(blockArr, number);
        if (indexBlock == -1) {
            return -1;
        }
        int startIndex = blockArr[indexBlock].getStartIndex();
        int endIndex = blockArr[indexBlock].getEndIndex();
        for (int i = startIndex; i <= endIndex; i++) {
            if (arr[i] == number) {
                return i;
            }
        }
        return -1;
    }

    public static int findIndexBlock(Block[] blockArr, int number){
        for (int i = 0; i < blockArr.length; i++) {
            if (number <= blockArr[i].getMax()) {
                return i;
            }
        }
        return -1;
    }
}

class Block{
    private int max;  // 块中最大值
    private int startIndex;  // 起始索引
    private int endIndex;  // 结束索引

    public Block() {
    }

    public Block(int max, int startIndex, int endIndex) {
        this.max = max;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }

    public int getStartIndex() {
        return startIndex;
    }

    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    public int getEndIndex() {
        return endIndex;
    }

    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }
}

在这里插入图片描述

二、排序算法

1. 冒泡排序

  • 步骤:
    1. 相邻的元素两两比较,大的放后面,小的放前面;
    2. 第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推;
    3. 如果数组中有n个数据,总共要执行n-1轮。

a. 示例

  • 定义一个数组{2, 1, 4, 5, 3},并排序。
import java.util.Arrays;

public class Demo1 {
    public static void main(String[] args) {
        int[] arr = {2, 1, 4, 5, 3};
        // 循环多少轮
        for (int i = 0; i < arr.length-1; i++) {
            // 每一轮排序
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

在这里插入图片描述

2. 选择排序

  • 步骤:
    1. 从0索引开始,与每一个索引上的元素依次比较。
    2. 小的放前面,大的放后面。

a. 示例

  • 定义一个数组{2, 1, 6, 8, 3},并排序。
import java.util.Arrays;

public class Demo2 {
    public static void main(String[] args) {
        int[] arr = {2, 1, 6, 8, 3};

        // 进行比较的索引值
        for (int i = 0; i < arr.length; i++) {
            // 拿每个索引值对应的元素与后面的每个元素进行比较
            // 每完成一轮,索引值加1
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }

        System.out.println(Arrays.toString(arr));
    }
}

在这里插入图片描述

3、插入排序

  • 步骤:
    1. 将索引在[0, N]的元素看作有序的,把[N+1, arr.length-1]的元素当成无序的。
    2. 遍历无序的数据,将遍历到的元素插入到有序序列中适当的位置,如遇到相同数据,插在后面。
  • N的范围:0~arr.length-1

a. 示例

  • 定义数组:{3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48}
import java.util.Arrays;

public class Demo3 {
    public static void main(String[] args) {
        int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};

        // 找到无序的那一组数据从哪个索引开始
        int startIndex = -1;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > arr[i + 1]) {
                startIndex = i + 1;
                break;
            }
        }

        // 遍历从startIndex开始到最后一个元素
        for (int i = startIndex; i < arr.length; i++) {
            // 记录索引,以防被修改
            int j = i;
            // 遍历交换位置
            while (j > 0 && arr[j] < arr[j - 1]) {
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
                j--;
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

在这里插入图片描述

4. 快速排序(效率最高)

  • 步骤:
    1. 将排序范围内的第一个数字作为基准数,在定义两个索引变量start、end
    2. 索引start从前往后找比基准数大的,索引end从后往前找比基准数小的。
    3. start、end都找到一个数后,替换两个数。
    4. 循环上面三步,直到start和end指向同一个索引。让基准数与这个索引的元素替换(基准数归位)。
      • 归位后的效果:基准数左边的,比基准数小;基准数右边的,比基准数大。
    5. 对基准数两边的数据重复上面四步,直到要求范围的开始索引大于结束索引。

a. 示例

  • 定义一个长度为100万的数组,为数组随机填充数字,给数组进行排序。
import java.util.Random;

public class Demo6 {
    public static void main(String[] args) {
        Random random = new Random();
        int[] arr = new int[1000000];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt();
        }
        
        long start = System.currentTimeMillis();
        quickSort(arr, 0, arr.length - 1);
        long end = System.currentTimeMillis();

        System.out.println("共用时: " + (end-start));
    }


    public static void quickSort(int[] arr, int startIndex, int endIndex) {
        if (startIndex > endIndex) return;
        // 记录索引值,防止被修改
        int start = startIndex;
        int end = endIndex;
        // 记录基准数
        int baseNumber = arr[startIndex];
        // 利用循环找到要交换的数
        while (start != end) {
            // 从end往前找
            while (end > start && arr[end] >= baseNumber) end--;
            // 从start往后找
            while (end > start && arr[start] <= baseNumber) start++;
            // 交换start和end
            int temp = arr[end];
            arr[end] = arr[start];
            arr[start] = temp;
        }
        // 基准数归位
        int temp = arr[startIndex];
        arr[startIndex] = arr[end];
        arr[end] = temp;
        // 确定6左边的范围
        quickSort(arr, startIndex, start - 1);
        // 确定6右边的范围
        quickSort(arr, end + 1, endIndex);
    }
}

在这里插入图片描述

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

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

相关文章

期权懂|2024年期权最新止损策略有哪些?

本期让我懂 你就懂的期权懂带大家来了解&#xff0c;2024年期权最新止损策略有哪些&#xff1f;有兴趣的朋友可以看一下。期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 2024年期权最新止损策略有哪些&#xff1f; 一、浮亏比例…

Pandas模块之垂直或水平交错条形图

目录 df.plot() 函数Pandas模块之垂直条形图Pandas模块之水平交错条形图 df.plot() 函数 df.plot() 是 Pandas 中的一个函数&#xff0c;用于绘制数据框中的数据。它是基于 Matplotlib 库构建的&#xff0c;可以轻松地创建各种类型的图表&#xff0c;包括折线图、柱状图、散点…

PCM5102A具有PLL和32位、384kHz PCM/I2S接口的2.1VRMS、112dB音频立体声DAC

PCM5102A外观和丝印 1 特性 1•超低带外噪声 •具有BCK基准的高性能集成音频锁相环(PLL)&#xff0c;可在内部生成SCK •直接线路电平2.1VRMS输出 •无需隔直电容 •线路电平输出支持低至1kΩ的负载 •智能静音系统&#xff1b;软斜升或斜降搭配模拟静音&#xff0c;实现120dB…

深度学习实战项目】基于OPenCV的人脸识别考勤系统软件开发【python源码+UI界面+功能源码详解】

背景及意义 人脸识别&#xff08;Face Recognition&#xff09;是基于人的脸部特征信息进行身份识别的一种生物识别技术&#xff0c;可以用来确认用户身份。本文详细介绍了人脸识别基本的实现原理&#xff0c;并且基于python与pyqt开发了人脸识别与信息管理软件&#xff0c;主要…

Go第三方框架--gorm框架(一)

前言 orm模型简介 orm模型全称是Object-Relational Mapping&#xff0c;即对象关系映射。其实就是在原生sql基础之上进行更高程度的封装。方便程序员采用面向对象的方式来操作数据库&#xff0c;将表映射成对象。 这种映射带来几个好处&#xff1a; 代码简洁&#xff1a;不用…

AVL树介绍与构建

目录 AVL树的概念 二叉树的构建 平衡因子的更新 旋转 左单旋 旋转过程 左单旋代码 右单旋 旋转过程 右单旋代码 左右双旋 发生情况 抽象图 具体图 平衡因子更新 左右双旋代码 右左双旋 右左双旋旋代码 验证测试AVL树 测试成员函数 测试代码 AVL树实现代码…

使用virtualenv导入ssl模块找不到指定的模块

最近在学习tensorflow&#xff0c;由于教程里面使用的是virtualenv&#xff0c;所以就按照教程开始安装了虚拟环境。但是在使用的时候&#xff0c;卡在了import ssl这一步&#xff0c;提示如下错误 >>> import ssl Traceback (most recent call last):File "<…

兼容Lodash的真正替代者

大家好&#xff0c;我是农村程序员&#xff0c;独立开发者&#xff0c;前端之虎陈随易。 这是我的个人网站&#xff1a;https://chensuiyi.me&#xff0c;欢迎一起交朋友~ 今天给大家分享一个前端工具库 Lodash 的替代品 es-toolkit。 仓库地址&#xff1a;https://github.com…

Android 自定义 Dialog 实现列表 单选,多选,搜索

前言 在Android开发中&#xff0c;通过对话框让用户选择&#xff0c;筛选信息是很方便也很常见的操作。本文详细介绍了如何使用自定义 Dialog、RecyclerView 以及自定义搜索框 来实现选中状态和用户交互&#xff0c;文中大本分代码都有明确注释&#xff0c;主打一个简单明了&a…

A survey of loss functions for semantic segmentation——论文笔记

摘要 图像分割一直是一个活跃的研究领域&#xff0c;因为它有着广泛的应用范围&#xff0c;从自动疾病检测到自动驾驶汽车。过去五年中&#xff0c;各种论文提出了用于不同场景&#xff08;如数据偏斜、稀疏分割等&#xff09;的目标损失函数。在本文中&#xff0c;我们总结了…

NVR监测软件/设备EasyNVR多个NVR同时管理构建智慧城市的大数据解决方案

在当今的数字化时代&#xff0c;安防视频监控已成为各行各业不可或缺的一部分&#xff0c;无论是在智慧工地、智慧工厂、智慧景区还是智慧水利等领域&#xff0c;都需要高效、可靠的监控系统来保障安全。 一、背景需求分析 随着科技的发展&#xff0c;智慧城市建设成为城市发展…

★ 算法OJ题 ★ 前缀和算法(上)

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;将和大家一起做几道前缀和算法题 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 算法专栏&#xff1a;★ 优选算法100天 ★_椎名澄嵐的博客-CSDN博客 ❄️❄️❄…

毕业设计选题:基于Django+Vue的物资配送管理系统的设计与实现

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录界面 管理员功能界面 申领者管理 后勤处管理 物资信息管理 入库信息管理 …

i春秋web题库——题目名称:SQLi

WEB——SQLi 写在之前&#xff1a;题目简介&#xff1a;题目分析&#xff1a; 写在之前&#xff1a; 本题在CSDN上或是其它博客上有过解答&#xff0c;只不过不知是什么原因&#xff0c;我没有找到解题过程比较完整的文章。于是我决定在CTF初学阶段写一篇这样的博客&#xff0…

ctfshow(78->81)--文件包含漏洞

Web78 源代码如下&#xff1a; if(isset($_GET[file])){$file $_GET[file];include($file); }else{highlight_file(__FILE__);代码审计&#xff1a; 使用 include() 进行文件包含&#xff0c;通过GET方法 传递参数file 获取被包含的文件。 思路&#xff1a; 利用 data://…

已解决:Uncaught SyntaxError: Unexpected token <

已解决&#xff1a;Uncaught SyntaxError: Unexpected token < 文章目录 写在前面问题描述报错原因分析 解决思路解决办法1. 使用开发者工具检查网络请求2. 验证脚本路径3. 检查服务器配置4. 处理跨域请求5. 检查打包工具配置6. 确认内容类型7. 使用原始文件进行测试8. 处理…

基于SpringBoot的电商网站源码(前台+后台)

主要功能流程&#xff1a; 前台购物&#xff1a;用户在前台进行商品浏览、选购及下单。个人中心查看&#xff1a;用户登录后可在个人中心查看订单状态、个人信息等。后台发货&#xff1a;管理员在后台系统处理订单&#xff0c;包括发货、退款等操作。 运行环境&#xff1a; …

iOS 18.2 可让欧盟用户删除App Store、Safari、信息、相机和照片应用

升级到 iOS 18.2 之后&#xff0c;欧盟的 iPhone 用户可以完全删除一些核心应用程序&#xff0c;包括 App Store、Safari、信息、相机和 Photos 。苹果在 8 月份表示&#xff0c;计划对其在欧盟的数字市场法案合规性进行更多修改&#xff0c;其中一项更新包括欧盟用户删除系统应…

张三进阶之路 | 基于Spring AOP的Log收集

前情提要 &#x1f4cc; 张三对于公司的日志处理系统不满意&#xff0c;认为其性能不佳且功能有限。为了展示自己的能力和技术实力&#xff0c;他决定利用Spring AOP&#xff08;面向切面编程&#xff09;开发一个更高效的日志处理系统&#xff0c;并将其存储在Redis中。 首先…

初识算法 · 二分查找(4)

目录 前言&#xff1a; 寻找峰值 题目解析 算法原理 算法编写 寻找旋转排序数组中的最小值 题目解析 算法原理 算法编写 寻找缺失的数字 题目解析 算法原理 算法编写 前言&#xff1a; ​本文的主题是二分查找&#xff0c;通过三道题目讲解&#xff0c;一道是寻找…