我对排序算法的理解

排序算法一直是一个很困惑我的问题,早在刚开始接触 数据结构的时候,这个地方就很让我不解。就是那种,总是感觉少了些什么的感觉。一开始,重新来过,认真来学习这一部分,也总是学着学着就把概念记住了。过了一会,让我重新来写这些算法,又变得不会。

我明白我的问题,就是感觉自己懂了,其实,还是不懂。只要逻辑乱一次,就基本oh my gad了。

然后我就看视频,找一些算法的更通俗易懂的一些理解。还是感觉差了些什么。

不过,最后还是找到一些自己的理解方式。

做关于排序的算法题:

首先你要明白它是怎么排序的。以选择排序为例:

 ok,我们知道选择排序就是每一轮寻找一个最小的值。

继续:看这个选择排序的过程,共进行了6轮、每一轮又进行了多少次比较?

这个问题,就是一个嵌套循环的问题:

写出这个循环的嵌套才能进行下一步:口诀就是外层循环表示行,内层循环表示列。我看了很对其它的解释,个人感觉所有嵌套循环,记住这个特点就足够了。

回到这个算法:

  //很明显,外层循环有6轮,那么外层循环的判定就是arr.length-1。这个很简单。//表示的范围就是【0~6】
for(int i=0;i<arr.length-1;i++){//内层循环表示列。for(){}
}

重点来了,怎么写内循环的问题!!!

这里一定要学好,因为不同的排序算法,基本上它的内循环都不同。但是它们都会存在一定的规律和共性。

我们在看这个算法。

每一轮都是找最小值。第一轮,从7个元素找;第二轮从6个元素里面找;第三轮就是5个。

那么内循环表示列:就相当于,第一轮7列(7个元素),第二轮6列(除第一个元素之外。)

for(int i=0;i<arr.length-1;i++){//内层循环表示列。//它的范围就是:0~6(7列)、1~6(除了第一个元素0之外的6列)、2~6(5列)for(int j=i;j<arr.length-1;j++){}
}

然后,循环嵌套的问题我们就解决了,基本上,选择排序算法我们的问题就解决一半了!

我们再来看不同排序算法间嵌套循环的共性:以插入排序的嵌套循环为例。

你可以自己尝试一下,写出这个循环的嵌套语句:

//6行,就是外循环6次
for(int i=0;i<arr.length-1;i++){//内循环,观察这个算法的要求。//第一行:从第二列开始和前一个比较。//第二行:从第三列和前面两个比较。//第三行:就是第四个,和前面三个比较。这里不太好画图,自己画一下图,就是一种滑坡的形状。//那么初始条件,我们可以设为i+1。(从第二列开始)。那么判定条件是什么呢?//第一次判定只比较一次,第二次判定比较两次,第三次就是比较三次。那就是j>0咯。//它的范围就是:1(和0比较)、2~1(和0,1比较)、3~1(和0,1,2比较)for(int j=i+1;j>0;j++){}
}

 这个算法和选择排序算法的嵌套循环的共性是什么呢?

重点在内循环。

我的理解是:

   在外循环 i表示行数,内循环 j表示列的前提下。那么一定会在内循环的初始条件或判定条件用到i,而且有且只能用到一次。要么i用在初始条件,要么用在判定条件。

比如:看选择排序的算法:
内循环:for(int j=i;j<arr.length-1;j++)
i用在初始条件。插入排序的算法:
内循环:for(int j=i+1;j>0;j--)
i用在初始条件。冒泡排序:这个很简单,就是从第一个往后面比较,小的往前,大的往后。
内循环:for(int j=0;j<arr.length-i-i;j++)
i用在判定条件。上面三个算法的外循环都是一样的。

我之前做这个算法题时,就这样写过:

错误的写法,选择排序:
for(int j=i;j<arr.length-i;j++)如果是这样写,那么它的范围就是:
0~6(第一轮比较和之前是一样的比较的比较7次)
1~5(这里只比较了5次)
2~4
3~3(到这里就结束了,不会运行。)
造成的问题就是:只有效比较了三行(也不是很有效,只有效比较了第一行)。后面三行就根本不会比较,只打印出来。
而我们需要比较是6行。和i的关系是紧密联系的!
故此:我得出结论,在排序算法或者嵌套循环有关,在内循环里面如果要使用i。那么只能使用一次。

故此:我得出结论,在排序算法或者嵌套循环有关,在内循环里面如果要使用i。那么只能使用一次。
 

欧克,关于循环嵌套的问题就到这。想自己训练一下,可以尝试打印9*9乘法口诀表,或者打印三角形的形状。这些都运用了嵌套循环。

在来看算法问题:

以插入排序的算法为例:

它的核心就是从第二个元素开始往前比较。你要从内存空间的角度去思考。这里没有涉及堆和栈,堆和栈也很重要,不过在面向对象的时候才会学习堆和栈的空间变化。

它的空间变化:只以前四个数为例。

