我对排序算法的理解

news2024/11/17 13:27:45

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

我明白我的问题,就是感觉自己懂了,其实,还是不懂。只要逻辑乱一次,就基本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.coloradmin.cn/o/814393.html

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

相关文章

词典项目练习

思维导图 客户端 #include "head.h" //用户提示界面 void help_info1() {printf("\t-----------------------------------------------\n");printf("\t| HENRY 在线辞典 |\n");printf("\t|版本:0.0.1 …

官方实锤!AMD真的已经有了大小核:不搞Intel那一套

Intel 12代酷睿开始引入大小核混合架构&#xff0c;多核跑分提升立竿见影&#xff0c;在游戏、渲染等场景中也有很好的辅助作用&#xff0c;但因为大核心、小核心基于完全不同的架构&#xff0c;需要复杂的系统、软件调度配合&#xff0c;也直接导致失去了AVX-512指令集。 AMD也…

解决多线程环境下单例模式同时访问生成多个实例

如何满足单例&#xff1a;1.构造方法是private、static方法、if语句判断 ①、单线程 Single类 //Single类&#xff0c;定义一个GetInstance操作&#xff0c;允许客户访问它的唯一实例。GetInstance是一个静态方法&#xff0c;主要负责创建自己的唯一实例 public class LazySi…

浅析hooks,复杂前端业务解题之道

hooks 大势所趋 2019年年初&#xff0c;react 在 16.8.x 版本正式具备了 hooks 能力&#xff0c;同年6月&#xff1b;尤雨溪在 vue/github-issues 里提出了关于 vue3 Component API 的提案&#xff08;vue hooks的基础&#xff09;。在Vue3的组合式API出现后&#xff0c;githu…

VS2017配置Qt开发环境

VS2017配置Qt开发环境 安装Qt5.12.11安装Qt插件在VS2017中进行设置参考教程 安装Qt5.12.11 安装Qt插件 在VS2017中进行设置 参考教程 # Qt下载地址 https://download.qt.io/ # Qt安装 https://blog.csdn.net/jjxcsdn/article/details/125432165?spm1001.2014.3001.5506 # VS2…

【LeetCode】解码方法(动态规划)

