Java常见算法_常见的查找算法和排序算法——简介及代码演示

news2024/11/28 16:35:02

        在本文中我将介绍Java中的常见算法,查找算法包括基本查找、二分查找、插值查找和分块查找。排序算法包括冒泡排序、选择排序、插入排序和快速排序

查找算法:

1.基本查找:
代码:
public class BasicSearchDemo {
    public static void main(String[] args) {
        int[] arr = {1,21,31,41,51,61,71,81};
        Scanner sc = new Scanner(System.in);
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        boolean result = basicSearch(arr, num);
        System.out.println(result);
    }
    //基本查找方法
    public static boolean basicSearch(int[] arr, int number) {
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                return true;
            }
        }
        return false;
    }
}

这是简单的基本查找,通过遍历数组来查看元素是否存在

运行结果:

基本查找小练习:
代码(含题目要求):
public class BasicSearchTest {
    public static void main(String[] args) {
        /*
        练习1:
        需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        要求:不需要考虑数组中元素是否重复
         */

        /*
        练习2:
        需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        要求:需要考虑数组中元素有重复的可能性
        例如:{1,1,1,2,3,4,5,6,1}
        若查找1,则需要返回所有元素1的索引,即0,1,2,8
         */

        //生成一个数组
        int[] arr = {1,11,21,31,41,51,51,61,51,61};

        //键盘录入一个元素
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您要查找的元素:");
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        System.out.println(getIndex(arr, num));
        System.out.println(getAllIndex(arr, num));
    }

    //练习1
    public static int getIndex(int[] arr, int number) {
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                return i;
            }
        }

        return -1;
    }

    //练习2
    public static ArrayList<Integer> getAllIndex(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.二分查找:

特点:

        二分查找的数据必须是按大小顺序排好的
        二分查找可以很大的提高查找效率
代码:
public class BinarySearchDemo1 {
    public static void main(String[] args) {
        //二分查找的数据必须是按大小顺序排好的
        //二分查找可以很大的提高查找效率

        //定义数组
        int[] arr = {1,21,31,41,51,61,71,81};
        //键盘录入一个要查找的元素
        System.out.println("输入要查找的元素:");
        Scanner sc = new Scanner(System.in);
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        System.out.println(binarySearch(arr, num));

    }

    //定义二分查找方法
    public static int binarySearch(int[] arr, int num) {
        //用min和max表示当前查找范围
        int min = 0;
        int max = arr.length - 1;
        while (true) {
            //这种情况说明元素不存在
            if(min > max) {
                return -1;
            }
            //定义中间指针
            int mid = (min + max) / 2;
            //进行判断
            if(arr[mid] < num) {
                //元素在右边
                min = mid + 1;
            } else if(arr[mid] > num) {
                //元素在左边
                max = mid - 1;
            } else {
                //找到了
                return mid;
            }
        }
    }
}
3.插值查找:

        改变mid位置时使用数学公式使其更靠近要查找的元素

特点:

        适用于数据分布较均匀的情况下
代码:
public class InterpolationSearch {
    public static void main(String[] args) {
        //适用于数据分布较均匀的情况下
        int[] arr = {1,2,3,5,6,8,9,10};
        System.out.println("请输入要查找的元素值:");
        Scanner sc = new Scanner(System.in);
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);
        int index = interpolationSearch(arr, num);
        System.out.println(index);

    }

    public static int interpolationSearch(int[] arr, int num) {
        //定义查找范围
        int min = 0;
        int max = arr.length - 1;

        while(true) {
            if(min > max) {
                return -1;
            }
            //mid = min + (key - arr[min]) / (arr[max] - arr[min]) * (max - min)
            int mid = min + (num - arr[min]) / (arr[max] - arr[min]) * (max - min);
            if(arr[mid] > num) {
                max = mid - 1;
            } else if(arr[mid] < num) {
                min = mid + 1;
            } else {
                return mid;
            }
        }
    }
}
4.分块查找:

        对数据先进行分块,通过先确定要查找的元素属于哪个块,再只需对那个块进行遍历