原数据:56 、34、45、12、67、52、4
从算法是赋值的角度变化:
两两比较,小的排前面。在算法角度就是,两个交换了位置。具体变化:56、34、45、12
第一行:34 34 45 12 ~   temp=56
               34 56 45 12 
 第二行:34 45 45 12  ~  temp=56
                34 45 56 12 
 第三行:34 45 12 12  ~temp=56
                34 45 12 56 
                34 12 12 56    temp=45 
                34 12 45 56 
                12 12 45 56    temp=34
                12 34 45 56 

我们第三行的最终比较结果就是12、34、45、56、67、52、4。

那么就可以写算法了:

//外循环6行
for(int i=0;i<arr.length-1;i++){//内循环for(int j=i+1;j>0;j++){if(arr[j] < arr[j-1]){   //看上面的规律,是不是两两比较。然后小的排前面。temp = arr[j];arr[j-1] = arr[j];arr[i] = temp;}}Systemo.out.println(Arrays.toString(arr));  //打印每一行的结果
}

算法的主要问题在哪,主要就是j、j+1或者j-1这样的判断。不知道怎么用,会不会出事。这就是第二个困扰的问题。

这个问题解决了,基本上算法排序就比较容易理解了。

其实,关于j 、j+1这样的用法和嵌套循环也很类似。就是j+1的范围不能超过原来数组的长度。j-1不能小于原来数组的长度。超出了,基本上这个算法就出错了。

建议:打草稿咯,像我上面那个例子一样,去画一下内存的变化。就不会出错。

这里,关于插入排序的算法就很有意思了,它的核心算法从每一轮找最小的值,这个最小的值不能通过两两比较交换位置。(透露一下:通过比较返回索引值。直到找到最小的值所在索引,然后和第一个数进行交换。)

选择排序核心算法:

for(int i=0;i<arr.length-1;i++){//内层循环表示列。//它的范围就是:0~6(7列)、1~6(除了第一个元素0之外的6列)、2~6(5列)index=i;for(int j=i;j<arr.length-1;j++){if(arr[index] > arr[j+1]){index=j+1;       }}temp = arr[index];   //将第一个位置和找到索引最小的元素进行交换arr[i] = arr[index];arr[index] = temp;System.out.println(Arrays.toString(arr));
}

选择排序的算法去画画它的内存变化吧。

之后我会不停添加其它的算法来验证我的理解和猜想。暂时先写到这了。

补充:嵌套循环还有一个条件,在循环用的一个数组的情况下,内循环的范围不能超过外循环,外循环的范围不能超过原数组。

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

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

相关文章

案例|会展大数据服务系统 智能服务体系建设实践

根据相关的市场调查发现在国内进行的2000多个会展项目中&#xff0c;仅有15%的项目能够提供相关主题网站基本业务和服务&#xff0c;且提供的服务并不能够满足会展各方的应用&#xff0c;剩余的大部门会展项目信息系统构建的不够完善、技术性差、应用复杂等&#xff0c;甚至提供…

三、JVM-如何判断对象已死问题

内存模型以及如何判定对象已死问题 体验与验证 2.4.5.1 使用visualvm visualgc插件下载链接 &#xff1a;https://visualvm.github.io/pluginscenters.html 选择对应JDK版本链接—>Tools—>Visual GC 若上述链接找不到合适的&#xff0c;大家也可以自己在网上下载对应…

服务器的shell脚本

shell脚本语句可以执行linux的操作语句。 linux相当于网页&#xff0c;shell相当于java。可以解释编写执行逻辑。 shell的开头以&#xff1a;#!bin/sh 定义解析方式&#xff0c;不同的linuxe内核解释方式不同。大多数内核支持sh&#xff08;bash&#xff09;方式。 执行sh文件可…

输入筛选框搜索

文章目录 输入筛选框实现效果图需求前端工具版本添加依赖main.js导入依赖 代码 后端代码对应 sql对应 mapper.xml 文件的动态 sql 输入筛选框实现 效果图 需求 通过筛选框&#xff0c;选择公司&#xff0c;传入后端&#xff0c;后端根据公司名称去文章的内容中进行模糊查询 …

照片回收站是什么?恢复照片就靠这3招!

“我电脑里本来保存了很多照片&#xff0c;但我不小心给删除了&#xff0c;还能恢复吗&#xff1f;由于本人是个电脑新手&#xff0c;求一些简单的方法。感谢&#xff01;” 在照片拍摄后&#xff0c;很多朋友可能会选择在电脑上对照片进行保存。但是由于各种原因&#xff0c;电…

Simulink仿真模块-Signal Builder

目录 说明 实例 Signal Builder是创建和生成可交替的具有分段线性波形的信号组。 在仿真库中的位置为:Simulink / Sources说明 Signal Builder 模块允许创建可交替的分段线性信号源组,并在模型中使用。可以快速将信号组切换入模型或切换出模型,以便于测试。在 Signal Buil…

Linux【网络编程】之深入理解TCP协议

