Java开发 - 常用算法深度讲解,让你再也不会忘记

news2024/12/28 17:52:57

目录

前言

冒泡排序

原理

选择排序

原理

插入排序

原理

二分查找排序

原理

结语


前言

经常会有一些算法,我们说常用不常用,说不用也偶尔会用,当时看记住了,过几天提起来又忘记了,这是为什么呢?以博主为例,当时看的时候的确是“记住了”,问题就出在这个“记”上,算法是不能用记忆力去暴力破解的,需要理解,理解了,即使记不住,也可以根据理解手写出来。今天,我将带领大家掌握这些基础算法的要领,让你在需要的时候手写出来,而不是靠记忆背下来。

冒泡排序

原理

相邻元素两两比较,大的/小的往后排,一轮比较结束,最大值出现在最大下标处。会比较n-1轮。

看上图,两两比较,第一轮的最大值就已经排到最右侧了,接着就是第二轮,第三轮,第四轮...并且每一轮开始,都是从第0位开始比较,但从最后一位开始,都会少进行(第N轮)次比较,每一轮的最后一位都是已经排好的。

最终得到的数组如下:[6,9,10,12,13,14 ]。

我们尝试来谢谢冒泡的代码:

int[] ary = {10, 13, 6, 9, 14, 12};
//共比较ary.length-1轮
for (int i = 0; i < ary.length - 1; i++) {
    //每一轮次内的比较又会少相应轮次的比较
    for (int j = 0; j < ary.length - 1 - i; j++) {
        //j > j + 1 进行交换
        if (ary[j] > ary[j + 1]){
            int tmp = ary[j];
            ary[j] = ary[j+1];
            ary[j + 1] = tmp;
        }
    }
}
//最后我们输出看下结果和我们预测的一样不
System.out.println(Arrays.toString(ary));

这样,冒泡排序就写好了,核心要点在排几轮?每一轮最后少排几个?因为越排,尾部排好的顺序就越多,相应的就要减少每一轮内比较的次数,你要是选择每一轮都通排,那也行,只不过效率就降低了,这也就失去了我们用算法的初衷。

选择排序

原理

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

你听明白了吗?没关系,我们用下图来进行说明:

这样,原理就出来了,逻辑也出来了,我们可以尝试着写一写代码了:

int[] ary = {10, 13, 6, 9, 14, 12};
//共比较ary.length-1轮
for (int i = 0; i < ary.length - 1; i++) {
    //假设最小值为i
    int min = i;
    //每一轮前面就会有一个已经排好序的元素,所以我们不能重新对此元素进行排,就需要从i位开始比较
    for (int j = i; j < ary.length; j++) {
        //j > j + 1 进行交换
        if (ary[j] < ary[min]){
            //寻找最小值的下标
            min = j;
        }
    }
    //交换最小值和第i位
    int tmp = ary[i];
    ary[i] = ary[min];
    ary[min] = tmp;
}
//最后我们输出看下结果和我们预测的一样不
System.out.println(Arrays.toString(ary));

n-1轮后,排序就完成了,需要注意的点就在图里,大家也可以尝试着画下接下来的图,相信你很快就能掌握选择排序算法了。 

我们上面提到了稳定性,说选择排序是不稳定的排序算法,这是为什么呢?

首先,我们要先知道什么是稳定和不稳定的排序:排序后相同元素的前后相对位置发生改变,就是不稳定的排序,不改变,就是稳定性排序。

举个例子说明:{3,5,6,1,3,7,9}第一次排序,3和1交换位置,两个3的相对位置发生了变化,那么这就是一个不稳定的排序。这个不用纠结原因,规定就是这样,记住就好,只出现在有相同元素的情况下。

插入排序

原理

插入排序也称为直接插入排序,对于少量的元素排序,它是一个有效的算法,它的思想是将一个元素插入已经排好序的有序表中,从而变成一个新的,记录数+1的新有序表。和选择排序类似,也是将元素分为两部分,一个是已经排序的,一个是没有排序的,对未排序的部分进行遍历,将遍历的元素分别插入到已经排好序的队列中的合适位置,直到未排序部分元素数为0。

我们用一张图来表示下:

插入时,我们是从当前位置开始往第0位上倒着比较,小于第几位,就讲遍历的元素插入到第几位的前面。

图也有了,我们仿照着选择排序,可以来写写代码了:

int[] ary = {10, 13, 6, 9, 14, 12};
//共比较ary.length-1轮,这里第0位默认排好序,所以从第1位开始遍历
for (int i = 1; i < ary.length; i++) {
    //这里需要往前找,并比较大小,小的话就插入进去
    for (int j = i; j > 0 && ary[j] < ary[j - 1]; j--) {
        //ary[i] == ary[j],这里依次倒序进行比较,满足条件就进行交换, 
        //直到把arr[j]插入到合适的位置为止
        int tmp = ary[j];
        ary[j] = ary[j - 1];
        ary[j - 1] = tmp;
    }
}
//最后我们输出看下结果和我们预测的一样不
System.out.println(Arrays.toString(ary));