解码方法 题目描述算法流程编程代码代码优化 链接: 解码方法 题目描述 算法流程 编程代码 class Solution { public:int numDecodings(string s) {int n s.size();vector<int> dp(n);dp[0] s[0] ! 0;if(n 1) return dp[0];if(s[1] < 9 && s[1] > 1) d…

Packet Tracer – 使用 TFTP 服务器升级思科 IOS 映像。

Packet Tracer – 使用 TFTP 服务器升级思科 IOS 映像。 地址分配表 设备 接口 IP 地址 子网掩码 默认网关 R1 F0/0 192.168.2.1 255.255.255.0 不适用 R2 G0/0 192.168.2.2 255.255.255.0 不适用 S1 VLAN 1 192.168.2.3 255.255.255.0 192.168.2.1 TFTP …

Neo4j文档阅读笔记-Installation and Launch Guide

安装&#xff08;Windows&#xff09; ①找到下载好的Neo4j Desktop文件&#xff0c;然后双击进行安装&#xff1b; ②安装Neo4j Desktop根据下一步进行安装。 启动 ①激活 打开Neo4j Desktop应用程序后&#xff0c;将激活码输入到“Activation Key”窗口中。 ②创建数据库…

牛客网Verilog刷题——VL44

牛客网Verilog刷题——VL44 题目题目解析答案 题目 如图所示为两种状态机中的一种&#xff0c;请根据状态转移图写出代码&#xff0c;状态转移线上的0/0等表示的意思是过程中data/flag的值。 要求&#xff1a; 1、 必须使用对应类型的状态机 2、 使用二段式描述方法 注意rs…

远程医疗技术的变革

目录 1.远程医疗的概念 2.远程医疗的发展历史 3.远程医疗的靠谱性 4.远程医疗的潜在危害 1.远程医疗的概念 远程医疗是一种通过通信技术&#xff0c;使医生和患者能够在不同地点进行医疗咨询和治疗的形式。它利用视频通话、电话、在线聊天和其他远程通信工具来实现远程诊断…

自定义一个仿拼多多地址选择器

前言 做了一个仿拼多多的地址选择器&#xff0c;但是与拼多多实现方法有些出入&#xff0c;大体效果是差不多的。废话不多说&#xff0c;先上一张效果动图&#xff1a; 开始 先说说本文的一些概念。地区级别&#xff1a;就是比如省级&#xff0c;市级&#xff0c;县级&#x…

理解复杂系统的关键:耐心

理解复杂系统的关键&#xff1a;耐心 复杂系统本质上是多面的、复杂的。它们通常并非被设计成一瞬间就能理解的。这对于自然发生的系统&#xff0c;如生态系统&#xff0c;和人类设计的系统&#xff0c;如高级软件或机械&#xff0c;都是适用的。这些系统是由多个组件混合而成…

【腾讯云Cloud Studio实战训练营】使用Cloud Studio迅捷开发一个3D家具个性化定制应用

目录 前言&#xff1a; 一、腾讯云 Cloud Studio介绍&#xff1a; 1、接近本地 IDE 的开发体验 2、多环境可选&#xff0c;或连接到云主机 3、随时分享预览效果 4、兼容 VSCode 插件 5、 AI代码助手 二、腾讯云Cloud Studio项目实践&#xff08;3D家具个性化定制应用&…

牛客网Verilog刷题——VL42

牛客网Verilog刷题——VL42 题目答案 题目 请设计一个可以实现任意小数分频的时钟分频器&#xff0c;比如说8.7分频的时钟信号&#xff0c;注意rst为低电平复位。提示&#xff1a;其实本质上是一个简单的数学问题&#xff0c;即如何使用最小公倍数得到时钟周期的分别频比。设小…

一夜卷走220万美元

* * * 原创&#xff1a;刘教链 * * * 号外&#xff1a;今天在「刘教链内参」发表了《内参&#xff1a;对传国内某DAO组织被刑事立案一事的分析》&#xff0c;欢迎关注公众号「刘教链内参」并阅读。 --- 隔夜比特币继续在29k上方盘旋。 表面的百无聊赖之下&#xff0c;各种土狗…

隐私保护之隐私信息检索

【引子】用户的隐私保护涉及多个方面&#xff0c;用户行为的隐私保护更是一个难点。周末读了一篇论文&#xff0c;https://cacm.acm.org/magazines/2010/4/81501-private-information-retrieval/fulltext&#xff0c;涉及了很多数学上的方法和概念&#xff0c;很是费劲&#xf…

Python--matplotlib基础绘图

前言 本章来说一下绘图&#xff0c;毕竟在软硬件行业&#xff0c;设备端的日志有了&#xff0c;前面也讲了抽取数据&#xff0c;怎么能不绘图呢。 在工作中&#xff0c;我也是经常会遇到研发有这样的需求&#xff0c;把数据整理出来&#xff0c;做成图&#xff0c;便于分析BUG。…

类变量和类方法

类变量和类方法 引入 思考&#xff1a;有一群小孩在玩堆雪人&#xff0c;不时有新的小孩加入&#xff0c;请问如何知道现在有多少小孩在玩&#xff1f; 静态变量内存分析 1、静态变量被对象共享 2、静态变量可能在堆中&#xff0c;也可能在方法区的静态域中&#xff0c;这…

Python中的类和实例是什么意思

目录 python中的类是什么 python中的实例是什么 python中的类和实例有什么区别 总结 python中的类是什么 在Python中&#xff0c;类是一种用于创建对象的蓝图或模板。类定义了对象的属性和方法。对象是类的实例&#xff0c;它拥有类定义的属性和方法。 通过定义类&#xff…

【Ajax】笔记-JQuery发送jsonp请求

前端 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>jQuery-jsonp</title><style>#re…