Linux【网络编程】之深入理解TCP协议 TCP协议TCP协议段格式4位首部长度---TCP报头长度信息 TCP可靠性&#xff08;确认应答&#xff09;&& 提高传输效率确认应答(ACK)机制32位序号与32为确认序号 16位窗口大小---自己接收缓冲区剩余空间的大小16位紧急指针---紧急数据处…

无涯教程-Lua - 文件I/O

I/O库用于在Lua中读取和处理文件。 Lua中有两种文件操作&#xff0c;即隐式(Implicit)和显式(Explicit)操作。 对于以下示例&#xff0c;无涯教程将使用例文件test.lua&#xff0c;如下所示。 -- sample test.lua -- sample2 test.lua 一个简单的文件打开操作使用以下语句。…

改进的智能优化算法定性分析:种群多样性分析(Analysis of the population diversity)

目录 一、智能优化算法改进种群多样性分析 二、GWO与IGWO种群多样性对比 三、GWO与改进的GWO1种群多样性分析 四、代码获取 一、智能优化算法改进种群多样性分析 为了验证所提出的IDMO中种群多样性的丰富性&#xff0c;我们使用下式计算本节中的种群多样性。这个式…

Java并发系列之四:重中之重AQS

上一期我们介绍了乐观锁&#xff0c;而乐观锁的本质即是CAS&#xff0c;操作系统提供了支持CAS修改内存值的原子指令&#xff0c;所以乐观锁得以实现。从软件工程的角度去看&#xff0c;虽然底层已经通过CAS实现了乐观锁&#xff0c;Java的底层已经在Unsafe这个类中封装了compa…

《Java极简设计模式》第02章:抽象工厂模式(AbstractFactoty)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

3.病人排队

【题目】 病人登记看病&#xff0c;编写一个程序&#xff0c;将登记的病人按照以下原则排出看病的先后顺序&#xff1a; 老年人&#xff08;年龄 > 60岁&#xff09;比非老年人优先看病。 老年人按年龄从大到小的顺序看病&#xff0c;年龄相同的按登记的先后顺序排序。 非…

flask中实现restful-api

flask中实现restful-api 举例&#xff0c;我们可以创建一个用于管理任务&#xff08;Task&#xff09;的API。在这个例子中&#xff0c;我们将有以下API&#xff1a; GET /tasks: 获取所有任务POST /tasks: 创建一个新的任务GET /tasks/<id>: 获取一个任务的详情PUT /t…

prometheus+grafana进行服务器资源监控

在性能测试中&#xff0c;服务器资源是值得关注一项内容&#xff0c;目前&#xff0c;市面上已经有很多的服务器资 源监控方法和各种不同的监控工具&#xff0c;方便在各个项目中使用。 但是&#xff0c;在性能测试中&#xff0c;究竟哪些指标值得被关注呢&#xff1f; 监控有…

appium自动爬取数据

爬取类容&#xff1a;推荐知识点中所有的题目 爬取方式&#xff1a;appium模拟操作获取前端数据 入门级简单实现&#xff0c;针对题目和答案是文字内容的没有提取出来 适用场景;数据不多&#xff0c;参数加密&#xff0c;反爬严格等场景 from appium import webdriver impor…

git 常用命令有哪些

Git 是我们开发工作中使用频率极高的工具&#xff0c;下面总结下他的基本指令有哪些&#xff0c;顺便温习一下。 前言 一般项目中长存2个分支&#xff1a; 主分支&#xff08;master&#xff09; 和开发分支&#xff08;develp&#xff09; 项目存在三种短期分支 &#xff1a…

Linux安装MySQL 8.1.0

MySQL是一个流行的开源关系型数据库管理系统&#xff0c;本教程将向您展示如何在Linux系统上安装MySQL 8.1.0版本。请按照以下步骤进行操作&#xff1a; 1. 下载MySQL安装包 首先&#xff0c;从MySQL官方网站或镜像站点下载MySQL 8.1.0的压缩包mysql-8.1.0-linux-glibc2.28-x…

快速WordPress个人博客并内网穿透发布到互联网

快速WordPress个人博客并内网穿透发布到互联网 文章目录 快速WordPress个人博客并内网穿透发布到互联网 我们能够通过cpolar完整的搭建起一个属于自己的网站&#xff0c;并且通过cpolar建立的数据隧道&#xff0c;从而让我们存放在本地电脑上的网站&#xff0c;能够为公众互联网…

分享 一个类似 ps 辅助线功能

效果图片&#xff1a; 提示&#xff1a;这里的样式我做边做了修改&#xff0c;根据个人情况而定。 //你也可以npm下载 $ npm install --save vue-ruler-tool特点 没有依赖可拖动的辅助线快捷键支持 开始使用 1. even.js /*** description 绑定事件 on(element, event, han…

通用商城项目(中)

金山编译器出问题了。下面段落标号全出问题了&#xff0c;排版也出问题了。懒得改了。 使用对象存储OSS&#xff0c;保存品牌logo 新建Module&#xff0c;提供上传、显示服务 有些不明所以的&#xff0c;按照steinliving-commodity配置了一通pom.xml 新建application.yml&…