00:00
我们接着给大家来举另外一个案例,这个案例呢是数组的复杂使用,叫数组反转。那么现在呢?要求是这样子的,随机生成五个数。并将其反转打印。注意听啊,随机生成五个数,并将其反转打印,那么我们呢,来把这个题给大家完成一下,它也是一个题嘛,所以说我就把它直接放在我们第四一个案例里边去,大家注意听,这个呢,相对来说稍微复杂一点啊,这是一个复杂的复杂的一个应用,那么我们来看一看这个题怎么做。老规矩,我们呢,先把题的要求放这儿,然后我们来分析这个思路。第一步,首先他说随机生成五个数。大小在我们勾浪里边用什么方法可以随机生成数呢?有印象吗?是不是要用到一个叫做RAn.int n的这个函数?
01:04
是不是这是一个函数吧,我们来看这个函数是干什么的啊,这个函数你要知道,打开我们的百度里面输入go。够让官方文档。各官方文档,进到这个文档里边去打开,这里面有一个包包叫什么呢?叫做。Run这个包啊,没有直接有,它是在mass run,它是me run这个包进去这里面呢,有一个函数。叫什么呀,大家看到这看书。其实它准确的讲啊,准确的讲它是在这大家看到没有,有个in n点进去,它说这个呢,会返回一个什么呀,返回一个。零到N的随机随机数。而且呢,它是大于等于零小于N,也就是说N取不到这个呢,无所谓对吧,这个无所谓,那么我们这边就用这个函数了,能理解吧,就用它,这是第一步我们要用到的第二个。
02:04
第二个第二步,当我们得到这个数的过后呢,我们把这五个数放在一个数组里边去。当我们得到随机数后。随机。随机。术后就放入到。放到。放到哪里去呢?放到一个数组中。好,数组中就可以了,那数组呢,我们就用int数组就完了啊,我们就用int数组,数组就完了。好,这是第二步。第三一步问题来了,人家的要求是将其反转打印。走吧。怎么反转打印好,同学们这个时候就要求我们对这个数组进行一个。进行一个这个,呃,分析了,怎么样才能反转打印呢。就是说你要把最前面的,把后面的打到前面去,把前面的打到后面去,这个地方就是有点麻烦的,就是反转打印怎么处理。
03:06
反转打印,请大家思考。我们这样子啊,我们先留一个问题,让大家先思考着如何反转打印,那老师呢,先把第一个和第二个先把它完成了再说,然后有了数组过后,我们再来说如何反转打印好不好?来走吧,那现在呢,因为我要生成五个数,我得有一个数组,所以说我先声明一个数组。这个数组呢,可以存放五个数,这个没问题吧,那就是。In而三好吧,五。In,好,这个时候呢,就生命完了,然后我们for循环一下。一。因为我要生成五个嘛,所以说我就循环五次,每次生成一个随机数。那就是那。然后呢,INT3没没问题吧,然后I加加。哀加加,哀加加完了以后,我们就往这个数组里面放东西。
04:04
走诶,这方是占多了,把这个数组拿到,然后呢,D个数怎么写ran点。好,刚才呢,我们说这个函数叫int n。好,那么100,那这个时候就会随随机生成一个什么呢?就是大于大于等于零,就是在这个数啊,这个数随机数就是大于等于零,并且小于100这个数之之间。好,我们把这个数打印出来看一下是不是跟我们想的一样呢?PTPTFPT就这样输出就可以了,好吧,二三,然后这个地方显然你用到这个round过后呢,你要引包包,我们引个包,不然的话肯定要报错,对吧,我们是mass。下边math下边有一个包叫re,我们保存一下先。
05:02
看这个时候有没有报错。有报错吗?好像没有报错是吧,没有报错我们执行一下看。跑起来。我们可以看到。哦,对方应该是打印了,但是上面因为我没有换行。好,再来。跑一个。同学们先来看啊,大家看。这个的这个时候的的确确生成了有五个数,8187475981,但是我们会发现它是随机生成的,这五个数呢,你会发现一个非常奇怪的问题,什么呢?大家看。就是当我每次执行的时候,这五个数都是一样的,大家有没有发现这个问题啊,大家看上面第一次运行是这五个数,下面呢,执行还是这五个数那。
06:00
虽然这五个数的的确确是随机生成,但是每一次都是一样的。这个是为什么呢?告诉大家一个原因,注意听啊,这里面呢,有一个手册里面写的很清楚,他是这样讲的。他说这里面呢,有个叫做seed。CD,这个CD是使用给定一个CD来初始化生成器到一个确定的状态,也就是说。如果你不给它设置一个seed。这个值,这个是int值,这个值如果说你不设置它有一个默认值,那么这个默认值只要一旦固定的,它永远都会生成这样五个数,你不管怎么运行,它都是8187475981。你看我再次运行它还是个数,就是因为你给的这个种子。是个默认值,其实是没有变化的,那么这个种子一旦不变化,它生成的随机数也是不会变化的,能理解吗?
07:01
那问题来了,苏老师,那我怎么给他一个总子没问题,我们想一想,怎么给他一个总子数呢?我们突然想到是不是我们学过前面的日期和时间函数,如果我给他一个当前的描述,诶,这个问题不就解决了吗?我给他下个种子来。追听讲追听。为了每次。每次最新,每次生成的。生成的这个随机数不一样。不一样,我们需要给一个C的值。而且这个C的值呢,也要每次不一样才可以,好吧,那这个就简单了,就是run.c。然后我给他一个时间,大家还知道怎么获取当前的这个unix的时间戳吗?别忘了啊,应该是time no。
08:00
点unix还记得吧,Unix UN unix也写错啊,Unix这样写的是吧?好,我们这样一写你们会发现,诶这样子就比较OK了。诶,怎么还有问题。哦,是不是我忘了引包了,看他这是怎么提示的。哦,On time,那就说我这还忘了一一个time。Com这个包没引进去再保存。在保存过后呢,我们发现没有报错了,是不是没有报错好那就没问题,我们再直接执行,我们可以看到此时此刻,诶你看这次生成是613259,我再来跑一次。再跑一次啊,同学们。诶七五一十八,七五十八,是不是这个时候就怎么样随机了。但是我告诉大家啊,嗯,这个方式虽然好,虽然虽然没问题,但是还是有一点风险,就是如果你在同一秒。注意听,如果你在同一秒生成随移速的话,那这个。
09:02
这个生成的还是一样的,因为unix是按照当前的秒数,所以说它这个种子呢,如果说你在同一秒,同一秒钟你生成的100个随机数,那我告诉大家这100个随机数都是一样的,因此这个还是不够OK,所以说我们突然想到,如果能把这个种子下的更好一点呢,其实应该给他一个纳苗。还记得我们先讲日期和时间函数,是不是说过这个过去那秒啊,大家看是不是在这里面有一个这个时间unique time找一个啊。我们找到time。Re。A round。Int。是不是?好,我们点一个time,它有个time,我们把这个time找到吧。Time在哪里?他们是不是在这儿啊?点进去这个time里面有个时间叫unix纳秒,是不是用这个更好一点啊,因为这个呢是精确到纳秒了,大家知道那秒一秒等于1000。
10:08
1000这个呃毫秒,1000毫秒等于1000微秒,一微秒等于1000纳秒,那你如果是纳秒的话,那绝对这个这个时间就就分散的比较比较广了,所以说我们最好呢,用这个纳秒好不好,用纳秒更好。哎,这个呢,更更好一点,那你看这时我们一直行对吧,每次生成的也是不一样的,是看。对不对,每次生成的也是不一样的,你看282344410不一样吧,对不对,好所以说用这个更好一点,更好一点,好当我们有了这个之后,我们接着来完成第几步,第三步反转打印,那同学们想一想,你现在产生的数组是这样子的,441046。三五,那我们要做的事情其实非常的简单,你只需要怎么样呢?
11:01
把这个数。在打印的时候给他进行一个交换,我们交换交换,交换一下这个数组不就完了吗?就是让44和55进行交换。让这个十和34进行交换。而这个46不变。他想,诶,但是当我一分析,是不是大家已经有思路了。是不是就是倒数第一个,注意听我这句话,倒数第一个和第一个交换,倒数第二个和第二个交换。一共交换多少次呢?那第三次你刚好这个只有一个有自己跟自己交换没有意义吗?是不是刚好交换的次数是你的这个数组的大小除以二啊。诶是不是这样子的,你看啊,你一共有五个数,五除以二等于多少,是不是等于二,但是有时候是等于2.5,但是在勾浪里面它不取整吗?就等于二是不是我就只需要交换两次。
12:04
如果我是六个数,所以如果是六个数,是不是六除以二等于三啊?哎,同学们有没有发现它交换的次数刚好是它的这个数组的大小除以二,然后交换的时候是倒数第一个和第一个交换,倒数第二个和第二个交换,以此类推。思路赢了没有?其实很简单,好分析,其实就这么一点。好,我们来进行交换,交换的时候其实非常简单,交换的次数分析出来了,交换的次数。交换。的次数。次数是什么呢?是这个数组的大小除以二。是不是这样子的,而且每次是这样交换的,是倒数第一个和第一个第。一个元素交换。元素交换。对不对,然后倒数第二个,那这个我就。
13:02
专题拷贝倒数第二个。倒数第二个和第二个元素交换,依次类推,这不就完了吗?那我来交换一下。来交换。把刚才这一个分析的思路给我拿过来。这个有什么难的,来走一个for循环。For循环交换的次数是不是刚好是它除以二?是不是这么多次数好交换的时候我定一个临时变量。我这定一个临时变量好不好,Temp我默认给他一个零。这个是一个交换变量,这个是用来做交换的,就做一个临时,临时变量,做temp呢,是干什么呢?做。做一个临时变量。变量OK,用于交换,做一个临时变量。好,我就不写那么多了好不好?大家写了temp,首先我们交换的时候,前面讲过,先把倒数第一个的元素给我保留到这去,这个没问题吧,倒数第一个怎么写?
14:06
倒数第一个元素是不是就是这个数组?他的这个嫩。是不是它的这个长度减去一个一,因为因为因因为你减去一个一才是倒数第一个嘛,如果你不减一的话,是不是越界了呀,然后再减一个I,为什么要减I呢?因为你循环第二次的时候,不是这个I就变一了吗?再一减诶刚好是倒数第二个。是不是因为你要考虑一个动态的变化,好这个就是交换,交换完了过后再把这个字。进行交换,把第一个值给它放过去,能理解吗?第一个值就是三,第一个值是不是就是I呀?但下一次的时候,第二个字了。以此类推,做完了过后再来做一个动作,怎么样?再把这个值temp放过去,是不是这样子又把倒数第一个交给了?
15:00
第一个,当它I等于二的时候,就是把第二倒数第二个交给他了,以此类推。是不是这样子就交换完毕了,能看懂吗?再看看啊,这个是相当于是倒数第一个和第一个交换。就倒数第这样说第N个。和第N个元素交换能能理解吗?就是下面这段代码,就是完成这个事情。啊,就是倒数第N个啊,这个我就不写了吧,这也也挺简单的,并不难,其实思路分析到这个地方,同学们应该能够理解啊,并不难。但也就是说这个这个不是倒数的倒数的元素吗?先把它保存到一个临时变量,再将正数的第几个元素复制到倒数的第几个元素去。对不对,然后再把刚才你保留的倒数的第几个元素的值交给正数的那一个对应的元素,不就完了吗?能理解吧,好,做完了之后我们再来。打印出来好,我们两次打印啊,第一个呢是在交换前。
16:04
就是,呃,就是交换前吧。交换前。对不对,交换前是这么一个情况,还有一个交换后,我们看看交换过后是不是对的,交换后。那你。干湿路。那同学们,我们看交换前和交换后是不是?成功了,跑一个跑起来。同学们可以看到。O。交换前和交换后为什么不一样呢?我们看这地方是问题在什么地方。OK。是不是这个地方产生这个纳秒,诶不对呀。我们来看问题在哪里,我们来看看问题在哪里。分析一下这个思路,看代码错在哪个地方了,有问题的地方。嗯,同学们有有没有发现我这方是写是不是写错了呀,我把这个写成二瑞几了,是不是二,因为你你是针对二三来操作的嘛,对不对,那你这应该写二三,其实这个地方是不是也应该写二三呢。
17:11
你不然的话,你你自己就混淆在里面了嘛,是不是好再来跑一个。好,我们再来跑一个,看代码有没有问题。好看代码。我们可以看到此时此刻就没问题了,大家看这里。你看交换前是六三五零二八五十这个地方是十八十五二五十五十三没问题吧。肯定是对的,好,交换完毕,那交换完了过后呢,同学们。我们这段代码的这个分析就OK了,大家看能不能理解。大家看能不能理解啊。能理能理解。好,那如果说这个能理解,我把这段代码呢,给同学们再整理一下,大家看我们这里有一个问题,用的不是很舒服,就是这大家看这个长度,你看我。
18:05
计算了几次啊,一次两次,三次四次,太麻烦了。如果这样做的话呢,我们程序的效率会有影响,因为嫩它总总归是一个。内建的函数,那内建函数每次去调呢,它是比较耗费资源的,大家都知道我们调一个函数都会开辟一个对应的独立的数据空间,很耗费资源,那这样的话,反正这个值都是固定的,那何不把它先。算出来,然后做一个变量不就完了吗?是不是这个道理啊,因此我要做这个事情呢,我复制一下。然后我单独的把这个论算出来,能理解吗?长度。等于它,诶如果这样做的话,我把这个嫩直接把替换了,大家看这个地方换一个。对不对,画两个。好,这个地方是不是也可以换。对吧,这个地方也可以换,诶大家看这样用起来是不是比刚才更清晰了,或者说效率更高了。
19:07
你看我先把数组的长度求出来,然后在需要用到长度的时候,直接用这个变量来进行这个处理就可以了。对吧,好,这个呢,我们再来看一下对不对,我把这一个输出稍微的做一点变化,注意听我为什么要做一个变化呢?就是我希望能够看到的确是输出修改过后的代码,这是个开发经验技巧。来,走一个跑起来。当我们一跑起来,我们发现,诶看是不是仍然是OK的,463178634348673146完全的正确,好同学们,那关于这一个叫做相对复杂的一个叫数组的反转打印,我们就给大家分析到这里啊代码呢也全部说完了,大家看看能不能理解。好,我把这一段代码给同学们整理,然后呢,放到我们的相应的笔记中去。
20:07
我们做一个板书。同学们自己要去独立完成,就说老师写完一遍过后呢,如果你理解了。我建议同学们啊,或者是要求同学们怎么样呢,自己再敲一遍好吧,这样你才能把go浪的语法。包括它的一些数组的应用的一些细节,才能真正的掌握好同学们,那关于我们这一个叫数组的一个反转复杂应用呢,就给同学们介绍到这里。好,这个复杂。应用。OK,好,那关于这块我们就先说到这里。
我来说两句