这里的倒序比较很像冒泡,只不过是反向的,且有条件进行约束。需要注意的是第一次的交换10<13,所以位置不需要动,这时候已经排好序的部分就是第0,1位。

二分查找排序

原理

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

前提:

  • 顺序存储结构,比如数组
  • 已经实现了排序

线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意:这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点)

顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的结点存储在物理位置上相邻的存储单元中,顺序存储结构的主要优点是节省存储空间。结点之间的逻辑关系由存储单元的邻接关系来体现。

查找过程:假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

在偶数表中,middle这里采用的是使用前一位的值,其实选后一位的值也是可以的,无需介意。

我们来试着写出代码:

    //根据元素查询对应的下标
    public static int search(int[] ary,int tar){
        int start = 0,end=ary.length - 1,middle;
        while (start<=end){
            //确定中间位置的下标
            middle = (end - start) / 2 + start;
            //比较middle的元素与目标元素是否相等
            if (tar == ary[middle])
                return middle;
            else if(tar > ary[middle])
                //从while处重新开始查找
                end = middle - 1;
            else
                //从while处重新开始查找
                start = middle + 1;
        }
        return -1;
    }

注意:有人在计算middle的时候会采用middle = (start + end) / 2的方式,在数组长度不大的时候,这也是可以的,但是有个问题,如果start和end值过大,就会导致start + end超出作用域,middle就和原值不一样了,为了防止这种情况的出现,采用middle = (end - start) / 2 + start。

为什么要加上start呢?前半部分start=0,加不加都是一样的,查找的部分如果是后半部分,就需要加上start的位置了。

结语

算法的出现是为了提高生产效率,我们在实际开发中很多时候并不需要直接写着几种方式,API已经写好了,我们只要调用API就可以完成排序,但是其中的道理我们要知道。看到这里,这几种常用算法的原理想必你已经清楚了,回味一下,尝试自己通过理解来写一写吧。

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

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

相关文章

Spring Security:PasswordEncoder密码加密匹配操作

目录 PasswordEncoder SpringBoot&#xff1a;注入BSryptPasswordEncoder实例 BSryptPasswordEncoder详解 父接口PasswordEncoder BSryptPasswordEncoder及其使用 成员方法 SecurityUtils安全服务工具类 测试代码 PasswordEncoder PasswordEncoder是Spring Security框架…

51单片机学习笔记_4 IO扩展:LED 点阵

IO 扩展(串转并)-74HC595 前面接的一些输入输出设备都是直接连接的单片机 IO 口&#xff0c;单片机仅有的 IO 口非常有限。而使用 IO 扩展可以大量增加可使用的端口。比如后面要使用的 LED 点阵&#xff0c;8*8个格子&#xff0c;使用扩展 IO 输入就更为合适。如果多级联一个&…

20230102单独编译原厂RK3588开发板的开发板rk3588-evb1-lp4-v10的Android12的内核2

20230102单独编译原厂RK3588开发板的开发板rk3588-evb1-lp4-v10的Android12的内核2 2023/1/2 21:01 《RK3588_Android12_SDK_Developer_Guide_CN.pdf》 原厂的开发板rk3588-evb1-lp4-v10单独编译内核的方式&#xff1a; cd kernel-5.10 export PATH../prebuilts/clang/host/lin…

educoder数据结构与算法 队列 第1关:实现一个顺序存储的队列

本文已收录于专栏 &#x1f332;《educoder数据结构与算法_大耳朵宋宋的博客-CSDN博客》&#x1f332; 目录 任务描述 相关知识 编程要求 测试说明 AC_Code 任务描述 本关任务&#xff1a;实现 step1/SeqQueue.cpp 中的SQ_IsEmpty、SQ_IsFull、SQ_Length、SQ_In和SQ_Out…

ceph集群搭建

一、环境准备 1.1、服务器准备 操作系统服务器IP服务器规格centos7.6192.168.161.114C/8Gcentos7.6192.168.161.124C/8Gcentos7.6192.168.161.134C/8G 1.2、服务器环境准备 1.2.1 更改主机名并添加映射 更改主机名 [rootlocalhost ~]# hostnamectl set-hostname ceph01 ##或…

内存池算法简单剖析

为什么要引入内存池算法? 我们知道C/C 语言中通过 malloc 调用 sbrk 和 mmap 这两个系统调用&#xff0c;向操作系统申请堆内存。但是&#xff0c;sbrk 和 mmap 这两个系统调用分配内存效率比较低&#xff0c;因为&#xff0c;执行系统调用是要进入内核态的&#xff0c;这样内…

区块链知识系列 - Oracle预言机

Oracle 预言机 区块链外信息写入区块链内的机制&#xff0c;一般被称为预言机&#xff08;oracle mechanism&#xff09;。 借助预言机外界的数据得以灌入链内, 使得DApp的玩法更多样. 比如DApp倚重的随机数, 可以考虑让一个硬件产生真随机数, 通过Oracle,定时灌入, 这将更公…