代码:
public class BlockSearch {
    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};

        //输入要查找的元素
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入要查找的元素");
        String numStr = sc.nextLine();
        int num = Integer.parseInt(numStr);

        int index = getIndex(arr, blockArr, num);
        System.out.println(index);

    }

    private static int getIndex(int[] arr, Block[] blockArr, int num) {
        int blockIndex = getBlock(blockArr, num);
        if(blockIndex == -1) {
            return -1;
        }
        //将范围缩小到这块的开始和结束索引
        int startIndex = blockArr[blockIndex].getStartIndex();
        int endIndex = blockArr[blockIndex].getEndIndex();
        //遍历
        for (int i = startIndex; i <= endIndex; i++) {
            if(arr[i] == num) {
                return i;
            }
        }
        return -1;
    }

    private static int getBlock(Block[] blockArr, int num) {
        for (int i = 0; i < blockArr.length; i++) {
            if(num < 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;
    }

    /**
     * 获取
     * @return max
     */
    public int getMax() {
        return max;
    }

    /**
     * 设置
     * @param max
     */
    public void setMax(int max) {
        this.max = max;
    }

    /**
     * 获取
     * @return startIndex
     */
    public int getStartIndex() {
        return startIndex;
    }

    /**
     * 设置
     * @param startIndex
     */
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    /**
     * 获取
     * @return endIndex
     */
    public int getEndIndex() {
        return endIndex;
    }

    /**
     * 设置
     * @param endIndex
     */
    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }

    public String toString() {
        return "Block{max = " + max + ", startIndex = " + startIndex + ", endIndex = " + endIndex + "}";
    }
}

排序算法:

1.冒泡排序:
特点:
        相邻的元素两两比较,大的放右边,小的放左边(从小到大情况)
        第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推
        如果数组中有n个数据,那总共执行n-1轮代码就可以
代码:
public class BubbleSort {
    public static void main(String[] args) {
        //相邻的元素两两比较,大的放右边,小的放左边(从小到大情况)
        //第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推
        //如果数组中有n个数据,那总共执行n-1轮代码就可以

        //创建一个数组
        int[] arr = {1,4,5,2,3,9,5,6};
        int[] resultArr = bubbleSort(arr);
        for (int i = 0; i < resultArr.length; i++) {
            System.out.println(resultArr[i]);
        }
    }

    private static int[] bubbleSort(int[] arr) {
        //外循环:要进行几轮
        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;
                }
            }
        }

        return arr;
    }
}
2.选择排序:
特点:
        从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较
        小的放前面,大的放后面(从小到大情况),以此类推
        第一轮循环结束后,最小的数据已经确定
        第二轮循环从1索引开始,以此类推
代码:
public class SelectionSort {
    public static void main(String[] args) {
        //从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较
        //小的放前面,大的放后面(从小到大情况),以此类推
        //第一轮循环结束后,最小的数据已经确定
        //第二轮循环从1索引开始,以此类推

        //创建数组
        int[] arr = {4,3,9,5,6,8,2,1};
        int[] resultArr = bubbleSort(arr);
        for (int i = 0; i < resultArr.length; i++) {
            System.out.println(resultArr[i]);
        }

    }

    public static int[] bubbleSort(int[] arr) {
        //外循环:表示几轮
        for (int i = 0; i < arr.length - 1; i++) {
            //内循环:i后面的所有数据与i进行比较
            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;
                }
            }
        }

        return arr;
    }
}
3.插入排序:
特点:
        将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个元素当成是无序的。
        遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。
代码:
public class InsertionSort {
    public static void main(String[] args) {
        //将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个元素当成是无序的。
        //遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。

        //创建数组
        int[] arr = {1,6,5,3,9,7,16,1,22,3};
        int[] resultArr = insertionSort(arr);
        for (int i = 0; i < resultArr.length; i++) {
            System.out.println(resultArr[i]);
        }
    }

    public static int[] insertionSort(int[] arr) {
        //判断有序元素个数
        int index = 0;
        for (int i = 1; i < arr.length; i++) {
            if(arr[index] < arr[index + 1]) {
                index++;
            } else {
                break;
            }
        }
        //index为最后一个有序元素的索引

        //有序元素后面的每个元素要插入有序元素中   插入后有序元素加1   索引也++

        //我的其他思路   复杂了。。
        /*
        for (; index < arr.length - 1; index++) {
            int i = index + 1;
            for(int j = index; j >= 0; j--) {
                if(arr[i] >= arr[j]) {
                    break;
                } else {
                    //有序元素后面的无序元素只要比前面的小就交换位置
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                    i--;
                    continue;
                }
            }
        }
        */

        //从有序数组后的第一个元素到最后一个元素
        for (int i = index + 1; 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--;
            }
        }

        return arr;
    }
}
4.快速排序

        这里展示快速排序之前要先学会递归思想,我先来放两个递归思想的小练习

递归练习一 题目及代码:
public class RecursionAlgorithmTest1 {
    public static void main(String[] args) {
        //核心:找出口 找规律
        //方法中再次调用方法时,参数应更接近出口

        //求1~100所有整数的和
        int sum = getSum(100);
        System.out.println(sum);
    }

    //1~100所有整数的和 = 100 + 1~99的和
    //1~99的和 = 99 + 1~98的和
    //…………
    public static int getSum(int num) {
        //出口
        if(num == 1) {
            return 1;
        }
        return num + getSum(num - 1);
    }
}
递归练习二 题目及代码:
public class RecursionAlgorithmTest2 {
    public static void main(String[] args) {
        //需求:用递归求5的阶乘,并把结果在控制台输出
        int factorail = getFactorail(5);
        System.out.println(factorail);
    }

    //5的阶乘 = 5 * 4的阶乘
    //4的阶乘 = 4 * 3的阶乘
    //…………
    public static int getFactorail(int num) {
        //出口
        if(num == 1) {
            return 1;
        }
        return num * getFactorail(num - 1);
    }
}

        接下来开始讲解快速排序:

过程:
//将排序范围中的第一个数字作为基准数,在定义两个变量start,end
//start从前往后找比基准数大的,end从后往前找比基准数小的。
/*找到之后交换start和end指向的元素,并循环这一过程,直到start和end处于同一个位置,
该位置是基准数在数组中应存入的位置,再让基准数归位*/
//归为后的效果:基准数左边的都比基准数小,右边的都比基准数大
代码演示:
public class QuickSort {
    public static void main(String[] args) {
        //创建数组
        int[] arr = {6,2,3,1,7,5,8};
        int start = 0;
        int end = arr.length - 1;
        quickSort(arr, start, end);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

    }

    private static void quickSort(int[] arr, int i, int j) {
        //出口
        if(i >= j) {
            return;
        }
        int start = i;
        int end = j;
        //基准数
        int baseNumber = arr[i];
        while(start != end) {
            //end从右往左开始找比基准数小的数
            while(true) {
                if(end <= start || arr[end] < baseNumber) {
                    break;
                }
                end--;
            }
            //start从左往右开始找比基准数大的数
            while(true) {
                if(end <= start || arr[start] > baseNumber) {
                    break;
                }
                start++;
            }
            //交换位置
            int temp = arr[end];
            arr[end] = arr[start];
            arr[start] = temp;
        }
        //将基准数与当前start和end索引所在位置交换
        int temp = arr[i];
        arr[i] = arr[start];
        arr[start] = temp;
        //基准数左边继续重复刚才所做的事
        quickSort(arr, i, start - 1);
        //基准数右边继续重复刚才所做的事
        quickSort(arr, start + 1, j);


    }
}

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

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

相关文章

多线程学习-Lock锁以及监视器锁详解

目录 1. Lock锁 1.1 Lock锁介绍 1.2 Lock锁的其他加锁方式 1.3 Lock和synchronized对比 2.监视器锁 1. Lock锁 1.1 Lock锁介绍 我们知道使用同步方法或同步代码块会自动加锁和解锁&#xff0c;那有没有办法可以自己控制加锁和解锁的时机呢&#xff1f; java在JDK1.5之后提供了…

BoostCompass(数据准备预处理模块)

阅读导航 一、网页数据下载二、编写数据去标签与数据清洗的模块 Parser✅boost 开发库的安装1. 基本思路2. 详细讲解&#xff08;1&#xff09;程序递归遍历目录&#xff0c;收集所有HTML文件的路径&#xff08;2&#xff09;对每个HTML文件进行解析&#xff0c;提取出文档标题…

政安晨:【深度学习神经网络基础】(五)—— 霍普菲尔德神经网络和玻尔兹曼机

目录 简述 霍普菲尔德神经网络 训练霍普菲尔德神经网络 Hopfield-Tank神经网络 玻尔兹曼机 总之 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&am…

Python学习笔记10 - 程序的组织结构

1. if 语句 2. pass语句 3. 内置函数range() 4. while 循环语句 5. for-in 循环语句 6. 流程控制语句 break 7. 流程控制语句 continue 8. else 语句 9. 嵌套循环

申请GeoTrust证书

GeoTrust是全球知名的数字证书颁发机构&#xff08;CA&#xff09;和安全解决方案提供商。它成立于1999年&#xff0c;后来成为DigiCert旗下的一部分。GeoTrust专注于提供SSL证书和其他安全产品&#xff0c;以保护网站流量、电子邮件通信和企业身份的安全。 GeoTrust的SSL证书在…

Vue+node.js蔬菜水果农产品网上商城管理系统

用户能够及时掌握最新的数据&#xff0c;并能有效地提升用户的服务水平。本制度的优势在于&#xff1a; &#xff08;1&#xff09;该系统将蔬菜信息及时地提供给使用者。使用者可以在任何时候登陆该网站查询相关资讯&#xff0c;所有资讯均真实可信&#xff0c;并严肃处理各项…

test4102

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

YUDAO源码中的正序倒序表格ElmentUI的实现,与后端的配合?

前端展示和实现&#xff1a; 1. elmentUI表格的定义 2. JS请求参数改造 <!-- 列表 --><el-table v-loading"loading" :data"list" sort-change"handleSortChange"><el-table-column label"Expiry Date" prop"…