单机Docker部署应用Kraft模式的Kafka集群

单机Docker部署应用Kraft模式的Kafka集群1 Docker镜像准备1.1 下载Kafka1.2 配置容器1.3 修改kafka配置2 部署Kafka集群2.1 启动节点容器2.2 生成一个 Cluster ID2.3 格式化存储目录2.4 启动kafka服务3 知识3.1 控制器服务器3.2 进程角色3.3 仲裁投票者3.4 Kafka存储工具3.5 缺…

久泰新材料在港上市申请失效:年亏损超2亿元,崔轶钧为董事长

近日&#xff0c;贝多财经从港交所了解到&#xff0c;内蒙古久泰新材料科技股份有限公司&#xff08;下称“久泰集团”或“久泰新材料”&#xff09;在港交所的上市申请材料&#xff08;招股书&#xff09;已“失效”&#xff0c;目前已经无法正常查看或下载。 其中&#xff0c…

Hack the Box CTF 网络流量分析 中等难度 Penetrated | Wireshark

这是一道Hack the Box网络流量分析题&#xff0c;中等难度&#xff0c;题目本身就是一个 pcap 包。 1. 题目&#xff1a; 原文件链接如下&#xff0c;有兴趣可以自己先看一看&#xff1a; 链接: https://pan.baidu.com/s/16KLwQuoYA1AfEwuK78bBWg 提取码: 8864 Flag 格式&am…

Nginx内存管理源码剖析注解

文章目录Nginx内存池总览内存池中变量类型定义创建内存池&#xff1a;ngx_create_pool内存池分配空间&#xff1a;ngx_palloc小块内存空间分配&#xff1a;ngx_palloc_small创建小块内存池&#xff1a;ngx_palloc_block大块内存空间分配&#xff1a;ngx_palloc_large<br /&g…

【电动车】主动配电网多源协同运行优化研究——大规模电动汽车的蒙特卡洛模拟(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

TiDB问题排查

TiDB 集群问题导图 1. 服务不可用 1.1 客户端报 "Region is Unavailable" 错误 1.1.1 "Region is Unavailable" 一般是由于 region 在一段时间不可用导致&#xff08;可能会遇到 "TiKV server is busy" 或者发送给 TiKV 的请求由于 not leader…

JMM内存模型

借鉴&#xff1a; 一文带你搞懂JMM内存模型和JVM内存区域_Apple_Web的博客-CSDN博客_jmm内存模型和jvm内存模型的区别 面试官问我什么是JMM_java技术爱好者_R的博客-CSDN博客_jmm Java内存模型 概述 Java内存模型(即Java Memory Model&#xff0c;简称JMM)本身是一种抽象的…

箭头函数带来的this变化实例

1.不使用箭头函数时 let Lesson {site: 后盾人,lists:[js,css,mysql],show: function (param) { console.log(this);// {site: 后盾人, lists: Array(3), show: ƒ}return this.lists.map(function(title){console.log(this);// Window {window: Window, self: Window, docume…

17. 老板让我手动控制网页渲染速度,说这能反爬虫?我信了。

手动数据延迟加载&#xff0c;真的可以反爬虫 爬虫训练场项目&#xff0c;加速更新中&#xff0c;专栏清单参考 pachong.vip 本次案例需要的代码量特别小&#xff0c;所以咱们再 Nginx 中也进行一下相关配置 文章目录页面逻辑实现接口逻辑实现延迟实现&#xff0c;time.sleep()…

2022年需求最大8种编程语言!(详细解读)

DevJobsScanner 在过去的 14 个月&#xff08;从 2021 年 10 月到 2022 年 11 月&#xff09;中分析了超过 1200 万个开发人员职位需求&#xff0c;并从其中挑选了明确需要编程语言的工作机会&#xff0c;得到了 2022 年最受欢迎的 8 种编程语言。 目前市场中需求最高的前八位…

数学建模学习笔记-算法(线性规划模型)-上

目录 线性规划问题 线性规划的matlab标准形式 解析 目标函数 约束条件 使用matlab的linprog函数来进行求解 线性规划问题 数学规划&#xff1a;安排现有资源安排生产&#xff0c;以取得最大效益的问题。 线性规划&#xff1a;目标函数和约束条件均为线性函数 在一组线性…

2023/1/2总结

今天AC了三个有关二叉树的题目&#xff1a; P1827 [USACO3.4] 美国血统 American Heritage_lxh0113的博客-CSDN博客 https://blog.csdn.net/lxh0113/article/details/128522831?spm1001.2014.3001.5502 P1030 [NOIP2001 普及组] 求先序排列_lxh0113的博客-CSDN博客 然后学…

web基础标签

标签分类&#xff1a; 文本标签&#xff1a; 文本标题标签&#xff1a;h1---h6 段落标签&#xff1a; p 水平线&#xff1a; <hr/> 换行符&#xff1a; <br/> 转义字符&#xff1a; 注释标签&#xff1a; <!--注释内容--> 无语义标签&#xff1a; 语义标签…