人体跟随小车(旭日x3派、yolov5、目标检测)

人体跟随小车&#xff08;yolov5、目标检测&#xff09; 前言最终结果接线实现注意 前言 上板运行的后处理使用cython封装了&#xff0c;由于每个版本的yolo输出的形状不一样&#xff0c;这里只能用yolov5-6.2这个版本。 ①训练自己的模型并部署于旭日x3派参考&#xff1a; ht…

直播系统的短视频直播源码,带有多功能后台系统的直播短视频平台 APP 源码。

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 此源码是一个直播系统&#xff0c;集直播、短视频等功能&#xff0c;根据市场趋势开发并推出思乐直播APP&#xff0c;APP功能丰富且可在后台管理系统进行配置&#xff0c;做到按需求来…

【算法一则】贪心加双指针-盛水最多的容器

目录 题目题解贪心算法双指针解题思路暴力破解法双指针 总结 题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器…

设计模式学习笔记 - 设计模式与范式 -行为型:7.责任链模式(下):框架中常用的过滤器、拦截器是如何实现的?

概述 上篇文章《6.责任链模式&#xff08;上&#xff09;&#xff1a;原理与实现》&#xff0c;学习了职责链模式的原理与实现&#xff0c;并且通过一个敏感词过滤框架的例子&#xff0c;展示了职责链模式的设计意图。本质上来说&#xff0c;它跟大部分设计模式一样&#xff0…

不到6毛钱的I2C总线实时时钟日历芯片LK8563

前言 8563实时时钟芯片&#xff0c;国内外均有多家生产&#xff0c;今推荐一个性价比极高的RTC芯片&#xff0c;LK8563&#xff0c;一片不到6毛钱. 特点 基于32.768kHz晶体的秒&#xff0c;分&#xff0c;小时&#xff0c;星期&#xff0c;天&#xff0c;月和年的计时 带有世…

【堡垒机】堡垒机的介绍

目前&#xff0c;常用的堡垒机有收费和开源两类。 收费的有行云管家、纽盾堡垒机&#xff1b; 开源的有jumpserver&#xff1b; 这几种各有各的优缺点&#xff0c;如何选择&#xff0c;大家可以根据实际场景来判断 什么是堡垒机 堡垒机&#xff0c;即在一个特定的网络环境下&…

第十届蓝桥杯大赛个人赛省赛(软件类) CC++ 研究生组-RSA解密

先把p&#xff0c;q求出来 #include<iostream> #include<cmath> using namespace std; typedef long long ll; int main(){ll n 1001733993063167141LL, sqr sqrt(n);for(ll i 2; i < sqr; i){if(n % i 0){printf("%lld ", i);if(i * i ! n) pri…

Matlab|【防骗贴】【免费】基于主从博弈的主动配电网阻塞管理

目录 1 主要内容 程序亮点 2 部分代码 3 程序结果 4 下载链接 1 主要内容 《基于主从博弈的主动配电网阻塞管理》文献介绍&#xff1a;主要采用一种配电网节点边际电价统一出清的主从博弈双层调度框架。上层框架解决用户在负荷聚合商引导下的用电成本最小化问题&#xff0…

电脑更新到win11后不能上网,更新win11后无法上网

越来越多的用户升级了win11系统使用&#xff0c;然而有些用户发现电脑更新到win11后不能上网了&#xff0c;这是怎么回事呢?而且奇怪的是&#xff0c;网络状态显示已连接&#xff0c;但就是无法上网&#xff0c;原本以为重置网络就能搞定&#xff0c;但结果相反。针对这一情况…

DRF的认证、权限、限流、序列化、反序列化

DRF的认证、权限、限流、序列化、反序列化 一、认证1、直接用&#xff0c;用户授权2、认证组件源码 二、权限1. 直接使用&#xff0c;用户权限2.权限组件源码 三、序列化1. 序列化1.1 自定义Serailizer类序列化1.2 在视图APIView中使用1.3 自定义ModelSerializer类序列化1.4 不…

vue3 +Taro 页面实现scroll-view 分页功能

需求 现在分页列表 后端只给你一个分页的数据列表 没有总页数 没有当前的分页 页数 只有这么一个list 、、、 如何去分页 我这使用的是scroll-view 组件 滑动到底部的事件 根据你当前设定的每页的数据数量和后端返回给你的数据列表数量 当某一次分页 两个数量不相等了以后 就…

ActiveMQ介绍及linux下安装ActiveMQ

ActiveMQ介绍 概述 ActiveMQ是Apache软件基金下的一个开源软件&#xff0c;它遵循JMS1.1规范&#xff08;Java Message Service&#xff09;&#xff0c;是消息队列服务&#xff0c;是面向消息中间件&#xff08;MOM&#xff09;的最终实现&#xff0c;它为企业消息传递提供高…