马士兵-MCA-架构师课程笔记-二-

马士兵 MCA 架构师课程笔记(二)

系列 2:P49:redis合集:1、Redis的5大Value类型解析 - Java视频学堂 - BV1Hy4y1t7Bo

你就会就是如果你穿的东西特别大。

然后想导出在别的地方导入的话,这个可能要花费1年才100多好111 200块钱吧,不贵,在在座的都是这个身家,对不对,都是身份证的人对吧,嗯好了,今天要讲什么东西,这两天主要讲什么东西啊。

redis为主redis,那么,越发的现在这个rise重要性很强啊,这个尤其在现在找工作,面试和你工作中,他的这个地位是越来越突出了很强,很长的一个小一个小东东,就是一个小东东。

但是围绕redis可以讲的知识有一大票的值,从计算机最底层的通信io模型,到他的单机使用集群,使用分布式,然后解决分布式当中的一些事情,然后解决你这个整个架构当中的流量问题啊,缓存问题啊。

性能问题其实都离不开release这个小东东,然后之前让你们看过一个预习资料,我在这强调一点,没看过的,你回去必须要看这个预习资料,不要认为他预习俩搁这不值钱,这个预习资料当中有从源码编译,安装。

然后最主要的是讲到它的因果关系,为什么有这个redis,然后release一些简单的一个特征,以及最主要的一个环节是有一个关于io这方面的,尤其讲到了操作系统底层的n o b l o到多路复用。

一炮的一个发展历程,而且我们redis也好,然后n x要很多技术使我们都是依靠这种多路复用的好吧,这个预习是必须要去看的啊,必须必须必须要去看,就光这个预习你如果看完的话。

其实这些这块的知识都能让你在面试当中增加很多的分数,这是第一个预习资料,要看第二个,你对redis必须有一个认知,我们做一个小小的一个总结,然后总结之后,今天先说啊,今天今天要讲什么东西。

今天是主要围绕它的使用场景,release可以应用在哪些场景当中去啊,这个东西很值钱,很重要,这是我觉得专业当中相当相相对来比来说比较比较重要的一点,为什么,因为你在面试的时候,这个面试官都会问你啊。

你你用过redis吗,你用过,那你拿出来这是干什么用啊,啊以及你比如说咱们好多报名的小伙伴,以及咱们在座的都说还我,我现在这个之前做开发一直是传统单机项目,sm传统项目。

然后我感觉现在公司一一看招聘信息,就是要一些什么分布式的微服务的,然后这个项目我也没做过,好这个好担心啊,其实如果redis它的场景主要场景你会了的话,那其实把你的现在手头这个项目改一改。

那这个感觉就不一样了,出去面试的时候,其实面你项目的时候,你只需要说我在里边用了某一个技术,这个技术你了解的很透彻,方方面面很多场景都用它代替了曾经的简单的c l o d的话。

那这个时候其实你的感觉是不一样的,好吧,所以你要重视这个学习的过程啊,先走一个小小的总结,对这个开始使用之前,我们先对redis宏观上有一个认知,那么redis是一个什么东西,看过预预习资料。

我咱们一块回顾啊,redis是一个什么东西啊,是基于内存的,然后它的性能为王,它主要是性能为王,速度快,对吧,这是一个很简单的一个描述,另外一个呢它是基于建制对kv的,这样的一个存储模型。

然后呢它是单线程的,the worker,是单线程的,就是他的工作线程只有一个啊,然后呢它的io底层网络通信,i o就是它是支持多客户端的并发的一种注意听是并发的一种访问,是并发的访问。

并发是通过一炮这种多路复用来解决io的并发问题,因为有两个词有两个词汇,一个叫并发,一个叫并行,然后并行的另外一个反义词叫做串行,redis是能够解决io并发,但是还是串行的一种技术。

这句话能听出来刷波一,我看他有多少能听懂,就并发redis是一种并发的啊,但是它并不是并行的,它是串行的,有录播吗。

有咳咳咳,那么先就这一块,我先在使用之前,先把这块的整体的给再给大家说一下它为什么性能好,速度快,然后呢它的一些特点是什么,首先如果从拓扑模型来说,拓扑模型也就是说我们会有操作系统啊。

首先你要知道一个kernel内核,任何程序是和内核打交道,才能够使用我们的人的网络硬件等等,然后你有很多并发访问,这些客户端是并发的访问,并发的访问的连接到达看到之后。

然后又会有在qq里边会有很多的这种socket,然后我们的就有点小是吧,放大一点,现在可以了吧,然后我们的redis是一个只说他的worker线程,walker是单线程的一个单线程的一个redis。

一个worker,他工作的时候是怎么工作的,我们先从宏观上来说,就是你要了解一个程序的特征,它是如何工作的,第一件事情,redis在io上用到了内核提供的多路复用器,一炮,那你出去面试的时候。

最简单的回答方式就是用最简单一句话来总结的话,就是第一步,redis这个程序通过内核的一炮获得了,知道了有这么多并发的客户端当中,哪些客户端有实际的数据到达可读可写,这是第一步。

一定要把这事情的12345想明白,他的其他的模型,你才能才能接受啊,就是这个县城的工作的第一件事情,如果他写了一个死循环,每循环你的第一圈儿里边儿,然后他要做的一件事情就是先掉下一炮,然后这块儿没听。

就是这块如果你没懂的话,证明你预习资料没有看,回去看预习资料我都讲过什么是e破了,通过e炮先知道吧,比如有三个客户端,那知道说哎这里边有两个客户端已经有数据可读了。

那么redis就可以通过e炮知道有两个客户端,两个socket可以去读取,第二件事情,重点的事情来了,你的redis会通过自主的在这个单线程里边,下一步就会真正的去访问内核。

要先去一个一个的one by one的线性的串串行化笔处去去读取,我们的客户端的这个io里边的数据,就是读取数据是第二步,读取数据12,第二步,而且这个读取的时候先读一个客户端给你读进来,然后处理。

所以第三步是在它的这个单程里边,第三步是一个计算的过程,这个计算我用记得那个词来代表啊,那这里这边可能是客户端发了一个这个increment加一,或者是set get等等一些操作。

这个操作会在这个线程里边,第三步执行处理完之后呢,然后再处理下一个客户端,再去读取,总的来说有123633个步骤,这是他的一个拓扑模型。

这个能看出来是不一。

好吧,而且这一定要记住了,关于io上,在这儿一定要总结出一件事情啊,这个很值钱,你之前没有没有关注过,因为这个之前直接使用现成的,就光io上有两有两个阶段,关于io它是有两个阶段的。

第一个阶段是有没有数据的一个状态,就是一共有这么多客户端,连我那谁可以读,谁可以写这个状态,这是第一阶段,第二阶段是有我拿到了有状态的之后,我要去读写,读写io是第二个阶段的事情,这还小吗。

这样自自带就可以了吧。

这是第一个拓扑图,这是第一个拓扑图,更深的东西啊,更更完整的东西去看这个预习资料就可以了。

另外一张拓扑图,这是第一个拓扑,第二个拓扑图就是它的工作模型。

工作模型的详细的这个过程,就把第一个阶段获知一破的时候给它屏蔽掉,如果你还是有很多的客户端,因为你是单线程的,把内核也去掉了。

连内核里边那个多路复用器也去掉了,如果你的redis是单线程,那么它的串行化这个worker单线程是怎么工作的,如果redis是单线程的,如果在客户端当中用两个吧,有两个客户端,一个是c1 。

一个是c2 ,数据都到达这台计算机了,但是因为它是单线程,它不能并行的处理它们,它只能串行的,所以他的第一件事情是哎,我先去读取read,然后c一的数据先去读它的数据,读到我的这个进程空间之后。

读到程序里之后,第二件事情才是计算,计算是一,这个计算你可以decrement,increment,然后等等一些计算或者said get之类的,计算完之后。

第三步才是rc一给c一把c一处理的结果给他返回,处理完第一个客户端之后,因为它是单线程的,才可以处理第二个客户端,所以它叫做串行化,有问题的先别发,我把这个讲完之后,到我到时给你留出时间讨论啊。

其实问题我一会儿会帮你提出签证的问题。

那么用颜色也区分一下前面处理的一个客户端,用这个颜色,后面这个客户端用另外一个颜色,然后但是在所有的操作你去发现一个特征,这个特征当中其实像前边读写是关于io的,读写是关于io的。

只有中间计算才是属于什么,城区内部的业务逻辑的就能感知到吧,嗯嗯好,接下来接下来那这个模型是redis在六点x之前的,因为它只有一个一个线程,那这个县城现在如果你去理解的话。

要总结出几句话来,第一个就是串行化,然后他你对release的操作应该就是原子的,只要它是串行化的,你的操作就是原子的,这这句话能听出来,刷波一redis是单线程的,无论你有多少并发的客户端。

他们的操作都是挨个的去处理,挨个去处理,它们是串行化的,然后他们的每一个操作并没有别的线程干扰,所以每一个操作要么加1-1,他说了算,所以它是原子的嗯,那这样的一个处理模型,请问是快还是慢,是快还是慢。

在这种模型下是快还是慢,那么你是一个程序员,你是一个架构师,你是一个工程师,你要在不同的维度去看它,如果单这么盯着的话。

那这一个线程显然是有点慢了,因为他们没有没有并行,但是如果把视野和技术堆起来的话。

这个东西可能就会有一个快慢,没错,有人说对比,或者你要参照了,举一个例子啊,举一个例子,如果在我们的业务性当中,你类似于秒杀呀,或者是订单等等这一系列的行为啊,比如说啊我举个例子啊。

如果你用的是mysql数据库,然后呢里边有一个item,这个安卓的数值是99,然后在并发整个系统有并发的客户端到达,那么在并发变成高并发的时候,那你肯定是需要用负载均衡的技术。

也就是说曾经你只有一个server,一个tom cat,可以接受两个呃,这个比如这个100个客户端的并发,你的一个sol可以处理了,再多的话它处理不了,但是并发一旦变成200的时候,你可以怎么办。

你可以再来一个sol,能理解什么意思啊,啊用另外一台server去使,就使用负载均衡的技术,把你的客户端的数量均摊一下,这样的话你的系统的接入能力就能接进来了,并发接下来之后。

但是注意他们可假设200个人都想访问这一个商品,当想访问了一个商品的时候,其实最终是要和这个数据库里边这个数值进行一个计算的过程的,那么在这儿注意听啊,在这儿注意听。

当你这个服务层现在上看上去在高并发情况下,你的服务做了负载均衡,你感觉它是什么的呀,是不是并行的,因为读取他们发来的请求,这个处这个处理过程是并行的,听不出来刷波一大家一定要听得见,并发并行是两个概念。

客户端是并发的,有很多并发的请求过来了,但是处理它的时候,读取他们的请求,分析他们的这个请求头这个hp协议,然后拿出他们的u r i,然后调自己的这个contraction,这个这个过过程是并行的。

在并发情况下,但是一旦听这个200人,一旦听到这个数据的时候,那怎么他这个过程是什么呢,如果说两个一两百人都想减这个数值,减减这个数值的话,那在数据库上,比如说他查过了99select回来。

test select回来,然后他们各自在这减一,并行的去减一,注意听啊,是并行的去减一,然后回更回去,其实还是这个就变成98了,减错了能理解什么意思吧,那这个时候一般在业务性当中。

对于数据库这样的一个使用模型,想让它减对这个怎么办,就是其实你看似是并行的,最终它要让我们的这个使用数据库的时候使用悲观锁枷锁,悲观锁的呗,悲而且是悲观的,最最严苛的就是串行化。

也就是这个这个服务如果想改他的话,先锁住它开启事务,然后减对了,回根回去之后释放,然后他再去锁住它,然后它再把它处理完,那其实它依然是一个串行,但是这时候你的视角就不要看着这,这看这玩意儿。

如果刚才看这的话是并行,但是如果你看完整个通路的话,其实它是一个串行到这个环节,能听出来刷波六,好吧,那这里面其实既是串行,而且使用数据库的时候,中间还有事务所提交等一系列复杂的操作,而且数据来回漂移。

这个成本比较高,那么你只需要把它换成另外一个东西,我把他给留住吧,这张图给留住啊,如果这是这是数据库的。

是是这个样子,复制一份扔一边去。

这是关于数据库,如果换成redis的话,注意你前面负载均衡这个并行接受客户端的并发的这种请求,接下来的话依然是并行的,这些服务service层依然是并行的,然后但是把后边那个东东。

把my circle换成了release,换成这种工作模型的话,注意它本身就是串行的,因为它是一个线程,它并不是多线程的。

而且redis有一个特征,就是它是键值对的是有k有value,你对着它的value是有类型,且类型这个数据类型有本地方法,比如说increase decrease decrement就加减。

如果说想对着这个item把这个值99-1的话,那他们两个客户端可以并发的去发出decrement,但是在我们的release处理的时候,它却要串行的去处理,你虽然两个人同时并发的发过来了。

但是我只有一个线程,你有再多的i o我得200万的一个一个读取,读取一个减减下,读取一个剪下,所以它最终的计算结果依然是正确的,那么如果你再从全局去看的话,它其实虽然这是并行的。

但是整个对数值的计算的时候,因为它最后是一个线程的。

依然也是串行的,但是这个串行比上面那个串行在成本上是要快了一些。

听过来刷一波一,这种串行是不会让你在通缉当中有所谓的事物加锁,然后都能抢抢抢占这么一个过程,判断这么一个过程是基本是无锁的。

因为它本身就靠一个线程,这个串行让它自动马这件事情做好吧。

一步步进阶啊,一步一步的去进阶。

把这个东西想明白,这个如果能想明白的话,那翻回头来你现在可以接受了。

这个其实单线程这事儿挺美的啊,因为多线程这个事儿反而成本更高。

但是这时候这是他的肯定快,这事儿就确定了,但是他又一个弊端,请问b端是啥,就是redis,现在描述你描述的这样,你感觉这个挺好的,但是这种单线程它有一个不好的地方,这个单线程有一个不好的地方。

什么是是什么问题,阻塞不不不并不是这些东西,你要说阻塞还是没有听到刚才那个那个那个那个理论没错,你的硬件是多核的,多核心的啊,你的硬件是多核心的,有四颗cpu,那你这个单线程的话只能供在一颗cpu上。

那是剩下三个cpu就已经浪费了,然后这时候我前面讲的知识不是白讲的,我一再强调io的干这一件事情是分成两个阶段,一个是判断状态,一个是读取的e i o读完之后,第三个阶段是计算,计算和io其实是两两步。

两大阶段能解吧,这些阶段性就不其实这也也也想说一件事情在并行处理的时候,我们尽量的去怎么样,就是说让你写一个程序,你要不要使用多线程,你要不要使用多线程是怎么去,是怎么去去分分析这件事情的。

要不要使用多线程,其实你这件事情是一个事儿,还是多个阶段,尤其在多阶段的时候,把不同阶段给它用不同的线程,这个才是你多线程最应该做的,而且是效率提高最高的,这句话听不懂你就往下看。

曾经release只有一个县城,这个县城里既负责了io,又负责了计算,但是其实我可以用多线程,比如说他的工作线程还是一个工作线程,还是一个,我先把这个图先这么画的,然后再加几个线程加,比如再加两个线程。

那这两个县城叫做什么,叫做io thread,两个i o线程,那么i o线程已经上面这个叫worker线程,工作线程下面i o线程就是读取io,它不值得计算,那如果现在我的release有三个线程。

注意看我的release曾经是一个。

现在有三个了,还是这两个客户端,那他怎么怎么可以怎么去处理,其中让两个io线程可以并行的去读取不同的客户端在l流里的数据,先加载到我进程中间里,进程空间里先读进来,读进来之后呢。

然后我的工作线程比如说先去处理c1 ,那这个工作形成一个的话,他不可能并行处理两个计算,他只能先处理其中这个c一的读取到的数据,然后处理完之后,他肯定要给这个c写回返回这个结果。

但是返回的结果如果还是这个工作线程去做的话,那你这个线程独到的数据就得排队排到后边去,那怎么能提升这俩线程,别别耽误呀,然后让另外的线程负责去写出这个线程,让出来之后,他不能在这闲着呀。

恰巧刚才那个并行的另外一个线程io线程也读到数据了,那这时候工作线程可以接着干活,处理另外一个io独到的独到的结果,然后他处理完之后,然后才会让另外的线程给他写出去,到这步能听懂同学来刷一波一什么。

你什么时候应该使用多线程,你的事情可以有很多的不同的阶段,那我可以把不同的阶段分在不同的线程里边,儿阶段与阶段之间,这其实就组建了一条所谓的流水线,你去想工厂有一个流水线,流水线粗看上去是串行的。

它是一个流水线,是串行的,但是串行的阶段与阶段之间,比如说一个车上了路线,我第一个人装了门,给到第二个人去装轮子,但是我第一个人不用闲着,我可以在接第二辆车装门的,然后再给他第二个人去装轮子。

也就在第二个人忙的时候,第一个人也在忙,他们并行的,其实这时候是一种稳定性。

最终还是听明白你数数就可以了,如果这台计算机只有一个线程,它只会消耗一颗cpu,其他cpu闲着,然后这一颗cpu上的进程,这个县城里边要干一件事情,读读客单一,然后计算。

然后写扣单一就是1233步完成处理,第二个客户端,右三步一共是成本是六部,才能完成两个客户端工作的事情。

就这个他们发来的数据处理这个这个这个连处理再再再回送。

但是如果你改成了三个线程,注意听啊,如果你改成三个线程,如果你感觉现在我在就就在重庆,注意听,如果你redis有三个线程。

一个县城还是曾经的工作线程,他只负责计算用户发的指令。

然后另外两个县城,这三个线程是不是工作可以工作在三颗cpu上,第一件事情,三个线程是不是可以工作在三个三个cpu上,这,个能听懂的来刷波一,三个线程是不是可以工作在三个cpu上。

那么这时候其实它们就不叫并发,他们叫做并行了,对不对,一定要注意用用词准准确度啊,他们叫并行了,他们是可以并行做事的。

那只不过并行做的事情不不是一类事情,因为i o我说了两个阶段。

一个是读出来,然后再再干,所以呢工作线程依然是要去负责计算这件事情,他如果刚起来的话,不读取io这件事情,工作县城里边是没有什么东西可可算的。

所以先通过一炮知道了,说唉有俩客户端数据可以读了。

状态知道了,然后这时候这个共主攻内城通知另外两个线程说。

你连你你们各自有两客户端,有两个哦,有两个socket,有两个输入流,一个输入流,一一个一步一个一步带你们各自读一个啊,读到的东西先读读出来,放到这个堆里边,然后我就能看到了。

所以这时候另外两颗cpu是并行的,就是它们是并行的,并行读取了,两个i o里的数据到这步能听懂,同学来刷波一,这两个线程可以并行读取两个i o,他们先把读到的内容就放到堆里面了,放到队里之后。

然后其实我这个县城可以处理一个,再处理一个,对不对,哎,我挨个去处理,那处理完第一个之后,本来我是处理完,我还得就是给客户端返回。

是不是还得抬着走io,是不是我可以让我这个线程调了一个从ioe给他red写出去,我还可以通知另外一个线程,哎我计算完这个结果,这个对象放在堆里了,你把它给我输出,你你这个cpu在做这个io输出的的时候。

我这颗cpu的一个线程就可以处理,我堆里边另外一个队列里边另外一个数据,就等他咱俩之间是不是开始并行了,就这两步是不是也是并行的,这不是不是并行的哎,病情处理完之后,你这边i o无论你发的快慢以后。

你你发着我找这个完了之后,我还可以让另外一个县城走另外一个cpu,然后走内核交互去把我刚才那个第二个计算结果再给我发出去,但是其实他们之间也也因为他的时间轴可能很长很慢,发的东西比较多。

但是他也会和另外一个依然是一个并行的,压到两颗cpu上,现在能听懂了吧。

没问题了吧,那其实你数成本就可以了,其实总共来说一个并行一次,单独它计算两次,然后这是一个并行三次,然后这一个这一个他俩有可能并行,或者他已经处理完了,但是他最后他必须有他第三部完了之后他能写。

所以还是第四步,下边是四个宽度,上面是六个宽度,所以下边一定是用了用到了多核的能力,比上面这release这个模型一定比上面这个模型快一点。

好吧,那下面这种i o这种多线程的方式是注意是在redis 6点差。

redis 6点叉的版本当中会增加进来,然后其实它的增加进来那个功能叫做io surprise,io多线程,但是无论注意听啊,无论你的是六点差五点,差三点差二点叉,它的工作线程是只有一个的。

多路复用是另外一回事。

多路复用是一炮,知道哪些客户端一共有1万条路,里面只有两条路可以有数据,那这时候走到e后,多路复用器知道了哪些就是获取i10000 个io事件。

这个事儿服用了一个调用,就知道了哪些可以掉了。

然后这是状态的第一个阶段,i o的第一个阶段,我知道哪些可以用了,第二阶段我要读取这么多。

我可以单线程one by one的串行读取,我还可以让更多的cpu同时让他们独不同的socket io读过的结果,第三个计算我可以单线程计算。

我也可以多线程,但是我们说了单线程计算是串行化。

串行化它的成本相对低,因为多线程一定会限制到锁。

串进化是没有锁的,数据是最干净的,其实效率反而更高一些。

最后这个总结能听懂。

好吧这能听懂,然后在这儿还有一个点要聊一下,这是之前一个学生问的啊。

我在这多说一句,再来一遍大哥开视频吧,因为我这还得讲别的好多知识好吧,咱们这个课是有视频的,而且现在是11024的高清的啊,回去那个今天我讲完课后就能看到这个视这个这个视频了,在这儿聊一聊一个事情啊。

刚才我说了,它是串行的,然后你有很多的客户端,它是先计算c一还是先计算c2 ,这个计算的过程会不会混乱,会还是不会,会还是不还是不会,其实这是一个未知的,这一位置一定会混乱,一定会混乱,这是未知的。

为啥,因为你的程序只知道有多少个有哪些io,然后程序调度的时候,它指不定先读到哪个啊,我后读到并并不一定能也罢,而且这两个这两边时间都是这个这个这个不确定的,所以在这个处理它们的顺序的时候。

还真的有可能先处理c2 ,后处理c这个这个c了,就看他俩,因为他俩并且病的时候就是一到并一个分布式的时候,这事儿就没谱了,它不像串行,我必须一个一个来。

对不对,即便其实串行的时候,如果两个客户端,其实你串行这个我还是读的时候,我有有可能先处理c2 的,后处理c一的,所以先处理谁,这件事情不确定,反而这件事情还带出了一个新的一个知识,也是你们平常忽略的。

其实就拿不拿下边这个复杂的模型来说,拿这个简单模型来说,想你加入程序,其实每一个客户端对于我的redis来说是一个connection,是一个连接,这个用在这个知识点可以用到很多技术当中啊。

其实每一个客户端来说,对于我redis是一个connection,是一个独立的连接,那其实一个程序他在这两个客户端中处理的顺序的话,如果没有曾经没有自己明确的代码约定。

死必须按照他们客户端的那个标签属性维度,先处理谁,后处理谁,如果没有这部分代码的话,其实在处理的时候,指不定先读谁后读谁,也就是说连接与连接之间是无序的。

系列 2:P5:马士兵老师JVM调优:5.系统上线前预估系统的并发访问情况 - Java视频学堂 - BV1Hy4y1t7Bo

hello酷狗,带我去往在太久覆盖的地方转转,就像上集火影霜发射热白光灯演出来时的脚印,成长,我从狂野转停不下来,借人间第一枝抖开。

分明只是星辰,能耐窒息,是偏偏做琼台青纱,浊气的彩虹,笑开穿身,过一段时出真正清白风骨,犹在爱上过,有不能期待,哈喽哈喽,这老师声音的老师扣个一,听下声音,听下声音,哈喽,发射的好。

慢慢等待时的脚印长长,带我去了在大雪覆盖的地方,因为你总是不成故乡,连同这遗憾埋过于盛夏,无所情长思念,从上面传来,前来人间被挤出了白,他们做春华的世外梦想,千百天的可爱开始装新手了。

做空的少女可爱纯真,过一个书桌,正在清迈风,不要再心软的,开不动的情怀,人称雪蝶,如何,越来越,你是走一生来,那这一水的轻巧,然后虚妄对的幸福,美的地方抓紧去世,手机多影响此时的等,来时的脚印。

常常带我去,我们在早上覆盖的地方以后,一早是不上冬,夏能同这遗憾埋没于喧嚣,不诉情长,风吹飞舞,人造反,青春开合时传来,就像潜入水,天天纠缠一起上,那是边上的浮动,从一生被归还的伤,谁能溅起。

无数人说你我一分钟那样,make it go,let it,will make it,will make it,哈哈哈哈哈,嗯哼哼,爱的是非对错已太多,来到baby是我的长河,为何他的冲动。

她的寂寞不计较快,你有100万个有漏洞,快说不说,我以后最沉默,在做爱我,你不理我,关心自己过,说你不要太过纯洁,不必停留,你说我要青春都再来,我等到再遇到,我都不要再等候,自由啊,自由现在就要自由。

爱的是非对错已太多,来到没对错误的场合,快和他怂恿她的希望风起小丑,你有100万篇游乐,快说破,说破以后,接着我是否爱不爱我,你不理我,还是这结果,你说结果中间不必停留,你说我要一转头再来过。

难道女的都不要再等候自由自由,现在就要自由,我要看见无比重要,你说我要一转头再来过,难道女的都不要再冷漠自由自由,现在就要自由,怎么走的时候,我明明向往,就想着像天空,怎么也说不出口,等到我转过头。

发现你已远走,要脸上的人不住你都是一生,我曾经牵着你的手走在我前头,就像在那童话世界遨游,不能牵着你的手走到世界尽头,是我一生最美的山河,嘟嘟嘟嘟嘟,一个一个地一个人在游走午夜的街头。

我就像是一只无家可归的流浪狗,那时候我挽留你会不会回头,若时光能倒流,你是否愿意跟我走,我曾经牵着你的手,走在自我之中,就像在那痛的世界遨游,不要牵着你的手走到世界尽头,是我一生最美的伤口。

我曾经紧握你的手,总在发节奏,就像在那童话世界遨游,有解答,你的手足够瞬间尽头是我一生最美的伤口,嘟嘟嘟嘟嘟,不是我游荡在世界的尽头,遗憾的我真的不是你,你的手,情它总是让人痛,梦会变得很沉重。

谁不渴望有人懂能够陪我春夏秋冬,爱来匆匆去匆匆,人心变得越来越苦,谁能够一生相拥,却又害怕自我嘲讽,站在海角望春天,一路分手,如心中缠绵的心动,对你闪烁,勇敢试探春演的春晚,就这样的相遇,擦肩过。

将苍茫茫一片,看沧海,月刀相见,去赴烟灭,哀愁在胸口,眼泪喷溅的眼泪化作穿鞋太长,如何穿上身,爱来匆匆去匆匆,心变得越来越困难,越呼吸,能够一生伤过,却又害怕自我嘲讽,笑着在海角望着天。

已不再回首我心中缠绕的心动,对人小说,动感的视频,终点不见外,这个是给擦肩过珍,苍茫茫一片片,四海无月踏星界,曲风音乐哀愁在胸口,沿海天天在眼泪滑落,世界太君如何处置,生站在海之涯。

望着天一幕幕的再回首,我心中缠绵的形状,对谁说,燕山风雪路不是1000金的笑容,生生生地擦肩过千,草木皆平坦,四海未相见,去死念,爱就在身后,你看下自,燃起爱情如何去驰骋,天空色的假的啊。

ta key that is true,每天不是在打to me,oh keep going on at you,and i'm done,i'm more than,i do。

你所谓的正门朝阳好惨无力的四叶草,cuz,i'm b,流泪也不累也不累,交给交给turkkk,可爱情,我感动的不累还不累,绝不能过年的年夜奇迹就,那个回答一下弹幕孤风的问题啊,这,去查一下吧。

say baby,我关掉了,你说啊,也不能红绿灯的夜路骑个球,面对things,she to take more than you。

now make it up,my testing meeting of the way,could have in your,啊啊,嗯,真的,那里的天空被动还冷清,青色的回忆,希望踏上成长的旅程。

就到这颗,你就忘了,从晚你快回去想想有多点延续,再现过去,在一起才会出现失落的时候,只剩我一样,相信你自己,失眠焦躁的还是日常意义,要找个粉红的小天真一起做个梦,有一天我们会重逢故里。

世界最大的还是日常意义,一起交错,只有他自己,偏偏等100天晴,我们之间靠近你,对头发的不清白的回忆,她成长的旅程,请大丘丘的歌,你就不要送我,你快回去去想象,拥抱每一句,发现我去找你,亲爱的怪。

瞬间失落的时候只剩我一眼,相信你自己是谁,在做自然是假意,我早上最痛的小天真一起做过梦,有一天我们会重逢的,离世界就像温柔的水,一场莫须有,是奔着书来的是吧,需要就行了,东风吹倒了青衣,抽奖码能扫啊。

一会儿扫啊,哪个小姐姐哪个小姐姐都可以啊,世界充满了许愿一下想不想天真一分一分牛已经在路哪条路啊,要不是黄泉路,任何一条路都可以啊,所有人现在都在黄泉路上奔往黄泉的路上,一直活到死为止。

别忘记我们学习学数据结构与算法,刷题立刻就可以了,长清路,只要你开始学习了,你就在找新的路上,小九可以啊,一说感觉基本不会刷,先刷最简单的,不要刷那个中级和高级,先刷简单的,啊傻黑黑买了我的天,这个是。

是吧,众众众众智人中之一啥呀,这哪出题立扣,那算法课程呢,数据结构与算法有还能扫码吗,油可以,7。55开始扫,屏幕上写字,用什么软件软件软件硬件,屏幕画笔,你随便搜一个就可以了,请小仓鼠的小公主。

这喝水杯接广告啊,一直在你水的嘟嘟嘟嘟嘟嘟嘟嘟嘟,骑上我心爱的小,有没有人卖什么水的,才会比较乱了,你就当我是空中的光,这茅台多了吧,哎呦茅台把他当,我越离烦恼和忧伤,先看老师讲的算法。

你就会知道没有没有那么难,嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟嘟,骑上我心爱的小摩托,它永远不会堵车。

骑上我心爱的小摩托,我马上就到家,推荐的这两把,如果你要是愿意刷算法的话,要不是有你算法目前没有纸质版的,你只能去找pdf版,还有一本书红皮的算法,这本书觉得还是写得不错的,三番讨论就别看了,太难了。

计算机程序设计艺术超级难,这两本比较难,只有当你到一定程度的时候,到风清扬这个级别好,然后去学这个好吧,baby,you go away,i still,you're good,建筑会怎么样,可以啊。

那个好多厂子都直接从上面刷原题,也够懒的。

就算把各种我现在算法讲的不多,只讲了那个排序的算法,然后下一步准备讲二叉树,但是还没更到,主要是比较忙,最近然后一直没有更,因为算法这个东西是一辈子的事情,你恐怕这辈子都刷不完这些个算法。

所以呢我们慢慢跟吧,哎呀我已经回答你了,有只是更,但是只是更换初级的算法了,有时间的话再慢慢的更到中级高级,这n e s u s u a l8 比一二十来,觉得什么你的那么逗啊。

借不小龙g one的一点区,你不给设置的话,它是动态弹的,你要不你你也不要设,这样呢是要他要他要完成你的想象时间,你要给他射死了的话,他完不成了,就不要设那个啊,开了美颜都快认不出来了,对我告诉你。

这都是加了二二百多层滤镜的,这已经不算过分了,才200层。

那你看一个那个加300层滤镜的,这能认出来吗。

而且他说呢赶赴印章,老师结婚了吗,结好几回了,都都不知道啊啊您太胖了哦,袁鹏,不要停啊,好咱们7。55开始抽奖,然后8。5分开始准时上课啊,cs并发标记错误怎么产生的,这样一个对象失去赢。

怎么重新引用kd twenty one,你这个问题今天有时间给你讲讲,没时间就算了啊,书今天收到了是吧,ok,所以说那个32g再说一遍,大哥怎么能这样子呢,过两天那个很可能会有录播,你翻过头来看看。

看见了啊,159页啊,对这本书是159页,现在word写着我们的模板编辑比较好啊,你哪个方便用哪个呀,你在那个人家平台上,你就用人家的模板呗,你要发邮箱,你就用word呗,90抽奖了吗,抽了。

小莫读完之后有什么难理解,不难理解的东西都不值钱,咱们看看有没有得奖,8。05自动开奖,二维码挡住了,因为还没到07:55,抽奖被老师挡住了是吧,谁这么讨厌,挡住了,抽奖码太过分了啊。

昨天的都已经开讲了,能抽离一本书吗,目前的那本书还没有印出来,最关键是没给没给啊,看一下高并发的课程吗,可以啊,没问题,等小姐通知就行了,列车队和内存哪个好,没什么太大区别,不管怎么样。

你都是需要通过面试的,这不是有的卖吗,我看清目前没得买,主要是这个内容呢其实是我们讲课的一个整理资料啊,还没有说特别完善的时,弄一本书出来,今天刚变,阿里居然没问这位m,你是第几面,现在阿里就忙死了。

一面往往问的都比较简,单,得看你是第几面,一面实习,你开一面,大哥别着急啊,好多是死在三四面上的,你还没到死的时候,一面线都比较简单,super的公开课,等一会儿给你问问,周老师,抽奖时间到了。

哎呀你说的还真对哈,这个,这哥们是台湾的,哪个哥们是台湾的呀,支出者,刚刚的电商那里就能用的业务层里,对没错,起码你自己写线程池,这里用线程池来完成一些任务,应该是能用得上的,实习的,用繁体。

用繁体就是台湾道,没准人家就喜欢烦的,就特别烦,你也烦我也烦,吴亦凡,阿凡提,那是华为三遍,挂了,赶紧来学习,补充一下死在什么体上了,感觉生活好难,也不是,也不至于你可以用那个佛系的吗,反正我也不干活。

我就混吃等死啃老,每天躺床上生活就没那么难了,做一个巨婴,现在都用spring boot吗,师弟毕业2年大概多少k看人,还有这个这个这个毕业2年,这个毕业2年60万,所以分人,这东西老是忘了怎么办。

记在纸上,把要点记在纸上,没事贴,贴在贴在边上,没事看两眼,没事看两眼,然后等你去面试之前再看两眼,上厕所的时候看两眼,吃饭的时候看两眼,谁都会蒙都够,我好多事我都忘了,昨天讲的啥来着,忘了都。

为什么我的提问就是发不出去呢,对啊,我好像没看到你的提问,简历和你差不多,简历跟你差不多的话,那应该也是个60万左右年薪的水平,连体啊,推荐我们自己写博客吗,必须推荐,如果你们要有自己的博客。

整理自己的学习,或者呃去研究一些新的技术,那面试官老喜欢了,做的笔记也是乱七八糟,要用的时候老找不着,做做着做着就顺了,老师你的演技真的可以,德云社都齐,你咋那么逗啊,老师哪有演技,都没有演技。

你问啥告诉你啥,还有什么演技,老师会都是口技,一直做一条怎么样,你能承认你能接受一个不太高的一个薪水,就可以一点儿,不怎么样,你说的我都听不懂,零基础慢慢听就能听懂了,谁都是从零过来的。

在座的诸位所有人啊,都是从零岁过来,从对于程程序程序一点都不懂过来的,这个点才涨了4。5,可以开心嗯不错,这位置六星下去吗,10年8年的,差不了,我就过来找虐,哎这个可以找js,这是一个好习惯。

而且怎么做到这么成功的呃首先老师也谈不上成功,其次呢老师已经60多岁了,比你们成多成熟一些,多懂得一些也是应该的,也是正常的啊,我60多岁要跟你们懂的还是一样的,那我这个就远远,这不叫成熟。

这叫loser了,就,对啊我都跟你说,加200的从滤镜吗,假如说清华毕业,我我没有没说呀,对呀,我就是清华的,又能怎么样,你打我,那个给给狗熊喝硫酸的还是清华的呢,那个我的小师弟周老师也是清华的,没有。

6年12k2 线武汉工资经验高还低了低了,张学友,你太优秀了,别人优秀跟你有半毛钱关系吗,你只要超过你身边的百分之八九十的人就行了,开始学习自己,努力起来的时候,是身边百分之八九十的人都在那打游戏呢。

你就是老大,number one,当然是我要超越的人,到马老师去世之后,你就可以超越老师了,假如你再活50年的话,3年合肥时期高了低了偏高,r语言计算机专业的吗,机械最多35算,你说对了。

nike要怎么学,先学怎么用,再看源码,号线8。1分,我们稍微等一下,路人小伙伴,8。05呢,咱们准时开课啊,这个职业规划怎么做,看你具体情况,一会儿有兴趣可以跟老师聊一聊,讲完课。

1年半北京大概得多少算正常,15左右,目前,spring的学习嘛就是先学用吗,任何东西都是先学用,你要了解自行车的原理,先学会骑,提熟了之后再分析那个链条怎么传动的,然后呢再往里分析它的材料怎么制作的。

工艺是怎么做的,原理是什么,4年北京25k容易吗,easy老师也是培训班出身吗,老师从学校毕业就培训别人了,毕业演讲的成都拿12k难吗,1年之内12k相对偏难,过了1年之后应该会好很多。

有的是机器人容易取得荣誉,圆梦,50年之内你应该是见不着的,师兄千百度300000算可以吗,可以正常应届生千百度300000算是比较正常,请问老师有哪些公司在过马士兵钓鱼,老师有这个偶像。

所以我们看到看到了,你看到了吗,老师做了多少年的培训,20年,今天有时间干别的来着,开玩笑啊,有时间去干别的了,没想到回来讲课居然还没人讲的过,老师,你说这不是太过分了吗。

揭秘小龙19年20年23k看在哪个城市,这个不一定,还有两分钟啊,两分钟之后呢,我们开始我们今天的内容,声音那叫一个年轻人,你不知道声音也是可以加滤镜的吗,学了就忘难受多倍。

南京3年15k可以不高不低吧,8年才17,那低了哪个城市都不算高,这声音都怀孕了,嗯只有你怀孕这个事儿不合适,下面我给你打胎,好,流产了吗,流产了我就可以恢复原来的声音了,嗯,北京多少年都40。

北京我不跟你说,那个就就就就是按黄老师的简历,2年就已经60万年薪了,好08:05啊,我们准时开始今天的课,这个,首先呢抽奖这个没有抽的一段时间之后,不知道现在开了没有啊,开了就算了。

然后今天还有一次抽奖,是下课之前抽这个抽这个东西哎,这个奖是比较重的,主要是鼓励大家多陪陪老师啊,陪到下课呃,一等奖呢是一个b此耳机我都想要,二等奖是一个机械键盘机械的。

这就是我现在那台机器用的那个这台机器用有用的是也是个机械的,三角是一个小米手环,四等奖是一个京东的一张购物卡,应该是100块钱的吧,五等奖是十本书,其实你坚持到最后,这个书抽到抽不到的关系不大了。

我觉得这个讲述的有问题,回头跟他们说一声啊,那我们先回顾昨天讲的内容吧,好不好,简单回顾一下啊。

你们稍微回顾一下,昨天呢我带大家呢主要是过了一遍这个东西。

就是常见的垃圾回收器,垃圾回收器的一些常见组合诶,哪些呢是分带的,哪些是不分带的,哪些是逻辑上分,在物理上不分带的,讲了这个东西,然后呢我教了大家几个简单的命令,来观察一下咱们这边的一些情况。

观察一下dc的一些信息的,给他列出来,交了那么几个简单的命令,然后昨天呢我运行了一个小程序,这个小程序呢就是还有这个小程序,小程序呢是模拟了一个呃,对于信用卡模型来做模型匹配。

来做风险控制来做的这么一个小程序,而且小程序呢它本身是有些问题的,昨天呢呃大家伙也都看到了,然后在昨天结束之前呢,我跟大家说过,我说呢呃在我们实际当中调优的时候呢,我们还有一个特别好用的工具,就是谁呢。

阿里开源的那个office呃,其实来教大家做操作这个事儿相对简单的多,呃我今天给大家讲完操作之后,能让你的简历上能够大体写上有过jvm调优经验之后,看看能尝试给大家讲一点理论好吧。

理论其实相对难好难好多呃,面试的时候问理论问的比较多,实际上你只要有个操作,那么别人问你的时候,你是做的什么操作呀,什么情况下你做调优啊,这个东西能说的出来的时候,ok你这个简历就值钱了。

今天他特别过分,我以前的学生啊,就是从做线上教育以来,学了我们课程的学生少着大概学完课3~6月左右,少着能往上涨5000块钱,今今天今天特别过分啊,今天有个学生只涨了2000,还好意思跟我说,太过分了。

实在是太过分了吧,打破了我们一个记录,本来我们是原来的学生,差不多啊,每个月涨5000块钱,今天有一个只涨了2000,但是他只报名只报名了三天,哈哈哈哈哈,虽然他破了我们几个,我们还是很高兴的啊。

好开玩笑啊,来看这里,那今天呢我主要给大家讲这个office的在线拍照工具。

ok回来回顾我们这个小程序怎么用啊,稍微回顾一下,我们首先呢把我们的例子程序给跑起来,还是这个小程序让它跑起来,大家还记得吗,我们others怎么起来啊,就这个小程序呢,它有问题,昨天呢大家也看到了。

我们首先用top命令能观察出来它内存在不断增长,所以你的网管肯定会过来找你一个大耳刮子呼上来说,你这怎么回事,你赶紧给我调去好,你就给他调,你怎么调呢,你用几个命令来调。

当然昨天讲的那个几个命令都比较土,我今天呢给大家也是java自带的,但它比较分散,比较土,用起来不方便,今天用一个核武器,就是那个阿里开源的这个ars,首先所以这是这是原来我们需要需要调试的这个进程啊。

需要调试的这个进程,他在这跑着这个阿瑟斯怎么工作呢,阿瑟斯他自己也是个进程,他起来之后呢会attach到挂到上面去观察它里面的一些运营情况,这里面呢是java自带的一个编程接口,叫jvm ti。

如果你感兴趣可以去看一眼阿瑟斯是拿什么写的,是这个接口叫jvm t i简称叫java,virtumachine to interface,工具接口就是你可以为jvm写一些工具,通过这个gm ti来写的。

就是就是拿这个写成的,我看这里,来把直接点了,这刚站,os 5点战,挪一边去啊,好我们挂到这个进程上,这个进程是2176敲一,那么当你看到f4 这个界面的时候,ok你已经知道了啊,已经挂上去了。

s命令有很多,我推荐大家呢,你直接到others的主页上,就get up那个主页上去看他的中文写的注释写的很详细很好,也不用去专门找找些书什么的,可没必要。

还有一个呢你就是用这个help help写的也不错,非常好呃,我一般就直接看help help,它就会列出来在阿富下面呢,你可以运行哪些个相应的与相应的这种命令,哪些命令都有这么多mac。

我就不一一念了,特别多呃,我教大家几个好玩的,几个比较常用的,首先第一个呢叫dashboard,dashboard仪表盘,仪表盘什么意思,你一敲回车的时候,你会发现诶出了一个用命令行模拟的图形界面。

他每隔5000应该是每隔五秒钟刷新一次,如果没记错的话,当然这是可以指定的,这里面给你显示的是什么内容呢,我想你一看就应该明白上面列出的是什么,最繁忙的有哪些这些现成的状态,它写成的名字。

还有呢关于内存的一些信息对占了百分之多少啊,一边去百分之多少,survivor区多少,tenure generation,昨天我讲过tenure的generation,就是o的区域,老年代占多少了。

这个还有呢下面是一些运行时信息啊,操作系统的名字,操作系统的version,java version,java home,这就这就不说了,好这个比较好玩啊,当然这个是看一个大体的情况。

除了dashboard之外呢,就是dashboard,你可以远程的去看他什么呢,哎去看动态的去观察它,看看这哥们儿年代是不是不断的在增长啊,是不是老回收不了啊,的占用是不是不断在增长啊,去看这些。

去看这些信息,还有哪个线程是最忙的,占了cpu占了多少钱,程的名字是哪个,到底什么情况,他在干嘛,如果有人有县城不断的占占cpu,ok这个县城一定是有问题的,县城都占了百分之百了,查他怼的。

ok这dashboard就干这个式子来get到同学给老师扣一,这个比较简单啊,不难。

好我们再教下,然后呃在这个就是java,就是阿里的这个东西呢特别强大啊,他除了有一个命令没有弄完之外,其他的基本上全都全都全都完成了,好大家看这里啊,来我们再来再来教大家另外一个命令,就看这个吧。

jvm this late tardage of information,大家还记得吗,昨天我教了大家一命令叫infer,然我看出这位的相关信息,阿里的这个g v m啊。

这个命令其实比昨天我给大家教大家那个jinfer那个命令,它显示的更加的详细啊,他比那个要详细的多,最好的是它能够显示出来,你到你现在到底用的是哪些个垃圾回收算法。

比garbage collectors,你现在用的是哪个,copy market,the mark mark compact,你现在用的是拷贝,拷贝完了之后呢,是一个mark swift。

再加上压缩输入,有有就是简单的说就是我们原来的psp,他算了,当然还有一些其他的信息,这个你自己去看就行了,这个不难,ok,啊没有clear票吧,好我们说我下面我下面来教大家呢,教教他什么呢。

教大家怎么定位我们这个程序的问题啊,我这个小程序一定是有问题的,当然他现在还没有显示出来,但是它有问题有什么问题呢,我现在教大家怎么定位,昨天大家观察这个小程序的时候,你会发现它会执行一段时间之后。

它会频繁地g塞,对不对,频繁发生gc不断的gc,然后呢它不断gc呢是什么情况引起的呢,还得看一看,一会儿我就一会,等他评判g c之后,我们再来看他信息啊,你就了解了,我先教你别的命令吧。

一会儿我们回来看这个信息再看啊,教你一些别的命令啊,你比如说,这也是一个很有用的命令,是把这个java进程里面所有的线程全给你拽出来,昨天我们讲过jdk,大家还记得吗,jdk是干嘛的。

也是观察那些现成的信息的,阿里的这个thread和jdk完成的功能一模一样,但是它用起来更好用一些,比方说我想观察16号这个线程,它的一堆栈的调用,而且呢和16ok就可以了,我知道啊。

这个16这个线程在干嘛,他是在一个什么状态,它是在运行哪个方法,这个方法的调用站是什么,当然如果你一个程序里面现成非常多,你还可以进行过滤thread或者may。

比如说may may may里面开的线程啊,全都给他列出来,全列出来单位呢,如果你像阿里的那个要求,每一个线程你都起了正确的名字的话,那么你就可以用名字来进行过滤,如果县城有谁是,比方说它是持有锁。

产生了这种死锁的现象,直接一个命令thread当b反正我这是没有锁的,就是没有组,没有会产没有产生死锁的线程,所以你刚毕是看不见的,如果你产生死锁,你自己去写的,你用它来挂上去的时候。

thregb就直接会把那个县城哪个线程死锁都给你找出来,thread呢还有一些其他的参数,任何一个命令后面调杠help回车,你就知道这个命令的用法,这个命令到底是什么意思。

他说display infer threstack,然后它有一些个examples,一些告诉你的用法,比方说gb gb是什么意思呢,find the thread。

who is holding a log that blocks,the most number of threads,你懂你就明白了是吧,find the threat,找到那个县城谁呀。

holding log,他正在拿着一把锁,阻塞了其他人,阻塞了其他见证,他导致了思索,把这县城给我揪出来,fly刚毕是不是用起来特别简单,感受到了没有在一个界面里面把所有的问题,所有的问题全解决了。

会影响被监控进程的性能吗,必须得会,如果不影响他怎么去拿到那些信息呢,必须得会影响,然后我们继续往下接受命令,等他等一会儿他要死机的时候,我们再来看他的信息,好吧,再介绍几个啊。

这里面的命令我就不完完全全的从头到尾已经介绍完了,这个就没意思了啊,我就是多数人,大多数的人应该更看外面的文档,看,帮助的信息应该都能完成是吧,来有这个学习能力的,给老师扣个一好不好,我觉得应该有啊。

参加过任何1年半年的工作的这些成员,这都不是问题,大家就再给大家介绍一个命令是什么呢,这个呢我倒是我这几个命令啊,我建议你可以了解一下这个命令还是挺好玩的啊。

第一个呢叫search classes loaded by gb m s c s c,什么也叫search class sc sc呢,当然他的命令的方式有特别多,如果你这条s的话,它就会把他就会把星。

它就会把所有的这种命,你它里边加载的这些类全都弄出来,当然你可以这么来写科目两码是诶,这是我们自己加载的那个类,ok这个包下面呢它加载进来的所有类的信息全都列在这里了啊,你看到除了我们的主力之外呢。

还有三个蓝的表达式是吧,有啊内内部类的啊,两个栏目的表达式啊,两个内部类啊,一个是有名的内部类,一个是匿名内部类,不说了,老师你把这个类的名字找出来,有什么有什么用吗,是因为呢他为下一个方法做准备。

下一个方法叫什么呢,下一方叫sm sm别扭,这名字起的全称是什么,sm叫search the method of classes,loaded by jim,去查什么,查方法,找到那方法,sm。

你点视频这样如果是这样的话呢,它会把这个类下面的所有的方法全都给你列出来,当然你要查那个main方法的话,就可以直接按这样的格式来写,马士兵jvm gc啊,把这个麦给给给搞出来,只是查类名,查方法。

这个东西呢没什么意思,其实它最重要的是干嘛呢,最重要有两个命令是跟在这两个命令之后面的,不是sc,你有几百个类,我用sc把我关心的那个类找出来,这个是需求是经常有的,100个类里头把这个类给我找出来。

这类头有好多比较关键的方法,忘了方法名叫什么了,sm给他搜出来,搜完了之后主要是干嘛呢,一定是这个方法有bug或者有问题,我想观察他,你说对不对啊,同学们,这是肯定的。

那下一步呢有几个观察的命令开始服dc了啊,这就快了,有几个观察的命令命令你值得大家拥有,你值得拥有呃,这几个命令是什么呢,第一个呢是trace,他说你看这里啊,他叫trace。

the execution,time of specified method invocation,这是什么意思啊,读一下你们理解trees,后面要跟参数的话,如果你不知道它怎么用,很简单挑help。

看他的examples就行了,你看啊,比方说它trees某一个类下面的is blank方法,看到了吧,这个trace是干嘛的,这个trace是跟踪时间的。

the execution time a specifimethod of vacation,指定一个方法的调用,它来跟踪这个执行时间,这个就是执行效率,你比方说你写了一个很关键的方法,放上去之后。

这个方法呢肯定会让用户不断的调用,不断的调用,不断的调用不断调用啊,或者是你的web application的话,这个方法会不会用不断调用,这个方法是一个很关键的方法,要求它性能比较高。

但是你会发现这方法性能不到位怎么办,观察他到位没到位啊,这个trace直接跟他看他的方法执行了多长时间,当然我们这个小程序呢没有这种不断执行的方法啊,不停的执行,又来一来一个请求执行一次。

来个请求执行一次,所以这个目前用不到,但是在你们自己写的web application里头,一定有这样的方法,你比如说你写了一个什么service。

service service里面有一个方法叫make an order是吧,设施给他成成交一个订单好,这个方法和数据库打交道,和硬盘打交道,和缓存打交道打交道完了之后反馈回来。

你可以跟踪这个方法的执行时间,你会发现他是执行时间特别长,一定有问题,每次用这个东西跟他跟他跟晕了,真晕了,说明你不了解这,到底是怎么用的,这很难吗,很简单,应该是好,讲。

到这里能跟得上的同学给老师扣一来,那除了这个trace之外,trace很有用之外,还有一个跟踪方法也挺有用的,哪个哪个呢,就简单对老师把这层窗户纸给捅破了,你就觉得没那么难了,就好多时候叫会诊不难。

难者不会给你捅破了,你就觉得没什么难了,叫monitor,这个也挺好玩的,也挺有用的,你看一眼就是monitor,method,execution,statistics,for example。

success,fader,count,average,favorite等等等等等,这是干嘛的呢,跟踪这个方法的运行数据,这是什么意思啊,简单说一下,已经跳不进去了,因为那边那个进程已经死掉了。

这monitor是什么意思呢,monitor的意思是当你跟踪某一个方法的时候,这个方法是哪些值被传进去了,传进去的哪个参数值,哪些值被返回了,他的一个执行过程,这些数据全都能给你跟踪起来。

这个对于你定位问题来说也特别特别的好玩儿是吧,也特别好用啊,这是你为什么要跟spring的方法呀,你不应该跟自己的方法吗,现在为止呢其实还有一个关键的命令,我还没有讲莫及,下面我来讲这个关键的命令。

这个关键命令是什么呢,就是但你的程序发生问题之后,你看啊,现在看我现在这个不停的复dc,看到了吧,不停的刷新,不停的刷新,这特别频繁,而且你看到了这哥们其实已经死掉了。

他只不过有些遗留的线程还在不同的不停的输出而已,那个输出线程哈哈还没有输出完,已经死掉了,已经om了,这个程序的bug就已经出来了,程序bug会是什么样的呢,内存不断增长到一定程度之后。

频繁f g c f d c之后,再过一段就有可能产生l o m,这是这个小程序的问题,那下面呢我们就来定位这个问题,先把这个给停掉,大家需要注意的,有有有一有一点在这儿,其实有一些细节我已经略过它了。

因为呢那些细节对咱们今天的时间来说不是特别重要,你怎么设置gc的日志,你实际的工作场合也是特别重要的,如果有面试官问你,你纸质的设置的这种参数,你要是回答的有问题的话,我告诉你。

面试官一眼就能看出来你的水平到底是高还是低,什么意思呢,这个我在笔记里呢也给大家记了,我怕大家看不懂。

我多说两句,的话,好看这里日制参数的时候一定要好好设,有很多人啊在设这个日志参数的时候,它就直接呢就指定指定一个日志文件,知道吗,那就不管了,我告诉你,凡是指定一个日志文件都是业余干法。

有为什么要问你说你们有几个日志文件,就一个死大耳刮子直接给你抽上来,为什么,因为你自己想想看这个日志它会不断的增长,不断的增长,不断的增长,日志要是增长到四五个g的这种日志,你想分析里面数据。

你累不累啊,累死你,我告诉你,真正的日本参数,按照文档里头这么说,设好日志的名字,自动生成,这个日志是一个滚动日志,叫log for rotation,有多少个日志文件,五个这个数你可以自己设的啊。

五个十个你自己看着办,每个日志文件是多少,20什么意思呢,产生五个日志文件,每个日志文件最大20兆,因为它是滚动的,最后一个日志,满了之后写第一个,第一个就被覆盖了,这样的话总共就100兆。

要搞一个日志文件不断增长,肯定会问你,那是有问题的啊,刚才我讲的这一小段街道同学老师口音。

主要是让你知道你怎么跟面试官聊天,日志的信息,这里给的信息叫做非常初级的信息,如果你设日志的时候,一定要设置的特别详细的那种,我给大家讲日志文件的解读,主要第一比较容易。

第二呢跟我们实战的关系并不是特别大,今天所以呢我们先把它放在一边,但实际上每一个不同的垃圾回收器的认知。

它实际上还是还是很复杂的,你真正要把它看懂的话,你得确实实了解啊,就是这里面的每个日志它到底产生了什么意思啊,这个我有一些整理啊。

你自己尝试看就行了,在这儿呢就不花时间讲那个了,比较枯燥啊,也没什么意思,先把它放一边儿,你在日志里头发现就定位一个日志问题的时候。

系列 2:P50:redis合集:2、Redis实现活跃用户用户统计playlist.f9 - Java视频学堂 - BV1Hy4y1t7Bo

都在三颗cpu上,第一件事情,三个线程是不是可以工作在三个三个cpu上,这,个能听懂就来刷波一,三个线程是不是可以工作在三个cpu上,那么这时候其实他们就不叫并发,他们叫做并行了,对不对。

一定要注意用词准准确度啊,他们叫并行了,他们是为病情做事的,那只不过并行做的事情不不是一类事情,因为i o我说了两个阶段,一个是读出来,然后再再干,所以呢工作线程依然是要去负责计算这件事情。

他如果刚起来的话,不读取io这件事情,工作线程里边是没有什么东西可可算的,所以先通过一炮知道了,说唉有俩客户端数据可以读了,状态知道了,然后这时候这个共主攻内容通知另外两个线程。

说你俩你你们各自有俩客户端,有两个哦,有两个socket,有两个输入流,一个输入流,一一个一步一个一步带你们各自读一个啊,读到东西先读读出来放到这个堆里边,然后我就能看到了。

所以这时候另外两颗cpu是并行的,就是它们是并行的,但读取l这是并行的,并行读取了,两个i o里的数据到这步能听懂,同学来刷波一,这两个线程可以并行读取两个io,他们先把读到的内容就放在堆里边了。

放到队里之后,然后其实我这个县城可以处理一个,再处理一个,对不对,哎,挨个去处理,那处理完第一个之后,本来我是处理完我还得就是给客户端返回,是不是还得还得走io。

是不是我可以让我这个线程调了一个从ioe给他right写出去,我还可以通知另外一个线程,哎,我计算完这个结果,这个对象放在堆里了,你把它给我输出,你你这个cpu在做这个ip输出的的时候。

我这颗cpu的一个线程就可以处理我堆里边另外一个队列,里边另外一个数据,记得他咱俩之间是不是开始并行了,就这两步是不是也是并行的,这不是不是并行的哎,病情处理完之后,你这边i o无论你发的快慢以后。

你你发着我只记得完了之后我还可以让另外一个县城走另外一个cpu,然后走内核交互去把我刚才那个第二个计算结果再给我发出去,但是其实他们之间也也因为他的时间轴可能很长很慢,发的东西比较多。

但是他也会和另外一个依然是一个并行的,压到两颗cpu上,现在能听懂了吧,没问题了吧,那其实你数成本就可以了,其实总共来说一个并行一次,单独它计算两次,然后这是一个并行三次。

然后这一个这一个他俩有可能并行,或者他已经处理完了,但是他最后他必须他第三部完了之后他能写,所以还是第四步,下边是四个宽度,上面是六个宽度,所以下边一定是用了用到了多核的能力。

比上面这release这个模型一定比上面这个模型快点,好吧,那下面这种i o这种多线程的方式是注意是在redis 6点叉,redis 6点叉的版本当中会增加进来。

然后其实它的增加进来这个功能叫做io surprise,io多线程,但是无论注意听啊,无论你的是六点差五点,差三点差二点叉,它的工作线程是只有一个的,多路复用是另外一回事儿,多路复用是一炮。

知道哪些客户端一共有1万条路,里面只有两条路可以有数据,那这时候走到e后,多路复用器知道了哪些就是获取i10000 个io事件,这个事儿服用了一个调用就知道了哪些可以掉了,然后这是状态的第一个阶段。

i o的第一个阶段,我知道哪些可以用了,第二阶段我要读取这么多,我可以单线程one by one的串行读取,我还可以让更多的cpu同时让他们读不同的socket io,读过的结果。

第三个计算我可以单线程计算,我也可以多线程,但是我们说了单线程计算是串行化,串行化它的成本相对低,因为多线程一定会牵扯到锁,串进化是没有锁的,数据是最干净的,其实效率反而更高一些,最后这个总结都能听懂。

好吧这能听懂,然后在这儿还有一个点要聊一下,这是之前一个学生问的啊,我在这多说一句,再来一遍大哥开视频吧,因为我这还得讲别的好多知识好吧,咱们这个课是有视频的,而且现在是11024的高清的啊。

回去那个今天我讲完课后就只能看到这个视这个这个视频了,在这儿聊一聊一个事情啊,刚才我说了,它是串行的,然后你有很多客户端,它是先计算c一还是先计算c2 ,这个计算的过程会不会混乱,会还是不会。

会还是不还是不会,其实这是一个未知的啊,这个位置一定会混乱,一定会混乱,这是未知的,为啥,因为你的程序只知道有多少个有哪些io,然后程序调度的时候,它指不定先读到哪个l厚度的l并并不一定能解吧。

而且这两个这两边时间读来是这个这个这个不确定的,所以在这个处理他们的顺序的时候,还真的有可能先处理c2 ,后处理c这个这个c一了,就看他俩,因为他俩并且病的时候就是一到并定要分布式的时候。

这事儿就没谱了,他不想串行,我必须一个一个来,对不对,即便其实串行的时候,如果两个客户端,其实你串行这个我i读的时候,我有有可能先处理c2 的,后处理c一的,所以先处理谁,这件事情不确定。

反而这件事情还带出了一个新的一个知识,也是你平常忽略的,其实就拿不拿下边这个复杂的模型来说,拿这个简单模型来说,想你加入程序,其实每一个客户端对于我的redis来说是一个connection。

是一个连接,这可以用在这个知识点,可以用到很多技术当中啊,其实每一个客户端来说,对于我redis是一个connection,是一个独立连接,那其实一个程序他在这两个客户端中处理的顺序的话。

如果没有曾经没有自己明确的代码约定死,我必须按照他们客户端的那个标签属性维度,先处理谁,后处理谁,如果没有这部分代码的话,其实在处理的时候,指不定先读谁后读谁,也就是说连接与连接之间是无序的。

数据到达之后处理的顺序是无序的,这个能求同学来刷波一,但是有的时候我们但是这里边你会发现redis本身就是串行化的啊,这个redis本身计算是串进化的,如果这两台服务器里边如果对了同一商品。

然后它的增删改是有顺序发生的,怎么办,怎么来解决这个问题,所以这时候其实你要宏观感宏观,你知道为什么俩客户端一定做了负载均衡,一定把一台变成两台了,所以你前面一定会有并发,然后后边是串行的。

然后你又想保证所有东西能够所有制这个执行步骤能串行化,别出错,先创建后更新再删除,这仨事不能乱了,那有人说用锁其实不需要用锁,如果你还知道另外的一些知识,就是你的知识点如果足够宽的话。

比如说在我做负载均衡的时候,我一个负载均衡器,那么这个c1 c22 台服务器,它们各自两个客户端对,是在使用这个redis,如果他们各自有一个连接的话。

其实我可以在负载均衡的时候可以按就是客户端很多请求进来了,我是可以根据ui这种七层的,我看到用户他们访问的是哪一个商品的ui,如果ui相同的,我就给到c1 ,就是拿ui做负载均衡。

相同的ui一定去到某一台机器,在负载均衡的时候,我们是不是可以随机负载均衡,这个客户端给他第二次请求,给他,第三请求给他或者轮询的,可以随机的,也可以把客户端绑定,客户端绑定的,我拿着客户端的ip地址。

只要是这个客户端的,无论访问相同,上面不动上面我都让他去c1 ,或者是我拿着ui去做负载均衡,只无论是你a客户还是b客户,只要你访问的是这个商品的,我就一定让你去到一个服务器里。

就是负载均衡的策略有很多,这不能听懂,来刷波一,然后这里边都是细活,你在考虑解决这个环节的问题的时候,其实你可以把眼睛往前看一看这个环节,如果我让我的负载均衡的策略是把相同ui相同商品的。

无论是来自于谁的,都附带了一台机器,那这台机器如果在这个这个这台机的肯定是不止受到了一种ui,但是它它里面可以开启多线程,就它也可以开启多线程,而且它里面的连接池也可以多做,它的临时也可以多个。

但是这时候其实我可以更倾向于相同ui,就由一个线程在一个连接当中把相对u2 处理掉,就是一个connection里边,那所以你re收到的也是只要是一个ui,也是按照你接到的顺序来处理的。

就这块你可以去调整它,调控它,这都是细活儿,就是你而且这个过程当中其实是无锁的,整体的过程是不需要锁的,好吧,其实你如果能够将你的商品的ui的处理打成一条通路,打成一条通路,虽然看似是多线程。

虽然看得多连接的,但是我一定会在我设计的时候,让我的ui一定是走的这个县城或者走走这个最终是走了一个connection,对不对,就一定会处理它啊,所以你收到的一定是串行的好吧。

ok那这是一个扩展的一个知识点,就像上面这两点说的就是什么说的就是一个整体宏观的reits是啥,有三个模型,你只要把这三张图你会画了,面试的时候你就有这种感觉了,第一个是它的这种并发模型。

然后它的串行化单线程,另外一个就是现在以及这个之前的版本当中的dworker现实工作,以及他未来的版本变化,或者是你对整个技术发展当中,尤其在i o这件事,你想明白了,他是会多个阶段的。

所以在一个词汇叫做ios rise,是可以让我们的某些技术提升的,不只是redis,像nike,像我的,像我们的很多的技术,它都是有一个ios rs这么一个概念,就是从io读到的东西。

编解码的事情是可以由一个线程来处理计算的事情,可以一个线程也可以有一个多线程的一个线程量,对吧,其实这个技术是可以,就刚才我讲的release这个知识点是其他技术可以。

并且这个这个这个这个这个这个这个这个传递的,好吧,ok收,那这块能听出来刷波六,如果还是那句话,刚才听的时候你已经晕了懵了,看预习资料,尤其在e po这你先懂,尤其i o的不同的阶段,这个事儿很很重要。

因为这个不懂的话,io多线程你不懂,那nt就很难去懂,多线程不会乱,怎么会乱呢,他们依然是你看这我没有说在这儿还能计算,一定是在尾随它后边来的,这个计算的结果,工作一定是在这个时间时间点的后边发生的。

好收这块不浪费时间了,那么接下来进入最后的环节,简单给你们总结一下,串一下这个知识点,下面就开始讲我们redis使用场景,使用场景呢,然后我是按照他的五大vd类型,一个一个类型去给你讲。

他有哪些场景可以使用这个使用场景,你一定要把它换成最终你的你的你你最终要为啥要听这节课,你时时刻你想着你曾经做的传统项目,传统项目当中哪些模块功能或者哪些所谓的c r u d的那个代码底层。

其实可以从数据库里好,从那也好,换成redis,因为如果你把你曾经的熟悉的工作用release替代了你这个项目,听上去的感觉和能应付的压力,这事儿就变了一个所谓的逼格,就是逼格往上升了一下。

其实其实你所谓的你认为那个大牛大神,那个项目也就这么也也也就是这么一回事儿,好吧,那讲他之前啊,首先我们来简单回顾一下,或者是你如果没学过,也不怕,我先告诉你redis,它是pv的。

那么它的value类型有哪些,y类型有string类型,value的类型有string,有list,有哈希,有set集合,还有一个什么呀,最后一个就是常常用的五大八类型是salted set,有序集合。

或者也叫做this set啊,接下来这样一个名称,这是他五大八的类型里,一会儿我们只需要分析它来,你可以解决你项目的哪些场景和需求和这个这个问题,在这用。

我忘了那个预习资料里边有没有讲他这个value为什么要有类型,这个这个余字老师跟我说了吗,是value为什么是有类型的,以及它的本地方法,说了说那我就在这不讲了,回去看鱼子料就可以了。

在这就不浪费时间了,因为再讲一遍肯定浪费时间,对不对,讲他省之前安装,其实在预习资料里等等我都有讲过了,在这我不浪费时间。

然后打开我们的shush,基于release是基于linux去使用去部署的,明白吧,就是我们是基于linux的,也很少有企业拿它布置在windows上,所以那个就不说了,使用linux时候。

然后呢安装我已经讲过了,我先把它跑起来,去到redis的部署目录下,然后去到b目录,这是他给我们提供的一些个这个软件和程序,比如redis server就是它的主程序,我用了前台阻塞的方式给它跑起来。

reserver回来之后呢,然后他去占用了一个端口号,默认占用的6379啊,现在这个release我已经跑起来了,跑起来之后,那么怎么去连接它,使用它,它的通信是一个什么模型,怎么去使用它呢。

它的端口号是6379,它是一个服务已经坚定起来了,唉有客户端有很多的在这我多说一句ai和命令行,我只讲命令行方式就可以了,这个ai的方式我就不去讲,可以去讲它,因为你只要会面命令行了。

它是多客户端语言的,无论p是p啊,然后python啊,然后java都可以使用它,命令行呢会使用之后,其实那边的app还是比较相似的,那假设我想访问这个已经运行的这个服务,redis怎么可以访问它。

首先借助工具啊,不用它自带的,比如说nc这个小程序,这是在linux操作系统中,你可以安装一个nc的小程序,连百度连什么,他只是完成一个tcp连接,你自己根据你连接那个软件发送对应的协议。

它能读取读取明白就可以了,比如nc连谁连local house 63796379,说的就是我当前前面启动这个reserver回来之后,那么现在是建立了一个tcp 3次握手的一个连接,io就通了。

为什么i o就已经通了,i o通了之后,然后注意看我们可以比如说set一个k一是hello,那么什么是键值对,比如最简单的你要设置一个键值对,在这个ready release去存,你们别讨论啦。

跟着我这来学东西,先跟着课,课下之后这个操场上见好吧,sd一个k1 ,然后就是k y6 值是hello,当回车之后,那么就发送给我们release release给你返回了一个ok确认了一下。

然后这时候你还可以case星,然后这时候k4 星就是可以返回我整个very cool里边,这个星是通配符吗,有哪些个key就已经有它了,还可以get k1 ,然后知道他的y6 值是哈喽。

那么这里面可以看到一些呃,你看上去很很慌乱的地方,比如说在kiss新客户端发出一个指令之后,其实之前你可能只看到了k一或者都是多种k,然后现在它里边有一个文本传输的一个协议啊,协议这个协议是什么。

协议就是星一星一就是返回的整,如果这是返回的所有报文,你可以人工去解析这个豹纹,这个豹纹什么意思,星一代表返回的是只有一个,只有一个元素,这个元素是什么,注意第二个不是这个元素的内容。

第二个是它的一个描述,描述的是dollar,是描述描述什么,描述真正的一个东西,它是几个字节,几个字符k1 ,这两个字节就是连二就是两个字节能理解吧,如果get p一的话,那么返回的是dollar是五。

这个五描述的是我只是描述我描述的我后边那个东西有多有多宽,你读取到读取那就结束就可以了,听我们来刷波六,就是星后边跟的是元素的个数,然后dota后边是我紧邻我那个元素,它是字节数啊。

就这么一个简单的一个东西,就是nc啊,其实你会发现redis通信的成本和这个语法协议并不是很复杂,起码比你hp协议那个看上去稍微简单一点,都不再再来,除了nc,那有人说我没有nc怎么办。

我再给你秀一把啊,a e c准备一个八或者准备一个九吧,随便一个数值输入流,输出流就是linux基础基础知识了,我就是给你显显显摆一把,我会这个东西啊,输入输出两个流。

这两个流指向哪指向了dv t c p,然后local,l o c a l local host,然后6379,那这样的话,其实一期节文件也会开启一个socket,并有90g的io io连接石油之后。

你只需要echo echo一个case星,然后到我们的9号文件描述符发出去,这样的话也可以发给我们的redis,然后呢发过去之后,他可能给你返回呀,那读取九就可以了,也能看到刚才浮现那个文本。

这是在没有使用任何第三方软件的情况下,好吧,或者换言之,你都已经和这边建立建立关系了,那比如说我比如我在简单做一些echo一个set,一个k3 ,现在我库里有一个k1 ,看到吧,我再设置一个k3 。

只是随便设置,然后给到九就设置进去了,然后你如果会写脚本的话,well,while的时候让我们的用瑞的这个指令读取到的东西,存到一个圈差这么一个变量里,然后呢do执行的时候。

每次用echo打印圈叉这个变量的值,然后但结束,但是来自于九的返回值来看,这个看不懂无所谓啊,现在只是前前辈,我有多厉害了,走,然后回车ok读到了,少读了一个,因为刚才刚才刚才设置进去了。

那这时候如果再给他发送一个echo,因为反反正就是第一个,ok嘛,如果再给他发一条指令是k4 星的话,k4 星k4 星给到九的话,k4 星的返回值是什么,是不是会返回一个星二,因为有k1 k2 了。

然后第一个k1 k3 了,第一个是dollar 2,然后k1 ,然后再来一个dota 2 k3 ,对不对,是这样一个一个一个一个回旋给我发出去,然后再掉,刚才那个写了个小小小脚本,是不是有两个元素。

第一个元素两个字节是p3 ,第二个元素两个字节是k1 ,好吧这只是给你给你学校显显摆一下,那这个东西有什么意义,e无论加上刚才的nc还是我写这种脚本,这种l6 连接l是一件事情。

二一个它的中间传输的东西比较简单,并没有别的地方所说那么复杂就可以了收但是其实作为人的话,我平时使用什么东西啊,就是用它给我们提供的redis cli的一个客户端,因为这个客户端里有什么有have。

help里边可以告诉你,你可以学习通过have帮助看它的分组的知识点,命令的知识点,然后还可以用table这种股权的方式,而且你在set的时候还可以有提示。

这是这个方式肯定是比刚才我那种写法要简单的多了,因为直接使用它客户端就可以了,但这时候你先看一眼啊,case星你看到的k3 k一有看到刚才那个所谓的星和dota那些内容吗,是不是没有,换言之。

其实现在你已经明白了,你能你能不能写一个redis cli出来,你能不能封一个release客户端出来,只要你会i流就可以了。

没毛病吧,哎现在刚才讲的这票的知识让你看到最原始的方式。

然后它里边传输交互的是什么内容,然后这个会了之后,你再看看客户端,然后看他给你给你,结果你只是底层发生发生了什么事情了。

好吧,收这些都明白了之后,我们再来讲开始讲开始讲歪的类型啊,string list hash set set,先讲spring。

但是讲string之前先说have这个事情,have的是at符,可以接tb键补全,这是一个全局,对哪些指令,像刚才所谓的case啊等等,很多人都都有出现,然后你have n加at之后。

里边就有一个string,它每一种y的类型都有一个自己的组组内,你help的时候会告诉你有哪些指令,就是关于string有哪些质量你可以用。

而且都会有描述,所以他的学习成本很低,你只需要按照我做这种思维导图方式。

一会儿延展出哪些知识点,记住了之后,未来真的忘了都不怕,你记住了一个命令叫害就可以了,好吧,那就先来学第一个使用这个类型,它有set设置啊,有get等等,还有一些其他的东西,我们先来做一件事情。

比如说set,我先听一下库啊,这个指令就当没看到啊,现在我case 4星里面什么东西都没有,那个库里边,然后我set一个k1 ,比如说hello,然后get k一就能取得它的值,这是面向string。

接着段你能设置的,那你能设置的除了他之外,面向字符串还有哪些操作,比如说append追加k1 ,追加一个圈圈叉叉,那么在gk一只能追加到他这个字数就被追加了,还可以。

比如说get range k一从零开始,然后到三就取出四个字符,然后在这儿多说一下瑞当中它的索引,这个零到底是索引,所以分为正负的,你可以从左向右零下放到七八小时,也可以从右向左-1-2-34。

但是放的时候比如放-4-1,你不能放成-1,-4索引是从右往左数,但是索引往上摆的时候是从左向右那个摆法,所以这时候你还可以零到-1,就是取所有或者是-四到-1,就取得后边的这些东西,这是变成字符串。

它该能做的事情,名字串还有什么,比如spring lance,我的k一长度是九,那么这时候你来看看这个九代表的什么意思,来互动一下,哎这个长度这个九是什么意思,有人说是这个字符有不同的意思吗,好吧。

你再来看吧,我set一个k2 ,set一个k2 啊,然后放一个a strlk 2的长度是一,那里边应该有只有一个一,只有一个a只有一个a对不对,哎有一个a那这时候再来看set一个k2 。

然后不是append,追加一下append,追加cr cr里边刚才是一个a我往里面追加一个什么,追加一个中国的中子,那么这时候p2 里存了什么东西了,p2 里存了一个a和一个中国的中字。

然后string l我的k2 ,请问它的长度是几回,知道是几,是234512345,是哪是哪,是哪一个数值,14为什么是四啊,来看一眼get k2 ,它里面存了哪些东西呢,存了一个a。

这个a是什么意思啊,就是我开始放进那个a然后后面我这个中的中字它就显示成这个样子,这是什么表示方式,这是16进制表示方式,显示有三个字节,它的实用均值分别多少,有三个字节,加起来四个字节。

所以使用lts给你返回的是什么,是它字节的数量,是字节的数量,注意听是字节的数量,然后你再做一件事情,看我看我做一件事情,如果我把我当前这个客户端注意听。

我把我当前的客户端从u t f杠八切换成,这个gpk就我把当前的编码集,就是把我的数据这个编码去的话,这个编码级换了一下,换成j pk了,然后再set一个k3 ,里边有一个a然后再append的k3 。

一个中国的中字回车,那么这时候spring lk 3它的长度为三,就不是四了,你gk 3就是一个a和后面两个字节了,这是第一个,首先说,你往里存的数据,人给出的数据是不是都是a都是中,对不对。

但是这时候你会发现客户端编码集不一样,它在reality存的东西大小坑都是不一样的,这个东西和二进制安全,一句普通话就是release,只存什么呀,字节数组,你客户端按照你的编码及按照你的序列化的方式。

你把你的数据即便是相同的数据,你序列化成什么字节数组了,我就按照你给我的数组去存,我不会改变它不会怎么着,这就是二进制安全,像hbase super卡夫卡,他们都是让你给他一个字节数组。

这个能能能听同学来刷波六,是这个意思吧,嗯嗯,再接着听啊,再接着听,到时候给你总结出来,到时候给你结出来,那么除了这个string这种方式,然后再让你见识一个东西啊,他还能做这样的一些事情。

比如说set一个k4 里面存了一个九回车,那么请问它的长度是多少,它的长度多少,这是一个数值,一个数字九的呗,哎长度上哎,回车是是一个对对,那这时候注意听啊。

如果set我把k4 的值更新成99或者是129,129吧,分成129,请问它的长度多多少,更新成129,长度多少,在学java的时候,这给你补充一个常识啊。

在学java的时候都知道数据空间有压缩的概念和这个调优的概念,1270127,它java里边即便你是定制类型,它也是存一个字节里,因为一个字节是可以满足0127的。

这种这种显示的就是-170到正170,因为前面那个有有无符号嘛,然后超过170,这时候他才怎么样走,他正经800的那个多字节,这个这个这个四个字节这事对不对,他可以调的过程,那么如果在re中。

我set的一个k41 个数值数值了,这桌料开了多少个字节,回车放进去了,spring lk 4是三个字节。

是三个字。

系列 2:P51:redis合集:3、Redis实现秒杀抢购排行榜评论列表playli - Java视频学堂 - BV1Hy4y1t7Bo

Yeah。比如说我再ss1个K4,把4这个里面改成9999,改成这么大的一个数。就是lceK47个字节。显然他其实没有走数值这个这套东西,因为他把这个数值也理解成了文本。明白吧?

就是咱们reis客户端也把它理解成文本,就是文本字符块存进去了。但是注意了,res有这么一个功能,比如说increase。😡,对着K4,它可以做加一加法这个计算,再get的K4就往上涨了一个一。

它能做计算。虽然你存的是文本,但是它支持这个这个数值计算。好吧,然后再来看有一个指令,注意看啊,我刚才写了很多东西。现在我们总结一下第一个指令叫tab。typeap的时候,你可以看K一是str类型的。

typeap看K4,它们都是 string类型。因为刚才你用到的这些个指令都是str。都是sring的这种类型的。命令,所以它的value的类型都是基使类型的。但是还有一个东西叫OBJ。

就是对象真正的我的Y头对象的,比如说encoding。这个单子什么意思?是编码对不对?看K一看K一啊,K1是一个肉类型的啊,里面存存的这种这种这种简单的字符串,或者是看K4,它能识别成int类型。

但是这注意听了,inc code的编码虽然看K4是int,但是实际它占7个字节,它依然按字符串里存的字节数组去存的。只不过它加int有什么好处,因为你曾经对他参与过计算,他计算成功了。

那下次如果你继续想这个increase我K4的时候,这个时候他只要看到你上次结果,把那个K里边的描述那个int,只要看到int了,他就可以大胆的直接去把它转成数值,开始做加法。

它不需要判断我能不能转转的时候有没有错误。

是不是这道理?哎,那么简单总结一下,在这sring。第一个。它可以有字符串。的操作。你们在下边在聊什么?注意听课好吧。第一个有字符串的操作,字符串操作哪些?比如说我get site。

我可以这个这个这个这个append追加,可以显示的长度,对不对?字符串常规操作,然后刚才发现了它有一个数值操作,也,就是里边其实你你是可以有数值。你存1个99,存1个一存一个2存1个3,但是他们注意。

虽然它有数值操作,子符串操作。我说了,它是二定制安全的。20这安全是什么意思?无论这个东西最终是怎么怎么去处理的,底层真正存的时候,它是20安全,20安就是字节数组。就无论它是哪种类型。

最终它都是一个字节数组,只不过在OB的时候,对数值,它虽然有一个int的显示,这个int只是说我曾经参与过就这个数据来的时候,或者我做过计算了。我知道它依然计算结果还是一个数值。

那我下次再再调那个计算方法的时候,发现它是int,我就直接开始把字节数组转成数值进直接进行加一。如果没有曾经没有这个int的话,那如果你是一个程序员,你读到一个字节数组。

你每次是直接就敢把字节数组 tot吗?万一他要一出了,或者里边存的是一个字符串呢,是不是这这里边计算就会报错?你是不是加各种判断,对不对?也就是说复杂度不是O一,而是要每个操作都要判断,都要判断。

都要判断,都要判断。😡,但是如果有一个意子的话,你可以把判断的一些票过直接转,直接直接算就可以了。😡,这是re作者非常细腻的一个一个一个点。你你去品你细品是不是这个这个这个这个这个特征。

就是人家可以不加这个int,反正你我就自己储存内存了。你每次如果你想调in这个计算的时候,我大不了每每一个操作,都要加入一个转换前的判断每一个字节是不是一个数值,它举值是不是一个数值,是的话。

我才给你转,然后才让你参加计算。但是如果曾经参与过计算了,它也变成一个数值了,我就给你标识一下int。那未来未未来如果10万次加一的话,不怕我,这10万次,我都不需要判断每一个字节了。

直接转成数值就可以参与计算了。那后续10万次的计算速度性能极高。现在听懂了吧。哎,你学你听我的课,学我的做时候,别急,别慌。我前面给你要讲一大堆的东西,你感觉听着很low,这你都会了。

但是我到最后我会给你总结它的目的是什。呵。嗯。好吧,str有字符串类的操作,有数值类的操作。那么字符串类的操作就加上二十进制2二进制字节数组。那么我们说了最值钱的地方是你要学习这个技术,它应用的场景。

对啊,追听是场景。那么请给我在这两个范围之内找一些场景。找一些场景字符串,你们公司用字符串str字符串可以存什么东西,再加上二级专线,你可以存什么东西,你可以解决哪些场景,说几个场景哎,有三个共享。

对不对?除了30块钱,还有什么东西啊?😡,tken这不是一类东西吗?嗯,对象哎,说对象的对了,对象。或者叫做小文件。因为它是二0安全的,它里边没有数据类型的概念。实上就是给你你你可不可以把一个小图片。

字节留读它,读完之后变在内存里变成一个字接数组,直接存进去。😡,把你公司很多静态的那那些个静态的页面,动静分离的那种静态东西,以前放在磁盘,放在文件服务器的,但是里面sL可能有点慢。

你是不是可以放在一个reice这这里面来提升这个速度。对象存储这个对象就包含了任何你你序列化东西,你你java这个java里边序列化,我不我不是存在磁盘里边了,我存在reit己去了。

因为它是是个字节数组。那后续其他的GVM重启,或者是这个扩展的时候,是不是加载的时候都会很快。😡,这是他的场景啊,认可你就刷二波一。所以这时候你就想你,你公司项目当中凡是用磁盘IO的。

都可以把它调成reice。你公司就用了redi了,你公司的性能就已经提升了。是这道理吧。好,这是第一个。那数值刚才说数值还能它能有计算,计算的时候,它能加减啊,加一减一或者加几减几。存图片也合适啊。

你包装一下,你公司只要对着一个readd集群包装一下,内存贵,但是速度快。对不对?你比如说都不只不只用提供外部这种服务。比如对你的这个。呃。

AI的机器学习机忆学习里边可能要训练大量的这个这个图片的数据及,反复的读去反复训练。然后你这时候可以把整个一个read集群内存里的东西给它烘装一下。然后直接暴露的就是读图片的路径存存存储。

然后把这个整个外界需要频繁访问这个图片快速加载这个过程全部迁出来,对不对?啊,这是这是字符串啊,字符串不要看它表面的意思是字符串,但是他需需要把这二进制安全加进来。然后再来看数值,数值可以解决什么问题。

但哪些场景可以使用啊,比如说秒杀。秒杀这一定要注意了啊,秒杀的时候,真正啊我们在秒杀性当中库存扣减这件事情一定是放在DB的。那么拿reis做秒杀做一件事件什么事情?reice秒杀做的是限流和薛峰。萧峰。

算了,我不写了,你你自个自自个自个那个哎这个基数啊,基数也可以用它。其实。如果简单的这个基数的话,是可以拿这个sring兼职对的。但是一般我们后边还会说有一个哈西,哈西里边会有很多,对不对?其实。

薛峰还是萧峰,我忘了啊,反正就是大概的意思,这个列了吧。哎,那 string到这儿呃,你的视野我觉得应该呃以以前你可能以前你可能只知道它是一个缓存,能存一个兼职队就完事了。

但是现在的话是不是觉得哎还挺有应用场景的,你都迫不待想回去在项目当中简单的试用一下,对不对?除了两点不值钱不值钱,这都不值钱,还有一个更值钱的,它还有一个20制be mapap为图的操作。

就是为什么reis现在在出去面试的时候,为了问的频繁度这么高,然后他为什么可以取决你后边还跟你们面不面了。你reis答对了,人继续跟你聊。rereis没都没答答对的话,那不跟你玩了。先别说它应用场景。

那么beat map20制这类操作是一个什么概念?分两个阶段去我给你讲。第一个阶段我先给你去讲什么是20制,咱们复习一下。20的操作。以及专业当中如何操作二进制这个讲明白之后,我再给你讲它的应用场景。

好吧,因为可能这个大部分其实会啊,但是咱们我也我也讲一下吧,因为咱们可能有小伙伴平时没没用过这些东西。这个命令我一再强调我我敲就行了,你把它忘掉。其实在你们公司,如果真的。真的真的有运维的话。

这个命呢也会给你这个别名化,你根本敲不出这个命。这是一个清库的。库里都没有了。那么。什么是为图help。strring注意我们现在学的依然字符串,它里边有一些什么bitit set bit。啊。

然后还有一些什么get beat,或者是beat operation ,beat post或者be count,有些二人之位的这种操作的指令。它是一件什么事情来,我们来演示啊。他在库里什么都没有。

对不对?注意听,如果我set。地纸。啊,s beat set beat的时候,后边注意看字参数给出一个key,比如说K1注意听给出offset,再给出一个value,那都已经是二进制位了。

那value想想想的话,二进制里边无非就是零和一两种,其中一个那offset什么意思?先看我先写一个一,然后在偏量为一的位置,打成了一个二进制的一回车。那么这个时候首先看第一个知识点。

s K一请它的长度是多少回车是一,那么代表刚才的操作创建了一个间值段键是K1value是一个一字节的内容,一个一个字节的宽度。那这个字节里边一个字有8个二进制位,它里边是一个什么样子呢?

我们先来看它的值,最终是什么get K一回车是一个at。那这时候想一想,这有一个知识点,我不知道你们知道不知道啊,就是在计算机系统当中。有一个编码集的概念,艾特其实归属于哪个编码集。

艾特归属于阿码编编码级学linux太省劲了,书都不用买,网页都不用开。它有很多的帮助手册,menu ask玛回车。这时候他告诉你了,阿斯玛它用的是7个20之位一个字节,7个位左边那个高位永远至0。

然后后边7个的变化的话,就是从0到127的一个范围,下面的表里边已经告诉你了,从零啊数值为0的时候,这00000的时候,代表的是斜线0。然后再往下看艾特是你的011这个0101的某种组合达到64的时候。

那就是艾特。那请问。20制60就是十进制是64,是20制的多少?十这个十进制的64,这个数值是二进制的多少?

一个字节,一个只有8个连轴位,123456788个连轴位。然后我们一般怎么算二进制啊,是不是从左从右向左数就是。1248163264。每个位如果独立出现一的话,就是这个规律1248163264128。

那么其实刚才我这步sK1偏音量为一啊,打一个标识一,其实就是从左向右012345,然后在这个一的位置打成了一个一,这就是艾特在阿斯玛当中的表示形式。听出来刷波6。这是010000啊,这是阿斯玛。

那。这个你会了,而且阿码有规律的,64是它65就是大写的A。那么65实际就65,在二进制怎么表示?

这是64了,再往上加一个是不是65,这变成一是不是就可以了。那么现在怎么把刚才这个K一的艾变成一个大写的A呢?

偏移为一的这位时候打了一个一,是不是在最后那个位置再再打一个一两个一同时出现,是不是就是一个大写的A了?所以setd K179是8。因为从零下标从零开始打上一个一getK一就是大写的A。

这是可以设置的,看懂了吧?然后再来看哎,那如果我想设置注意听啊,我们看二地证码,我想设置一个数值。

找一找阿克玛当中数,你平你从平时看到123478910这里边,比如说我们看到1个48。48。48代表的一个0,对不对?嗯,48,那48的2D是多少?32加16等于48,对不对?

32加1612481632,也就是把这两位置成一就可以了,就0123把23两位置成一,是不是就可以了?所以set beat K2,先在偏量为2,打一个一,在set beat K3的位置。

这个K2三的偏量的位置打一个一。那这时候get K2就是一个数字0。然后我们increase K2就会变成一。

那变成一的话,其实是在刚才0110000的最后一位,也就是get beat K2的偏量为7,它变成了一个一。如果恶心一点,我们来做一遍啊,get beat K2的偏量为0,这左边第一个位是0。0。1。

1。0。0。0。有。Yeah。K2它的长度strring lung。是一个字节,这个字节从左向右的二令制偏偏移,2令制位的偏移ofside是0123467,那零位是0,一位是0110001。

这是它里边字节,一个字节里边二进制的这个001的一个关系。

这个看懂了吗?

刚看到这个不算完啊不算完,再再来一个再来一个。如果我对着K2做这么一件事情,set beat对着K29999打了一个一,注意偏量就不是02347了,换成了9999,打了一个一,那会发生什么事情呢?

会发生什么事情?streamring lung K2就有1250个字节。不会溢出它会自动扩展字节宽度,就是这个特征的一个特质。只要你给出偏移,这个26位的偏移。

从从左向右就是01234891112345,只不过每8个一个字节,每8个字节它会往后拼字节,这是一个特征。好吧,这个都记住了。那为什么要讲他为什么讲他?你记住这件事情之后。😡,2令制里边。

无论你是学ready好,java也好,你学C也好,学二令制意义不大。最重要的是二进制位的操作。2这位操作。什么样这个操作?它有一个beat啊,先说有一个统计啊,有一个统计。那像刚才我get K2。

这里边其实很多很多位,就这位置一,前面都是0。然后最开始的时候会有一个这个这个数值一。那么这么大的一个子接数组里边一共有多少个一啊,根据我开始的设置。怎么统计它里里边一共有多少个一。

可先说啊be count对着我K2从零开始到-1。所这里面说的是从第零的字节到最后一个负字节里边,一共有多少个一。回车一共4个。一共4个啊,因为刚才那个数值多多少,我给你回忆一下。😡。

零是64,64的话是。12481632。32加1648,所以这是一前面是一个0,就是00。11这K20,后来我让他加了一个一,所以这变成一了。第一个字就3个一。我后来在999的有点打了一个一。

所以整个里边一共有4个一。

一共是有4个亿的这个这个统计就对了。be count可以统计你给出的字节区间里的一的个数。这个抗位统治统计出来啊,然后最后是B的operations。

bitit of这个operation这个bitat operation就是做二定制的与获飞啊,你后边给出与获飞的操作的那个子子指令and all。

然后给出与获的结果的那个目标的key以及哪些可以去参与。首先我们来整合一下flash all清清完所有东西啊,跟着我思路走set bit。准了1个K1,我在它偏量到一的位置。

然后打了一个一在s和B的K一的偏量为7的位置打了一个一。就就说就是分开了,s the beat。那这个K一的值是什么?😡,🎼就是一个大写的A,就是01001,你懂吗?

就在这个一个字节数组天量唯一的位置打了一个一,就01。然后0000在7的位置,最后一个位置打了一个一,就是010001,然后再s beat1个K2也给了一的位置。

打了一个一再s B的K2给它呃偏量为6的位置打了一个一。那这个请问现在告诉我,请问K2的值是多少?K2值多少?现在K1的时候是0101,现在K2是01010,正是跳两位,它是一个大写的B。好吧。

这两个有了之后,注意看我下面做beat operations,然后做and安慰语,然后是and key的结果K,然后K1和K2做安慰语。请问结果是什么?希问结果什么?get and key。

是at为什么回顾一下回顾一下,刚才是在脑子里回忆的,现在我给你解释啊。我第1个K1在内存里长什么样子?我K一。他的字节在那那那内存里长什么样子,我怎么去设置它的,是不是在K一的下标为一打了一个一。

下标为7打了一个一,下标为一打了一个一,下标为七打了一个一。那么K一的value值的字面表示就是大写的A,对不对?

然后后来我又做为1个K2K2的时候,我是不是在下标为一下标为6的位置打了一个一,然后七的位置它还默认是一个0,所以K2的字面值多少,是不是一个大体的B。对不对?然后这时候我如果让他们做暗慰语。

什么叫暗慰语,咱俩与一下,咱俩与一下相互位相同这个高度的位去做那个按按这个二级安慰语语语计算的特征什么特征,全意为一有零则0,所以它的结果就是什么呀?就是你看这个一跟那个零就是零了,零跟一就是零了。

但是这两个一就是一就是01000000,所以结果就是at。

那这个这个第第一步,为什么是under case艾听懂同学同学来刷波6。你还可以做一件什么事呢?beat operation。做货运算就是OP,让K1K2来参与,对不对?这个参与之后回车。

那么get OP它的结果就是一个大写的C。因为按微货计算的时候,就是有一则1,有一则1,全零为0,有一则1就是010011。

01是110是211是3123,正好是这个ABC对不对。

好吧,说这是20的基本操作。这是我讲的20制的基本操作的这块的知识。这个知识只是一个复习。那么你学它有什么意义?

要看它的应用场景,那么Bm可以应用哪些场景,这个才是最值钱的。我再说你刚才听懂了,或者没听懂,下边去翻视频场景是什么?好,我给你一个需求啊。对。第一个需求。让你统计。统计什么任意。时间。窗口。ね。

用户的登录次数。就统计一个用户。这个老板你的老板说了,我指不定让你统计哪天到哪天的这哥们儿,他一共登录了多少次?那么如何落地这个需求怎么做啊?对。你可以用数据库,用日志,怎么都都可以理解,对不对。

这用数据库可不可以?你这张表,你只需要这表里边把你公司这个所有用户的每天登录的事情,888就开始管理管理记录就可以了。你也可以。比如说你曾经没做过这些事情,是不是你来自于你的日志当中会有用户的日志行为。

对不对?你再做一个统计分析,是不是挖掘一下就可以了。但是这时候你的老板可能一会儿给你一个88到8月到9月的,一会儿双十一的,一会618的。同样的数据,他可能给出同样的数据同样的人。

他可能一口气给了你不同的,或者今儿给你这个窗口,明儿给你那个窗口,所以你一定要想出一个办法来,能够让你的数据支撑这种动态的任意时间窗口统计的计算。reis不只可以放在web当中使用,在大数据。

或者你临时分析个数据都可以用,能明白我什么意思吗?那这个时候其实换成reis怎么去做?

注意跟着我思路走啊,比如说用户我你可以做一个set,先听一下库啊,flash off先听掉。sta beat,然后肖恩,这是keyK就是我我呢,然后后边肯定是valueY呢。

我就想成哎一年有多少天呢365天,那就应该有365个格子。我哪天登录了那个格子,你给我翻一下牌子。那你有什么意思吧?那比如说我第三天登录了,那应该就是012,下标为2,不过制撑一就可以了。然后呢。

比如我第第50天登录了,那就是把下标为49给我打成一。我第365天登录了,那就是364。打了一个一。是这意思吧,那这时候其实你看面向我的一个人,我的数据的统计量。Stam lung肖恩。46个字节。

即便我天天登录,依然也是46个字节,就是46,就是360360。364个1嘛,要么0要么一,对不对?明明白我什么意思吧?哎,然后这时候其实那我这一年登录多少天啊,我是不是登录3天。

怎么怎么你怎么知道的beat count。😡,肖恩从0到负1有3个一。Yeah。一天登录多次,你就一直往里设置一,那么代表这天他登录了,注意听这一天他登录了,这天登录10次,也叫他登录了。

对吧那要说两年的怎么登录的,两年的怎么怎么设置setbit肖恩。然后第八天第第二天的时候登录了一下。那明年的时候set beat。肖恩2021年的第二天也登录了一下。

Yeah。很灵活。对要我给了你一个简单的一个题目,其实你要举一反三,条件反射了,这事儿其实可以玩了。

对吧这一个统计,那么这是一个维度啊,这是一个维度,以人为K,然后以自以天数为value料占取你的二进之位再来一个需求。如果那个京东。

也就说这个肖恩202什么意思?那就其实这个key就是代表肖恩,我在2020年Y6一共有300有3有64个字节,是我每天登录状态。肖恩2021呢就是存到后边这个46个字节365个20之位里边。

就是我2021年的登录的状态,你只不过取了个名字而已,这只是个名字区别数据而已,对吧?

那接着接着跟我听啊,接着接着听他的场景。比如京东是你是你开的啊,你你就是东吧。京东是你开了之后呢,然后比如说啊618双十一,然后呢都想给用户送礼。登录就送一个礼。那么这时候你的大库要备多少件商品备货?

然后假设你有2亿用户。两亿注册用户,你在大库里边备货要备多少件礼物?备多少货啊,是备两亿个吗?看登录人数,你怎么统计出来的?🤧是不是你要根据不同时间圈,你要看历史数据,比如去年的618啊。

一共有这个有多少人,或者看这个临近的几个月,一个时间圈里边有多少活跃用户,你是不是要算活跃用户?

能理解我这个需求吧,是不是要算出一个活用户,那你算活用户这怎么算,怎么做啊,再flash烧一下。😡,用reis这么去做,看着啊。一年不就365天嘛?你公司不就是有这么多用户嘛?用户有ID对不对?

把用户的ID转成0023478小时做做做成映做成映射这这注意这样去做啊。那么一天里边有多人登录,把每个登录人在一个这个表表单上给他勾出来。

比如set在2020年1月1号这一天8号用户8号用户他登录了加一在他那个他在他那个ID那个偏移的位置给他打一了,他代表他登录了。但是这一天里边除了8号用户可能3号用户也登录了。

也给打一个一这一天里边谁登录了,谁就在那个在那个相同的一天那个日期里边,在他那固定的位置。打上一个一就可以了。那这个一行二针之位里边肯定有间隔到很多的一出现。到第二天的时候。

再s beat到第二天7日了。2020年0102这一天,3号用户又登录了,8号用户没登录。那么现在就两天的数据,我问你活跃数是两个人还是三个人。活用是223。你不要看记录数有三条,这是用户的话。

其实8号用户和3号用户,3号用户即便每天都登录,他也是算活用户的呗?那你怎么算出来的,你怎么算出来的?😡,这时候怎么去算,是不是等于有两个K了,一个1个01K,1个02K把他们的一是不是收纳一下。

是不是可以了,先把一收纳,再统计有多少个一,这是两件事情。把一收纳,把两个K里的所有的20制的一收纳成11个一个维度,里边怎么去做啊dat operation做货运算有。

系列 2:P52:redis合集:4、redis实现推荐系统抽奖商品详情页playlist - Java视频学堂 - BV1Hy4y1t7Bo

一得一相同位置上,对不对?然后结果会就是result,然后谁参与2020年的0101的一天和2020年的0102的一天,把两个两个K里边的value的一全收纳成一个reult里。

然后你再通过be count统计一下我们result这个K里边,从0到负一字节里边一共有多少个一,就是多少个活用户。

对吧这是一个统计。比如说这个上次讲课的时候就人说了,你这根本就不符合什么,我这个这个这个这个需求,我只是给了你思路了,条条件反射。其实这里面这个场景它可以是外b的,也可以是离线的分析。一件分析场景。

因为比如你公司老板就说了,今儿年底了,咱就算算这个活用户数或者怎么做一个统计。你要么用java写一个程序,要么你学一个大数据的have学一个数仓,要么就是把离线的日志数据读取一遍。

用你的java语言IO读取读一遍,把用户数据结构化之后存到数据库里或存到readit要么写circle,要么用它的2be map去分析。或者其实还有一个场景。

这个场景你们大多数尤其年龄比较大的人都知道这件事情。负一是他的所引反向的。这个场景是工作年头比较多的人都知道的,就是在我们的OA系统啊,或者是等等系统,只要他有部门有权限的时候。

或者你学过lininux。它的RWX有权限的时候,其实我们可以建张表用N个字段。代表这个人在不同的部门,不同的模块当中有什么什么权限,或者是把这么大量的一个最终在磁盘占这么多存储空间的东西换成一个。

int类型四个字节,4832,你有32个模块,那这个人在哪个模块上面有权限,在那个固定位置打一就可以了。

对不对?你比如说在我们lin那的操作当中,你会看到这样的一个效果。比如说。CDTMP目录。我的makeDR一个全圈叉叉一目啊,CD圈圈叉叉。然后在这个目录下,我touch。一个文件啊,圈圈叉叉点TIT。

那么这个文件注意这个文件它的权限是RWXRW是空RR,那权限是什么意思?如果我想让这个文件啊谁都能读,谁都能写,应该怎么写,甚至mod这个命令就修改你的圈圈叉叉点什么呀?是不是777就可以了。

那这个777这个7是什么意思?3个20制位1244加2等于66加1等于7读写执行。如果都有权限的话,是不是三个一正好是7。第二组里边这是用户的组的和他人的,其实三个不同的维度。每个维度权限全开的话。

就代表3个20制位都是一,那就是777。这回来看是不是每个位置都给它开启功能了。这个很直观吧,这个是不是很直观了?😡,对不对?如果说我就想让用户自己可以读写,其他人都不不可以怎么办?😡。

是不是春之mo的让自己是7,别的人是不是都是00,然后圈圈叉叉。是不是把别人的权限关掉了,那一是不是都给都给减掉了,这是十进制表示方式,底层是不是就二进制3个2进制位。如这只是三个啊。

如果你公司有50个模块,一个用户有50有50个模块当中的不同的模块开启的权限。你是不是只需要在不同的位置打上一就可以了?比如说天之帽子。这个是724宣传章这啥意思?7就是全开二的话。

是不是中间W4是不是R读读,你是不是可以很灵活控制这这个这个事情,这是十进制,最终是要转成二进制的。在这边是不是就是相应的s beat?如果是7的话,是不是就要给一个K1?

假设啊假设那个那个最后三位应该是7655上打了一个一,然后六上打了一个一。然后。这个西上。打了一个一,那么这个字节代表的什么意思?就是前面前面是5个0,后边3个1。

你如果想看这哥们儿在五这个偏移上面有没有权限,是不是一get beat。K1这哥们儿的555假设代表的是能不能去KTV回歌一能去玩的吧。假设四假设四是这个这个这个这个睡觉,4get0啊,你不能睡觉。

对的。

是不是这意思?哎,好收好收收收,这是他P map在这。然后这个场景就是前三个,还有一个场景在这不做展开。我只是告诉你,一般你听到的布容过滤器。Yeah。所有半布的车人。什么叫做布容过滤器啊?

布容过滤器是不是用的也是这种20日的操作。但是这时候布容过滤器,你在你怎么去用的?各位用过布容过滤器的,怎么去用的?你是在reice里用的布容过滤器,还是在你的客户端代码中用的布能布容过滤器?Yeah。

用过布能过滤器的刷一下,你是用的regs的布能过滤器,还是用的你代码当中的?布能过滤器。在代码中对不对?我告诉你reency是模块化。re利士自己就有布容过滤器。你不需要写一行代码。

你只需要调用就可以了。同学们,它底层用的就是。这个这这个beat map这个这个这个这个这个事情好收。这是光一个string,我跟你讲的,它能做字符串,但是你要二D安全,它是字节数度。

它可以存对象实session,什么东西就可以存。它是数值可以有秒杀限流,然后统数值统计。它支持二D操作,可以有相应的一些场景统计离线分析。不管怎么样,都可以让reice插到光一个str插到不同的环节。

不同的场景去使用string听名同学拉1286。好吧,就光一个str,现在你你感受一下,你感你你真的切身的感受一下。现当于如果把你放出去面试对了,聊到readit环节了。

你低头想想你公司的项目是不是有一部分东西就可以readies实现替代,或者就就这个这个了解的话,你项目的感觉。还有你对技术离解的感觉就不一样了,逼格都不一样了。是吧哎有点懵的话。

代表基础这块可能用的不多。下面呢就到咱们这个视频是可以支持回放的,好好学好好看就可以了。限流怎么搞不隆,这个这个就不不先不扩展讲了,这个东西扩展讲光了一个就可以讲一节课。我们先把整体性的给你穿完了之后。

我让你找到知识的一个脉络体系。剩下的事情你只要这个能托底能hold住了。剩下扩展的时间慢慢去扩展式不就可以了。下面讲一个list。好,脑子flash一下,把大脑也 flashlash一下。

开始这个讲listlist是一个什么东西。list首先我要跟你说list是列表的意思。在我们已知的呃质体当中,链表的话,比如说单向列表双向链表,有环无环,对不对?那么在read当中链表是双向什么意思?

一个元素既存了自己的数据data,又存了一个向下的指针,还有一个是向上的一个指针,就回列的指针,它有它要往往往前指的指针,所以一个元素可以往下走,这个元素还可以往上走。

而且它是建段是KK里边除了就这个K啊,除了K叫查K里有指针能找到这个value,在一个K当中既有这个链链表的开始那个元素的,又有这个列表最后结束那个元素的这两个指针。

所以在使用reies的链表这种Y类型的时候,你给它很多元素,你访的头和仿向的尾都是O一复杂度,一下就过去了。两端都可以快速的访问到这步能听懂回来说2波一。

Yeah。好吗?为什么要讲它?因为链表其实有很多。可以聊的事情list。啊,list似这个we类型里边有很多的指令,有很多L开头的,或者是L开头的。在reis有这么一个命名规则。

你的w类型的首字母一般是它这些指令的首字母。在例的时候有一些特殊,一些不是L开头的那其实这些个L和L有一部分代表的是方向的意思。我给你演示一下,注意听。

如果是L pushush复ush是箱列表里推送的数据,比如说K一里边,我要推送ABCDEF一共推送这么346个元素到我的K1里。那么回车就能推送进去。这里面flash忘忘了清步了,清一下L push。

K1ABCDEF推动那么多数据。那么数据推出去之后,请问这个链表不是翻车啊,不是翻车。刚才我忘了清库了,链表里边ABCDEF的百列形式什么形式的?

Yeah。

注意听它其实链表是有顺序的,但是这个顺序不叫排序的一个顺序,是你放入的顺序,从左边先放入A再放入B,那就是在A的左边放到一个B。所以它放进之后,你可以用L range可以看K1从0到-1。

就从左边到最右边完所有元素展开,就是FEDCBA。他有放入顺序,首先例子有一个放入顺序。

好吧,你能从左边往里放箱子也可以从右边R对我的K一放入XYZ。那这时候放进去之后,它是从右先把X放进去,然后再把Y放进去,再把Z放进去,那么XYZ是顺序的。

比如说我们可以通过L rangeK1从0到-1是不是就是前面这些元素是从左边插进来的。XYZ是先从右边先把X扔去,再把Y再把Z扔扔进去,它左右是有方向的。好吧,那么结合这个方向能往里插,还能弹。

比如L泡弹出我的K一弹出一个元素,F出来了。RK一就把右边一个元素,Z就弹出来了,两个方向都可以弹。那它为什么给出这四个两个方向的命令,其实你总结一下就明白了。

如果是同向。同向的命令,它这个list可以完成另外一个数据结构。这个数据结构叫啥?相同的方向都是左边放,都是左边出。

注意同一个方向。我给你演示一遍L pushush左边我们脸完K2里边放了ABC。那么最后其实L range最最后进去的是C。最后进去了C1,但是L泡我的K2却把C先弹出来了,这叫站同向为站。

就是他还可以模拟一个站,然后意向的话。就是方向相反了。是为什么呀?队立?左边左边进去,右边出来,左边进去跟一个管道一样,这就队列了。Q对不对?啊,除了它可以模拟这些东西,还有一个L index。

然后K2K1,然后给出一个下标3。

给出一个下标,可以取出一个值,给出一个下标,可以给出平你返回一个值。这个东西它又可以模拟数组。

是不是还可以模拟数组哎,而瑞。那么现在站队列数组它都可以完成了。再来看还有一个功能,还有一个功能。

是先看L range,我K1从0到-1有EDC,然后一直到XY这么多元素。注意它有一个Ltrain。trim我们的K1trim是清除的意思,删除的意思,删除什么东西,注意看从0到-1。

它删除的是你给出索引范围之外的数据。当我回车之后,请问还有数据吗?从0到-1,这里边还有东西嘛,要render这个区间里这个0到负一区间里边还有吗?有注意听它删除的是你给出的范围之外的。

就是从零到-1之外的东西,它之外也没东西了,就没删它的正确使用一定是怎么样?L trim从0到就到3。0到3就是0123,就留下的是AXY这么删,你再用L rangeK1从0到-1。就是这这他留下的。

把它删删除删除这个0到0到3之外呢,就是00123,这是他留下的这些东西被删掉了,他删掉之外,你给出这个这个这个它之外的东西啊,刚才刚才这样说反了,不管怎么样,它能删除你给出区间之外的东西。

那么它的应用场景是啥场景啊?山场去。比如说你有一篇博客下面堆了好多的评论,好多评论,好多评论。但是人们看评论的那个。特征是我打开页面的时候,咱们一般就给它显示第一页,后边几页就不要了。

他点了下一页之后才能看到,对不对啊,或者一些预加载的这种这种数据,我就可以放在缓存里边。用户有固定的点阅读更多的时候才会把东西再刷出来,其实可以把数据截断到两个地方,热数据在reise里边。

多余的数据给它清定期的给它清除掉,保证你reice内存流出来,截取的意思啊,就这个意思。

这个点这个点一定要记住了。Our train。好吧,那讲到每每讲到这儿啊,每每讲到这儿的时候,其实list似的这东西就这么这么去用。但是在这儿其实有扩展的,它的这些个东西的场景可以解决什么东西?

尤其在场景上可以解决解决哪些问题?场景它的场景是什么?可以解决哪些问题?那些困了的难受的就去睡觉,保证你的一个体力,明天在上班嗯。这个别把节奏带跑了,你这老卡困了困了,我也困了。

对吧别人别别人别人困不困。对你们一唯一独给大家喊课呢,他真的不上课了,对不是?它的场景是什么场景?大家能想一想。别一提reis秒杀抢购排行榜,把你的视野放大一点。因为你现在时时刻今天听我的课就在想着。

假设你的面试官就坐在你的面前,假设你的面试官就坐在你的面前。那我刚才问你场景是什么的时候,你就把我想的就是面试官在问你。可以做什么?我告诉你一句话叫做。其实讲sring的时候带出这句话叫做这个数据共享。

或者是把状态迁出。因为你想这个东西嗯如果不给你归,我为什么给你总结这个分类啊,为什么给你总结这个分类MQ那都是弱的那那那些个大大家都会说,我给你一些。更高级的说法。你曾经用java。

java会有一些collection。你学炸样的时候会有一些集合的操作。这个ja的集合操作是在DVM里边的。😡,现在随随便便的话,订发一多,或者是你的服务器性能低。然后呢。

这个模块没有拆分一个项目东西比较多,然后它能承受的高端连接的数量比较少,进的比较慢。然后这时候随随便便呢,现在就得就得有一个所谓的分分布式。然后这个负载均衡。然后抗并发等等的一个一个概念。

也就是你的同一个业务,它就不是一台服务器了。它可能把当起三台服务器来做一个负载均衡。那起散来之后等于有3个GBM。那么你其中一个GVM里边如果准备了一个数据集的话,准备了一个数组也好,准了一个也好。

也好,准一个也好。那么是这个GVM玩绝能玩明白的。但是另外两个GVM没有或者换言之上面说那个session,为什么session要共享出来,你登录了一台你登录另外一台那台里边没有session。

那你就还要重新登录,一定要共享出来多个并行的东西一定能读到同一个ession才能确定个这个权限,但是session还是相对比较简单的一个自符串而已。但是其实有的时候你需要共享的数据。

它是符合某种某种集合数数据结构的。那么我就可以把它迁出去,把站啊队列啊这种使用的曾经在1个GBM里东西迁迁到一个共共共的地方。听出来刷边音。那这样的好处是什么好处?就是微服务当中常这句话叫无状态。

因为你现在只有两台服务器做负载均衡并化大了,你再加一台变成三台了。但是第三台的启动的时候,你得思考一个问题。第三台8G启动,然后他是不是要先找前两台去获取数据同步,对不?

因为家这两台里边可能GM里边有一些堆列有些数组,有些东西有些数据,你不知道因为这些数据同步过了,你才能接着用。但是如果你同步的话,那这时候其实人家那边还在变化着,人家是阻塞住了,给你同步还是怎么着的。

这是一个问分布出问题,就是分布式很疼。但是如果曾经那些台,他们不自己你有自己的de collection,而是把数据全都写到一个公共的一个reis里去。第三台启动之后,他只要能连上reis。

他就有这些数据了。实时的变化也能看到。听回来刷波6。起码可以支持这个这个这些特征,对不对?而且我一再强调的是,你之前做传统项目的,我现在讲这些东西,你要低头看自己项目了。哎。

我在项目当中action就这个conter里边这个就是使用这个strring的时候都是单例的。单为什么单例单例里边其实你对象只有方法是没有属性的。单利是不是不能有属性?有如属性的话。

是不是一并发处理几个请求的时候,那个属这个属性是不是就就就就就乱了。一旦有一个数据,大家都想访问的时候,是不是得加锁啊?对。能听懂我想说什么意思吧?哎,单立的东西是没有属性的,只有方法。😡。

但是这时候如果有你在1个GVM里边,如果你你肯定有的时候是哎在几个县程,几个用户的连接读到的时候,他们处理的时候可能会有一些数据是共享的,得加锁,你把它迁出来,迁到read里。

readis还是个什么东西啊,它是单线程。你比如说你在经营当中,你可能会用到一个东西叫做conar hasab。Okay可以。卡克的哈 map可以起到一个什么优化呢?卡克的哈希可以起到一个什么什么优化。

如果俩县程,如果俩县程他们访问的就是尤其哈希 mapap和这个这个卡有卡如果两个线程访问一个一个哈 map,他们在获读写自己数据的时候,是刚好是不同的链上。哈希 mapap是不是组加加列表。

这个是仿的他那个那个那个T的时候,是在一链上,他仿的是三链上。这时候其实他们两个线程之间是没有锁的。是不是没有锁?😡,听明来上边一。因为它链锁这个这个锁锁在链上嘛。那这时候其实你你去想一想。😡。

如果把con哈西麦吧,一会儿我讲到这个reies的哈西的时候,或者是反正就是reies是单线程的。如果把这个数据结构迁到rey,re是单线程的。你即便两个县城想想操作什么事情,到那边也是串钱化的。

连锁都不需要了。好吧,听明白的刷一波666。😡,Yeah。来,我给你们推荐一门课程。你老提醒我,咱们这个这门课程就是马成平教育的课程。从小白一直到架构师,对不对?

证明这明技术技术上面还是有一些有些东西要补,对吧?不慌不慌啊,明天我告诉你结果,今天咱们先讲知识。好了,这是关于list史啊讲么多就可以了。小白的架构师绝对可以支撑你啊。例子讲那么多,回去总结思考一下。

然后下边讲一个啥,再讲一个讲一个哈希。Yeah。为什么例子要做数据共享?list可以做这些事情,我只是说就着它,我再给你扩展一下reis,可以做一些数据共享,把你的服务当中的状态迁出来。

就是有状态的数据迁出来。就是不在你的GBM里去存了啊,GBM可以用集合,也可以用对reis去使用这个集活,对不对?🤧。好了,那个我正好我明天会我明天也会讲这件事情。

明天明天的课程内容当中就会牵扯到微服务的划分AKF牵扯到从一台redis变成多台rease。然后你的数据的倾斜,还有分制的过程。那么下面讲一个哈西哈希是一个什么概念?

你就把它想成是java当中的那个哈希 mapap。我们来说一下啊。

比如说我先清一下库。嗯,这个help来学习一下哈西。哈西里面它的指量你看都是H开头的,因为你这个Y类型是哈希类型的,都是H开头。那H开头的时候怎么去做?再对先讲查之间,我先说啊,如果没有哈希。

你怎么去做哈希会有什么好的地方。你用sring就可以完成这种尖段的存储。比如set一个肖恩,然后呢name,然后是周志磊存了一个我的名字。是周志磊,然后我还有我还有别的属性呢。

再s一个肖恩age是1个18岁。那这时候其实这里面case星里边就存了关于我的两条间立段的记录,两个不同维度的valueel都都能取出来。这个能听懂吧。嗯,但是这时候其实如果你要真正想取回我所有元素。

怎么去取啊?你在客户端一定时间是case,然后肖恩星,因为肯定还有其他的维度,你要先得到一个K的列表,然后再M get。然后取回肖恩的。name然后在肖恩的age。你再给他取回来,不管怎么样。

你扣户端进定了两个环节很麻烦,这是第一点。第二1点。那么让他简单一点怎么去做?其实有H set,就是在s前面加一个H,这这是哈西的那那个那个那个维度了,它它的它Y是建这对了。前面前面我们讲的这个字符串。

它的Y就是一个单独的一个元素,但是后边这个哈西就是两个元素了,是建这对的,你可以这样去设置肖恩,然后它的nameJJL,然后再H set在肖恩,它的H是18这个写法上成本上你感觉是一样的。

但是case新的时候,肖恩就变得很干净了。只有一个,那这种写法有点太恶心了。那这时候你可以怎么做Hget or取回肖恩所有的连skimer。在value就field value都取回来。

你封装一个金字字符串,前端就可以展示了,或者是前端里边已经有固定的这个smmer了,只需要这个数据,那就是H values肖恩,那只会把数据取回来它的名字和和我这个这个大小jason直接发回去。

或者前端说我先预加载一下这个用户的这个skimer表格这个清单我不需要value值,还有H case。肖恩,你把这个取道之后,返回一个jason,那前端就可以画一个表单出来了。不是个嘛是个嘛是个嘛。

好 field。这个能听懂吗?原来刷波一就变得就变得异常简单了。😡,对吧,而且不只是这些操作,他还有什么操作?H increase increase by就是做加减加减操作。因为在这里面我肖恩。

的age是一个数值类型,我让他加1岁,那么就变成19了。你可以Hge肖恩的age单独取就是19岁。看来效果了吧。那这时候想一想,你只需要将肖恩不只是nameage加上一堆。比如他的好友好友的数量。

然后他的粉丝的数量,他购买的商品的数量。然后他这个活跃的天数,这种数值的都可以做。然后还有这个数值还能做增减。所以这时候其实哈西首先他是限立段的。

就类似于我们的哈西曼。你曾经可能是在你的GBM里边用了一个哈西 map,现在是不是可以用reis的哈西把你的GBM里边这个哈西ma是不是给以迁出去了?

那么另外一台是不是看到你写的一个hy map,他也知道那个用户有查了,也能取到的来,就数据开始共享了。那么一般它的用场景是什么?它的长景是啥?他的应用场景什么场景?跳什么场景?想想,比如说比如缓存啊。

我我承认缓存rener本身就做缓存的。他说的具体点,你公司项目中哪些东西可以拿过来用?原子的它的所有指能是原子的对象存组啊,可以这样理解,就是非非非句体化的这种对这个对象的存组。那么除了对象呢?比如说。

商品详情页。商品详那页里边有什么东西啊?用户啪点了一个商品了,这个商品当中是不是得有商品的详细介绍,然后有他的这个商品的这个ID,然后他的购买数,然后他的喜好数,它的评论数还有一些数值,这数值还得变化。

对不对?产地规格所有东西都画画在一起了。能理解我想白达什么意思吧?就商品详页,这是不是可以可以搞定了。还有什么?他其实这个这一类的这个商品详页这一类的东西叫什么?叫做聚合。场久。什么叫做聚合场景?

本来一个关于一个人一个商品或者一个行为,它有很多维度数据,维度数据可能来自于不同的模块和库表。比如说关于一个人他的基本信息来自于用户这端,然后这个人的配偶信息,工作信息可能来自于其他的模块。

然后这时候如果前端想调取这个人的全量聚合信息的时候,一个请求过来可定要访问不同的模块,不同的库表对不对?能没有说能理解我在说什么意思。那这时候其实是不是我们可以。用reds做缓存。

把这个人的所有聚合数据在不同地方上聚合回来放到缓存里边。然后用户在请求的时候就不会透穿到很多库里去了。听来刷波一啊。现在讲的是winow这个使用场景啊,像人们的可能性啊,然后为这个这个这个高频发情况下。

这个性能问题。那个时候你下节课要讲下节课讲。因为这个牵扯到主动复制集群啊,持久化呀,然后牵扯到这个业务划分AKF之类的。啊数据前置嗯,好,那是这是它的一个大大一个一个使用场景啊,它有两个优势。

一它会让你的数据更规整一些,不用。

有很多的K,因为K越多,让你的整个reis的维护成本很高,它虽然单线程,但是它是一个死循环。每循环里边或多或少会有一些事事物要做的。这个事物,比如说判断哪些K是不是该该该过期了呀,然后等等的。

如果这个K特别多的话,那就会出现问题。它的便利成本很很高。但是这样一收敛的话,那整个肖恩的一套属性,就归属在一个过期的时间这个这个判定之内。

Okay。这个我在这再吐槽一下,你看你是过来听课呢,你还是关注一些没用的东西。就是有一些人在这一节课里边啊,有人上厕所了呀,我听着好晕啊,我想睡觉啊,我困了,你是你会了,你不想让别人学呢,还是说。

你是别的地方来的人,你上这节课不想往下讲了。对吧你关注的点却不一样,这个这个这个这个这个就。🤧就不对了,对吧?好了,接下来聊啊,再聊了一个set含剧这么多啊,这个这个直播场景。再来一个是set。

set是什么意思?set现在表面来说一下set是什么意思。激活嗯。那集合是什么意思?集合哪些特征啊?记住了,集合有一一定什么呀?集合是去虫的。就是集合里边是没有重复数据,对不对?嗯,集合是去重的。

除了去虫,还有什么能力啊?集合是无序的。啊,集合是无序的,无序且去重的这为什么要可以强调它?因为在前面讲了一个list,list是有序的。但是他这个序不是给你排序,它是放入顺序。

是放入的这个这个这个顺序。然后后边还会讲一个Zet或者sty set,这个也是一个集合。这个集合它会给你维护排序。他会排序。而我们的set是集合是无序的,而且这个无序更强调一点。

它每你可能有一次看之前看的是可能是这个这个几个元素这么摆。一会儿数量多了之后,他的这些元素的前后顺序又颠倒了。他可能会颠倒,为什么?其实这有一个基本的一个常识,有一个常识,什么常识在比如在JDK当中啊。

在JDK当中。hy set其实靠什么东西实现的?hiad其实靠什么实践的?底层就是哈希。卖只不过他的歪了。we now对不对?啊,维ow只是存了K,K,只要有重复的,就反正就最后就key就是一个。

但是这时候只要谈到哈西麦吧,元素变多的时候,就一个支点,没试官肯定会问。棉数变多了,这就是就哎,没错,瑞哈西。就开始扩他的哈西这个列表的这个这个这个这个这个这个数量了。准意哈气的时候。

其实会让你元素本来是出现在一链里的,结果出现在二联这个这个这个这个三链里去了。吕哈希会打乱他们的顺序,对不对?啊,这是一个最基本的一个常识啊。

所以这里面的无序就是去虫无序且无序在整个生命周期里边对无序还变来变去的会变化。变化是因为你触犯了吕哈希啊,扩容的时候会造造成这件事情。🤧那么在讲集合之前,首先你要明白集合里边一般我们存的东西比较多。

然后它的成本比较高。就结合的操作一般成本比较高,一般都不推荐使用。当然这个是你在网上搜到的,说一般不推荐使用集合啊,集合这东西rease设计这东西有问题啊,一怎么着一怎么着就一怎么着一怎么着,对不对?

但是这时候其实你要真正理解了这个现在的项目架构的话,这个东西其实不同的实力,不同的节点,不同的rease进程,给他分配不同的工作就可以了。也就是哈希 mapap也是无序的嘛。

所以这这两个端点是来这个set上,哈希 mapap其来自于哈希 mapap的底层那个re哈希扩容这件事情。

Yeah。马上下课讲到几点,马上下课,我再讲一个点我下课,好吧,很快了,我马上讲完了,你注意听。😊,首先。Help。Set。😡,set里边他给出的指令的首字母都是S了。啊,来一个都是都是S了。

那代表s这些指令。这指令里边比有S at添加给出key,然后给memmeme和memem添进之后就变成一个集合。这个过程肯定是去重的,还有different啊做差级的,然后还有这个然后我来了。

就是做这个这个有。差级,然后交集,还有一个是病级案,还有一个什么操作的人?还有一个S round member啊,这个随机弹出。我给大家举个例子啊,S艾给出一个我先清步啊lash。

全清掉它SI的追加到K1里边,追加什么东西,就是圈圈叉叉叉叉圈圈,然后圈叉圈叉叉圈叉圈叉圈圈叉圈叉叉圈,然后圈圈叉叉。Yeah。当我给一个集合里边放入这么多元素。

这个元素里边有我特意的制造了一个重复元素,而且我在往里放的时候给出了一个他们放入的一个顺序,加击我就填进去了。填进之后,然后呃我如果取回所有呢,就是Smeers。

给出K一就给你返回它里边真正存了多少元素。回去之后,你就发现我上面给了一个2个、3个、4个、5个、6个7个元素,但里面却存了6个,且圈圈叉叉这个东西就剩一个了,也是代表它真正的去重了。

且我放的顺序是圈圈叉叉圈圈圈,却不是那个顺序。因为它里边是一个哈式的过程,而且你可以去看。O be get in coding。我们的K1哎。EncodingK一就是一个哈西table。

set其实这个K一是不就就就是一个就是一个一个一个s,对不对?因为你tap K一,它的we类型是set,但是它底层存储的是么I排机表去存储的。

这个是不是跟我所说的所有支点就挂上勾了,听不同学来2分6。对。当这个能听懂之后,再来往下捋。用集合我们都做什么事情啊,用集合我们都做什么事情。

比如说在随机事件上啊,随机事件抽奖上这这种这种场景当中,比如说Srun。的ran random就redom member随机的一些个元素给我拿出来。给出K一。

然后后边注意给要给出一个 count的一个值,你要拿出几个拿出几个里边,注意有这么几几种情况。刚才是6个元素啊,你可以-三或正3或者是负8或者是正8两大类,要么是负数,要么是正数,这个数可大可小。

就是能给出的数值有这么几种情况,我一个给你演示。如果给出一个正三的话,注意,无论是正这个正数是大小,它都是取回一个呃这个集合。只要给你返回的,依然是一个集合的话,是一个这个驱重的一个集合。所以你怎么取。

它里边都不有重复值,这是正数,正3。如果你给出一个负3负数是什么意思?你给出一数值。如果负的话,代表它返回里边有可能会有重复的。比如你取着取着。你取着取着啊,这这这这是不是重复了,这俩是不是重复了?😡。

正数是绝对不会给你返回,有重复的,负数就有可能给你返回,有重复的,小于的时候都可以好理解。但是一旦这个数变大了,集合就6个元素。如果给一个正数8,因为它的语义是返回一个去虫的集合,它就返回了8个。

它最多给你返回6个,因为这是去虫的,它不能拿别的给你往上补。然后这时候如果你给返回一个-8,负数是可以有重复的。所以这时候呢就绝对能给你返回8个。然后这里面因为是有一些重复。哎,就是他给这个取值特征。

现在听懂同学来说波一,那么他的应用场景是什么场景啊?他的应用场景什么场景?随机事件抽奖,对不对?就是微博上咱们抽奖。啊,你比如把所有人名人把这个人名扔到这个集合里去了。你你有55件商品。

那你一个人只能中一件商品,你就用正数。抽抽5个就回来可以了。但是这时候如果抽奖的时候,一个人还能多中几个啊,也不要求很公平了。反正这个抽出10个人就可以,你就可以用负数。为什么会随机?

我不懂它这个指令就要在集合里边产生随机元素个数吗?😡,这没有为什么他就想做这件事情,他就想满足我们随机这件事情。😡,对不对?那这时候其实还有一种抽奖的抽奖的这个场景,什么场景啊?

是年会年会的时候是我们把每个人的号扔到一个箱子里。抽三等奖的时候,先抽一个,最后把这个号从箱子里拿出来,然后揭示完之后扔掉,下次这样这人就不中了,就不能中了,对不对?

那这时候其实还有一个指能叫S pop。对着我们的K一一次弹一个弹完弹完弹完弹完弹完没了,再推就没有了。因为上面这一人已经挨个中完了。好吧,这个这个随机事件这能能听出来。

邵波一这是一个随机事件可以用的场景,就是抽奖啊或者随机事件,或者你是想让用户玩游戏的时候,还有随机的这个组合的宠物,你都可以这么去做。你身问这个每个背包的颜色什么样,或者什么一个有有哪些装备。

你这个随机事件都可以用这个东西来做,对不对?

随事件是一个,还有一个就是它是集合嘛,集合操作才是它的亮点之一。但是有好多人集合操作性能很低。但是如果你单独用了一个reies,就为了接收这种集合操作请求的话,就是来弥补这个这个这个这个他性能慢。

阻挡别的指令这个执行这个这个延时的问题。首先您看是一个什么概念。我再创建一下这个数据集案。不老少。全清工了,然后我的S艾。然后对着我的K1添进去ABCDE添这么多元素,然后S。

艾对我的K2进去CDEFG。有俩集合这俩集合里边,他们其实如果发生交并差级的时候,结果是不一样的。先说并级Sun对着我的K1K2,如果说并级是什么意思?病级返回的集合,就是它返回的集合依然是一个驱重的。

这里面就会出现ABCDEFG的结果。防地是集合嘛,也是一个也是一个驱重的啊,这是病级,有病级,是不是还有交集,就是S。inter,然后对着我的K1K2交集是什么意思?就是CDE是他们的交集。

就反复CD这些都好理解。还有一个就是差级分为左差右叉、前插后差上差下差,一个差级肯定有一个方向的概念。差级是不是有方向的概念?那方的概念注意,抱歉,它的差级只有S different。只有这么一个指令。

那指令的时候怎么决定方向呢?你给出P的顺序就决定了方向。就是参照谁做谁的差。好吧,这个集合的操作也能看出来上边一。这里面好多人说了,集合现在这些元素,当集合数量庞大的时候,这种交集交本差距操作会慢。

所以一定要记住了,在你公司里边不可能只用一个reies,你公司可以用一个reds。

然后这里面就是一些简单的精简数据的建设对了。就是list呀或者是stream等等的。然后你再有一个redis。是专门放某某几个集合的,就某几个集合,平时有这种这种集合操作的,放这个readice里。

另外还有一些集合,你就放在另外一个readice里。这样的话,其实你业务,你的服务在有不同的需求的时候,它是连着不同的服务器的不同的进程。那这时候这种前面装轻量级数据的就会反回很快,不会受。

因为它是串行的。如果你把这三个reis合成一个redies的话,那这时候如果这个服务调了一个集合操作,然后另另外一个线程想想取一个值,那取值的在等那个集合操作完之后才能处理它就会就会被阻塞住。

所以要多实例reice再部署这个能听懂学刷波6。好吧,那么最终它场景是啥?场景是啥?场景很重要。每个我都会给你说的场景,场景是什么?不要认为它没有意义啊,不要认为说这个东西慢,就不要用它。

我反而推荐要让你好好去用它。第一个是随机事件。第21个就是他的集合操作,集合操作其实可以完完成推荐系统。比如说相同的好友。相同的游戏。明明白什么意思吗?你比如像像像如果想做这个共同好友,用谁?

共同的好友谁?两个人的好友的集合做一个交集。对吧共同的好友,那么推荐好友。用什么呀?是不是用叉级。左叉右叉你给谁推荐,就是调整好的顺序就可以了。😡,是不是差就可以了。嗯,然后你们这个。

像病级病级可以做啥,自个思考一下。但是我告诉你了,他可以做推荐。这个推荐的时候有好友,有游戏,有商品,啥事都可以这么玩。所以还是低头看看你的项目有没有代码或在数据库当中做过这样的事情,调成redice。

速度一样很快。就两个人的好好列表,两个人的爱好,两个人的游戏,两个人的这个这个购房。两个人的这个购买的理财产品。啥东西都是集合,一个人都会有这么一个集合。集合上面如果有交并差题。

就一定会有一些共同或或推荐的事情。当然这种这种推荐系统是比较low的啊,比较low的,比较比较快速精简的,立刻上手的。但真正的推荐系统其实一个庞大的一个多维度多系数这么一个过程。对吧嗯。

所有呃所有的好友数据都存在read,不是不是不是不是你只需要把这个好友的这个ID存进去,是不是就可以了?啊,你这是最简单的一个一个一个集合操作嘛。行吧,五大Y的类型讲了两个多小时了,10点多了。

从徐春林,我们简单简单回顾一下,这里边关注一下关注场景。从str类型看似是一个所谓的字符串,却不那么简单。它里边是数值计算。虽然是字符串操作,但是它二D的安全,你可以存对象,存任何东西。

小的东西都可以往里扔。那这时候其实它可以解决IO的问题。因为一曾经存在rease这这种二支对象的数据。以前是存需要一个磁盘服务器,需要Nd等等,需要这种发CFS。对不对?当数据量不是特别大的时候。

你影响速度快的时候,解决的要就是屏蔽到IO这个层级的时候,那这时候我们是可以用reis,就光字符串,都可以解决这么多场景,这场景才是最值钱的。然后关键还有一个be mapap这种20制的位的操作其实。

呃,作为一个一个程序员,无论是C还是java,其实对二定制的使用是一个独立的一个学科。你去上网搜二定制的操作,可有很多的场景,那个场景都可以照搬到reis上,或者是你比如我给你举个例子啊。

你们如果你没学reis。你要让自己面试的逼格高一些。你比有时候都会搜一些二定制的一个操作提升性能的一个这个这个这个这个场景,在你Java的代码当中凸显出你很牛逼。但是这时候你如果再加上reis。

我都不是让我都不只是会了二令制了,我还用了reis里的二令制这种行为,还有了复读状态性的迁出等等的。那这时候其实你和面试官聊天一个reis就可以聊很久,而且聊的很开阔,很自由。能理解什么意思吧?

然后再往下聊到list的时候,list的时候,它不只是一个链表,它里边有一个放入顺序这么一个概念。所以完成队列啊,完成站完成这个数组,然后完成数据裁剪,我留住它一个顺序。

然后呢这个时候其实可以把你GVM当中常用的集合那个对象,就不要在本地GM出来了。直也签到里去,那签到re的好处是什么意思?未来你的进程,无论启动重启增加技能的数量,他们的数据的一直是持久存在的。

那这时候其实未来你还要关注一个问题,那re怎么能再存活的久一些re挂的数据是不是也没有了。但是你不要纠结,因为你曾经放在DVGVM里的GVM挂掉的数据依然也没有了,只不过放到re里边。

他可能还持久化一点,他起码给别人提供了一个共享,所以这这都是你和面试官要聊的事情,无论他提出任何质疑。那个质疑的点,代表他要问你的是另外一个基础点。至于你ready to会丢数据。

那他一定是想听听你懂不懂持久化或者集群间复制。所以只要进入面试环节,抛出一个问题,后续就要引入一个知识点。这个知识点会引出一个新的问题,那个问题一定就会引入另外一个知识点。

所以你只需要准备你的技术体系很庞大就可以了。对吧然后等到哈希的时候,这里面其实说可以没有哈希,我完全坚持对就可以了。但是坚立座会有影响,性能会变低。但是我如果把它具把相同的相同的数据。

不同维度的聚合在一起,算到一个K的名义下,就类似于哈希 mapap。这样的话取起来比较简单。关键是reice作为这种架构当中性能提升的环节的技术的话,它会让我们在使用的时候速度变得适应起来。

因为它可以让很多库表的连接,不再每请求里边都去触发。不是在所有用户的所有请求都去直接触发到数据库。因为聚合数据只要先聚合出来,就可以通过缓存的reice,把请求阻挡在你的接入层这个这个表面上了。

因为起码你前面一个index回过头来,只要看到URI直接调reis数据返回了。连你的这个tom head这种容器级都都都不用进。😡,对吧这是才是架构的一个思维。

因为你不是站在了一个的一个进程里边去思考事情了。那么讲到size的时候,它是一个集合,注意一定是去除无序的啊,然后这里面它有随机事件产生啊,然后有我们的这种所谓的推荐。

但是这时候一定要记住set操作成本比较高。因为你集合里元素比较多,性能一定低。一般使用set都不要和前面这些value的放到同一个re实例里,一定要分开放。这样的话你的业务在请求不同的时候。

那么慢速的就是慢速的快速的就是快速的把请求类型分开,把数据类型分开,放到不同实例里。当你你这么去想的时候,其实已经渐渐的有AKF服务划分的思维出现了。这时候其实已经再不是说咱们只聊一个reice的话题。

因为聊到这之后,如果把明天的歌再听一下的话。你就可以让对方闭嘴,因为要聊出很多的分布式啊,微服务啊,AKF划分啊、一致性啊,CP啊pas。这个面试你就能跟他从早晨一直聊到中午吃饭,请你吃个饭之后。

下午接着聊别的。C赛的讲,但是今天就不讲了,因为时间也差不多了,10点半了。如果这个讲完了就就就太久了。呃,这个是我到我明天讲,明天还能给你看个原码。因为计站里边会有一个东西叫做skiip list。

然后我们看看他的这个链表的源码是C源的源码是什么东西,怎么实现的这个层数的这个这个这个这个这个造层的这个这个过程,它的排序是怎么排?它原理是是什么原理?因为这个是面试的重灾区,就是如果你出去面试。

面试官拿什么东西去卡你,他一定会用。有序集合。就是必问的一个必考的一个考点。你可以去问你身边的任何小伙伴,只要你去的公司有reice面试,这个东西是一定会必问的。啊。好吧,这是今天讲的东西。还是那句话。

如果你是后来的,一直没有加过咱们这边的任何的小姐姐,然后待会儿这个图的资料等等的,都是要进群去领的。你加了别的别的小姐姐无所谓了。如果你没加的话,就加一下咱们小雪,比勾码是个6,然后我把图一会发给他们。

他们再给你们去发一下。回放是有的,然后我下课之后过一段时间吧,几个小时,然后这个视频就生成了。视频生成之后,然后是。这个应该现在还能看1024的高清的这个版本。好吧,今天讲到这儿了,怎么样有收获吗?好。

能帮到你们就就可以了啊,谢谢我也说一声,谢谢。那今天讲多下课了,拜拜,同学们。

系列 2:P53:redis合集:5、Linux系统的支持:fork、copy on wri - Java视频学堂 - BV1Hy4y1t7Bo

欢迎小伙伴们声音,没问题吧,哦嗯这个雷雷总也在,遇到个大佬,雷军,有人,嗯嗯,算了,看不到画面了,你把你那个客户端重新挤下,已经看到画面了,嗯这个这个我在这打出来,他也看不到了。

what a clap on heart,want to say,gosh,pin a place,shtuesday,i go back,want you to stay bing。

the preciate you,this time of my heart on the day,got your girl in the party,shake tuesday。

i go her want it to stay your part in the prediction,if i want my,哈哈哈哈。

on tuesday that you probably in the party,shake tuesday night of night,i always take your losing all。

this time i was down in a rise of the cal,it is me。

i never found i can to take to the party on the weekend,upstairs like,i said,i'm in i have a bottle。

arsa ship with you,do,so i get a good,look,my want some day,got your girl in the preciate tuesday。

but i love birit want it,tm stakes that you put in the party。

shado that i got my want to say that your pardon,the preciate to say that one day,我tmc有些讨厌你的语气。

真别太过马路,我曾经那些讨厌的学习打光,太是怕他们被人喜剧,你太过卖头,我自碎在是怕他们给谁去,嗯,妈妈妈妈妈,你好,我来我来我来哦来哦来嘞来嘞来嘞,on my my my,啊啊啊啊。

i look for peace to see a dotack money for keeps the soul game plan,love you b,i wanna wanna see。

i'm not the fast,i could come my soul,it's so long to the day and night day and night。

and when i wanna leave my life,be like me,like me,like me for me,啊啊,嗯,啦啦啦啦啦。

啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦,啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦,叮叮叮叮叮叮叮叮叮哦哦,快快给当当当当当当当当当当当当当当当当当当当当。

巴拉巴比巴比巴巴拉巴拉巴拉巴拉巴拉巴拉巴巴巴巴巴,啦啦啦啦,嘀嘀咩咩,叮叮叮叮叮叮叮叮,啦啦啦,叮叮当当,呜呜,拜拜拜,啊,i want my tears back。

the trees are searching this,the snow is sis between the green white flowers。

don't let those heather wind in the wheat a railroad cross water,the for grandpa,i love do by you。

it's a wonder,where it all,with the truck on it,takes me there with a relashing for your love,moch啊。

这歌听得我都我都忘了,这个厕所也没上,所以没接这俩事都没办,稍等我一下,稍等我一下,我去我去打杯水,去打杯水,救命,回来了,这个今天没洗头啊,这还有一根小天线,看到了今,听不到声音吗。

小天线应该能听到声音吧,看不到人,一会儿再看吧,咱们先太帅了,怕你们这个不能集中精力来学习,先把我们这个移出去,我们先来讲课,昨天讲到哪儿了呀,真题要讲的不是这个这个是,咳嗽了拉出去。

我这个咳嗽是经常的,昨天讲到了,该讲该讲这个骚鸡赛有序集合了,微问前面的这个应该都看完了,好好去看,尤其预习资料跟老师需要,然后现在先去讲那个有序集合啊,那么开始吧,在讲这个有序集合之前呃。

首先回顾一下上节课已经讲完了一个所谓的一个东西,就是集合,这个已经有一个set了,已经是集合了,为什么还要再出一个有序集合,这个有序是要排序的一件事情,那么排序是干什么用的,昨天有一个录播没上传。

不可能的,这是平台自己录的,这是平台自己录的,你可能是漏看了,那么要谈有序的一件事情的话,我们得先明白集合里边是放元素的,元素排序的话,那么元素应该是怎么排序呢,我们先从生活的角度出发。

比如说我给出一个apple,然后是,orange,然后再来个banana,有问题吗,有一个没回放,第一个没有上传,第一个没有回放,再确认一下吧,一会儿一会儿我下课时候,我也我也确认一下没有这个画面呢。

你就重启一下客户端好吧,待会我确认一下第一个有没有回放好,先跟着我的思路走,然后这个首先说集合里是放元素的集合,为什么还要谈有序的一件事情,这是一个非常非常根本的一个问题,首先说我现在有元素了。

那这三个元素啊可以放到集合里边,放到我们set里边,也可以放到这个soc,但是如果想使它有序放到sc的话,那请问这三个有序吗,现在这三个现在有序吗,apple orange bana有有序吗,没有。

那我调整一下,请告诉我他们有序了吗,他们有了有序了吗,啊有人说有序了,但这时候其实不精准的不精准,尤其是碰到数据的时候,这事不能这么回答,因为元素是以什么方式。

你哪个维度排序这件事情你并没有问能发能理解我想表达什么意思吧,你并没有问他们以什么排序,万一我说的是含糖量,个数大小公斤数,然后喜欢程度,所以这里面缺了一个东西,缺了一个什么呀,缺了它们排序的依据。

也就是car分值,s c car分值,跟着我的思路走啊,因为这个把这个东西想明白了之后,你这个你再去学它的时候,它里边为什么命令有那么多参数,他为什么设计成有分值,有元素的两两种,你才能想明白这件事情。

对不对,这是根本,这是第一个有你你要给出一个维度,比如说含糖量这个公斤数,然后这个营养维c等等,你给出这些维度之后,才会决定他们的排序的这个顺序元素只不过就是自身它的维度,你要给出这是第一点。

排序就得给出分值维度,另外一个既然它是排序的话啊,既然开始排序,排序的时候其实有排名的概念,所以它还有一个一个维度,就是它是第一名还是第二名啊,啊rank就是有元素,有scar分值,有rank排名。

这个才是有序集合,该为我们提供的纬度,相应的这个这个这个数值对不对,就是有一个应该提供哪333个维度啊,就有有元素自身有它的分值,然后按照分值排序,然后还有他的排名,而且既然是有序有序。

里边就会有两种序,一个是正序,一个倒序,那么证据倒叙它是不是能给我们提供以这个维度,这是在我们人的生活的角度思考出来的,对不对,哎那么这个你能想明白的同学来刷波一,这个这个得先懂啊。

这个得懂这个懂了之后。

我们再去学,先把它洗一下啊,release提起来再起一个客户端,shall清一下,这些都学会了之后,然后再help,然后我们的salted s关于有机合,它提供了一些指令。

这些和命令之前前面都是z开头的,为什么z开头的呀,只有分值不就可以了吗,那你分值排完之后,你一个三分,一个八分,一个积分,一个二分,你知道分是哪个元素吗,分值元素的俩收一个都不能缺,对不对,能理解吧。

唉就是分值和元素,因为你最重要的是元素分值值,让他去参与排序这件事情,这个z是什么意思,因为s已经被占用了,那个set集合的开始的命令首字母都是s,所以现在就全都全部用z,然后这个怎么去用啊。

我们看一眼,比如说有zi的,有经验了,添加添加,像一个key添加元素的时候,注意它跟set集合添加就不一样了,set的时候添添加member就可以了,you do the member。

这时候你要必须前面给出一个car一个分值,如果我刚才不讲这个的话,我说咱们要玩友谊集合的话,必须得用zs,然后给出分值,给出给出分值给的有点讨厌这个突兀是吧,那现在的话你就应该知道了。

比如把我刚才那个集合z add对着k1 ,然后先写分值,后期元素这样的一个成对成对出现的,比如说一个三块五的一个apple,还有一个两块,就是这个七块二的一个orange。

然后还有一个一块六的一个这个这个bana,好吧,那我是添了三个元素,且带了他们的car,分值低就填进去了,天气之后啊,然后可以用z range,然后对着我k1 ,然后呢给出起始在瑞文中所有的这种元素。

多个元素的时候,它都有这个star和,就是起始和结束,从左向右是0123678,从右向左是-1-2-3,要取回,所有的话就是零到-1,就是正向索引和负向索引,这么可以结合使用。

然后最后你还可以带着scarce分值刷出来的话,其实你会发现我给的时候是苹果orange和bana出来的结果是bana它的分值,apple它的分值,orange它的分值,这个东西它为什么后边这个小尾巴。

是因为这是一个精度的问题,分裂吧,哎那现在其实看到他已经给我们排好序了,这就是这就是有序集合的本质,到这一步能看懂,回来刷波一很简单的一件事情啊,咳咳,好了那接着再来,它有元素了,有分值了。

其实还有一些相应的其他的指令,比如说z,g2 k的时候有牌子有排名啊,你你你你比如说想取出它的排名是什么,这样给我们k1 ,然后apple他的排名为一,但是这时候注意了他的排名的索引是从零开始的。

零是banana,一是apple能看吗,就是三个维度都出现了,既有rank,然后又有这个元素,又有分值这三个维度,然后再来再来再来再来看,那它一般用它做什么事情,有排序的一件事情。

其实一般用的就是所谓的什么排行榜啊,然后有序的事件啊等等的,那这里面取的时候刚才说了,还有一个正序和倒序,那比如说听我一个语义,我想取出从小到大的前两名是什么,我想取出从小到大的前两名是什么。

怎么怎么取,z range前两名,然后k101 取出前两名是不是叫banana和apple,这就是前两名了,这能看懂吧,这就取出前两名的元素了,这在它已经有序的这个这个结果集之上。

如果再听我换换一个话术啊,请取出这个有序集合的从大到小的前两名,那怎么取,这是从老大的apple orange,那这个时候是不是就是orange apple把这两个取出来,对不对啊,怎么学啊,你说零一。

你觉得元素是可以根据你给出的参数,它就可以在底层翻个个吗,这是不对的,对不对啊,不是就没有改过来啊,我来看别人这个-2-1,有人说-2-1-2-1是负向索引,也就是说你取的整个的索引当中最后那两个索引。

而且负向索引也是什么呀,-3-4负-3-2-1,这个这个顺序就是从右边往左数是-1-2-3-4-5,所以你写的时候千万不要写-1-2,你要按照那个索引出现的那个负负值,在这个按照顺序写出来。

这样的话的确可以取出apple和orange,但是这时候你取出的是从大到小那个排列顺序吗,apple是从大到小的那个最大的值吗,不是吧,这这个其实你取的时候还是还是按从小到大,只不过取出了最后两名。

从小到大的最后两名,所以我的语义你没有实现,对不对,那这时候其实它有一个,在z rt前面加一个反向反向,这时候你再取的话,还是从零一,那么前两名嘛,前两名就是零一,对不对。

那这样取牌的就是orange apple。

这个就整个这个过程当中啊,就跟我刚才ppt讲的这几个概念就出现了,第一你要添加元素给出分值,第二它是有排名的,第三它是有正-2个顺序,你都可以实现的,然后这就是所谓的有序集合。

从概念到使用或者同学来刷波六,逻辑非常严谨吧,当这个你会了之后,它的应用场景,应用最多的场景就是什么呀,排行榜,有排行榜啊,然后有序事件,有趣的这样的一个事件或对列或消息之类的,都可以使用它来完成啊。

比如说还有这个评论评论分页评论,然后加上分页,因为评论的时候我们评论是有时间的,所以你的评论是元素,时间是分值,然后这个时候分页的时候,其实你应该是要么看到最新评论,要么看到最早评论。

就从两端看哪端去取。

然后给出区间,给出这个区间你想取多少条,如果再按一下,按一下翻页之后,只需要区间这个区间值,这个值固定的,只需要换一个起始这个这个这个位置就可以,然后后面加上那个偏移就可以了。

这样翻页也非常灵活,而且都是动态翻页,因为你在翻页的一刹那,如果别人评论的话,上一页的会挤到下一页继续看到,这样效果非常好,这是它的应用场景好吧,那么这些其实都是非常好理解的,最重要的是它是如何实现的。

就是这个有序集合啊,它是如何实现的,我们来看一眼啊,通过tap来看,我们刚才t一它是z set,是我们有序集合,还记得那个命令的吗,就一个o b g,然后e n coding,然后我们的k1 。

那现在给出了一个它底层使用的数据结构是jp list,好压缩表呃,我们上面说的类似这个value的类型和有序集合,其实它底层在你的添加的元素特别少的时候,它都会使用这种压缩表来节省内存啊。

就是类似于在一个线性数组里边把这些元素摆好了,然后之前加上一些偏移就可以了,这是非常省内存的,但是当你的元素特别多的时候,比如说z i的对着我的k一要么多,要么一个元素非常之大的时候,就会超出它。

就就会就有一个底层这个存储结构的一个变化,比如我添了一个分值99,这个22的,然后它的元素是,这个元素的值有点大,看到这个元素的值有点大,一定超过64个字节了,贴进去能往里填。

然后这时候你再看ob加including就是skip list,好吧,评论的数量太多,放缓存合适吗,看我上节课,我上节课讲过一个会维持一个合适的平均数的一个list,它有结果l trim。

然后像刚才如果你真的要使用有序集合展示你的评论的时候,这时候其实它作为分页,那么证明其实用户看不同页的评论的情,这个场景就比较大了。

就更关注这个评论内容了,所以这时候是在不同场景下,你做一个取舍的问题,因为如果你只是拿来做纯缓存,就就快速取回第一页内容的话,你用list就足可以了,特别trim它还可以清掉。

但是如果说你这个用户的行为习惯偏向于看很多的评论,而且这东西可能不叫评论,它就需要一页一页一页的,因为他不不想一次性io太大,取回所有东西,那这时候大部分用户还看全量,而不是只看第一页预热。

那这时候你最好使用有序集合。

是这个道理吧,哎所以这是一个非常灵活的一个一个一个事情,起码说release给你支持起了这个功能,用不用是你的事儿了。

对不对,翻回头来说说这个skiplist,也就是说有序集合,其实它底层啊,像这种压缩表,我们就是这个既不历史就不管他了,我们只聊这个skiplist,它是如何一直完成我们元素有序这件事情的,好吧。

这个问题问题就一会儿我们最后可以可以回答问题,现在先跟着我的思路走,咱把这个有有有一个底层,那个是个例子讲讲一下,那么讲他之前啊,讲他之前我先给你一个状态啊,就咱们先评论一下,比如说有这样的一个集合。

这个集合里边有元素x它的分值,比如说这个一,还有我就把所有元素都叫做x了,然后还有一个是,先让它有序起来啊,我先让他有序,然后呢我们找找感觉之后,先说这个修改插入的事情,当这个会了之后。

你知道他是一个什么逻辑了,再去讨论它从最开始的时候没有元素的时候,是如何构建出一个有序有序表,这事能想明白了,那么一步走一步推导,这个世界上为什么要使用这个跳跃表来维护有序。

它的时间成本和这个复杂度是一个什么情况,当你有一些元素的时候,假设一七十五二十五四十五,这是他的标分值,他们呢先组建一个链表啊,先组建先组建出一个链表来,无论你是zip list list。

其实这个list的感觉是要有的,那么先不说跳跃表示,先不说跳月表的事,先不说跳的事,先说这个普通的一个链表,当你有一个即可有一个元素,这个元素也是x,但是它的分值比如说是17,那么时期应该放到哪个位置。

才能保证它还是有序的,应该放到哪一个位置,它还是有序的呢,那么如果只是一个单向链表的话,然后你需要做的事情就是跳啊跳啊跳啊跳啊跳啊跳啊跳的诶,你比我大诶,你别你比我小b大,你不对。

我我一脚就插在中间这个位置可以了,但是这时候其实会有一个最大复杂度,有可能会差,最后就是其实它倾向于是一个o n的复杂度,有点慢,对不对,插入有点慢,那么如何调用它,如何调用它,其实什么叫跳表。

是这样的,它有一个牺牲空间来换速度啊,节省这个这个这个这个这个就拿拿拿一点时间来浪费一下,减少一下这个提高一下这个速均衡速度,它是一个渐层的一个概念的,比如说第一个元素就见了老板拉一下。

造了一个三层的一个房子,什么叫三层,一个房子是现在这个列表当中的每一个元素不只持有上下游的指针了,每个每个元素除了自己,然后分值他自个儿手里还攥了一个重组和链表。

一个若干层的一个这个层会水平的每层再维护一个链表,只不过这个链表不是向下边,应该是满的,它是会跳过,比如说这个就连到了他中间,他就没他,他就只有元素,没有自己那个那个那个那个那个几层那个房子。

先跟着我的思路走啊,你先别猜是什么,你你去推导,你去推导这个过程,推导的过程,然后他到最后可能指向了是他,然后二层的话,这边又来了一个层,然后到他了,然后他呢起起始绕,再没有元素能达到这个层次。

然后它就是new,谁也没指,没有指向,好吧,我先把这个层次给你画出来,这个层次画出来之后,比以前的这个单链表肯定牺牲了一些空间,对不对,能有什么意思吧,他肯定牺牲了一些空间,但是这时候大家注意看。

如果我拿着17,这个17应该去哪,其实17先来到第一个元素,然后以它这个元素最高的那个层次来判定下面的那个元素大小,如果比他大,ok那我就应该在你的右边找,但这个层次里边右边是没有的。

所以它降层相乘之后来到这个层次之后,然后找它右侧有右侧有,之后来到这个右侧,看元素是15 17,比你15还大,但是把你的右侧走,你右侧又是一个new没有,所以这时候我依然要降层,再降层的话。

然后走到这头是一个45,哎我这个45比他小了,那这时候其实你可以跟着往回勾,也可以再往下降层,往前往前跳跃,就一定能找到这个25,那这时候其实这个表因为它长度不够啊,这只是跳过了一个七。

他只是跳过了一个七七,是不是没有没有比较过,只是比了一个一,然后比了一个15就过来了,他跳过了一些东西,如果这个表足够长的话,其实这个优势是可以显示出来的,这个就这第一步先有一个有序,先是有多层的。

他这个查找并找到正确的位置,插入到这步能听懂是不一唉,足够长,高度是多少,这个题我给你解释,咱们看一下源码,刚找到之后,我们先说插入是一个什么顺序和逻辑,它是怎么工作的,其实如果把插入一个元素。

你想明白了,那么这时候从表示为什么都没有元素的时候,从第一个元素怎么构建,你能想明白了,但找到10 15和十那个二五之间的时候,它的成本是多少,他做了两件事情,在这一定要说说清楚。

二表示做两件事情的第一件事情是把自己入量,是入殓,不是入殓,入这个链入链是什么意思,其实都已经找,从这个他已经找到了,已经跳到这儿了,其实只需要把自己的地址付给他的指针,他曾经持有他的指针。

赋给自己的吓一跳,next指针,所以只是一个地址指针引用的一个修改,成本很低,这是链表该有的特征,到这步能听懂,原来刷波六,这是入殓的过程里,也就是链表的基本操作,那么它比链表list的多了什么操作了。

在每一个元素的增删改数量的时候,它有一个第二步,第二步就是渐渐层,他要建一个层次出来,那建层是什么意思,他会随机造房子,注意这是一个随机的行为,它随机造若干个层,比如说假设是一个抛,的确是一个方面。

假设建两层,它会有一个从这儿出一个两层的链,两层链的第一层链,那其实找到属于这个第一层链,它它这个层的这个这个左边那个元素,那怎么找到的,来自于它底层往左飘,找到你的元素,判定有没有上一层,有的话。

直接把你上一层那个指针修改就可以了,其实依然是一个修改指针的指向的一个过程,然后等于从这背离到这儿,拿到它的指针修改它,然后它如果还有一层的话,如果它还有一层。

其实这时候就看刚才你找到这个这个这个这个判定,它是不是有上有下一层,有下一层的话,直接把下一层的指针指过来就可以了,如果他没有下一层了,那只需要从这层往前跳一下,找到上一层,所以这时候他不是在底层。

纯欧文的一个便利,是这么这么这么往上跳,这个建桥建房子也是跳跃的,找他同层的最近的最最最左边那个那个那个勾就可以了,这个能听出来刷波一,你就是建层的时候,第一个是随机造成,然后每层会入链。

每层要入链就可以了,那这样的一个造成入链,造成入链,最终给我们的一个拓扑,就是它有很多的层次,这个层次其实越往上的话,这个元素的高度越倾向于稀疏,那跳跃的越远,这样的话整体的大量的增删改的操作的时候。

他这种这种跳跃表的速度和我们红黑树的速度,其实这个成本是差不多的,不过什么呀,红梅路的语法对这个这个算法比较比较复杂,这种是比较简单的,直接的,能理解现在什么时候跳跃表了吧。

这是面试常问的一个基本的这么一个数据结构。

系列 2:P54:redis合集:6、Redis的持久化:RDB、AOF、RDB&a - Java视频学堂 - BV1Hy4y1t7Bo

讲的时候都会问那层数层高的得多高,是十层还是1万层,还是还是还是几层,哎比如1000万大一千万。

这个这个数据多少层,对不对,来我们看源码,当你打开我之前,是不是教你使用源码编译安装的,对不对,所以你应该有一个源码的目录,src这是它的所有源码,c开头的a开头都是都是它的源码。

在源码里面你找一个this set有序集合啊,这个源码文件,点c这是一个c语言写的一个源码文件,这是他的,然后在这里面你搜索一个random,这有一个方法啊,返回一个int值。

这个方法是c这个this set,然后这个s是skip,然后l是list啊,就是它的跳跃表,random level就是随机的一个层数,然后给你返回一个值,这个值是取取什么的值,注意看return。

这是一个三木的一个判断,这个判断里边是你在上面这个while循环在随机数造成的时候,指定是悬空了多少次,造出了一个level值,让lel加一,指定加了多少次,你这个level值小于它一个常量值。

就是sky的这个max value最高的层数,如果小于它的话,那就取你这个值返回,但是如果你的值没有小于它,等于或大于它的话,那就取它的值就是最高最高你的层数是他给出的一个max value。

这个能看懂,回来说不是一,就是这这个这个srt里边这个随机随机造成一个函数,很简单的一个函数,相当简单,对不对,这是它的代码是相当相当简单,就是为了这个速度快,那现在你就只需要找一个点。

那这个这个常量它的值是多少,退你把它复制一下,你把它复制一下,保存,然后在这里面grep查找我们刚才给出的这个,字符串在当前目录下的所有文件查找回车。

他会给出很哪些文件包含它了。

那在这里面你会看到一个define定义啊,是在server。h这个文件里边,这其实已经看到了,是64了,到时候再带上,你再进去看一眼,它的值是多少,是64,好吧最高是64层啊。

是超不过去的啊,这到这步能听出来说说一相当于出去面试阐述你对面是你要对面,如果阐述什么第一啥是跳跃表啊,就是这样一个就倾向于跳过一部分东西,减少欧文复杂度的一个便利。

然后这就它比list多了一个层的概念,每层越往上越稀疏,那造成造多少层,告诉他原本有看的是一个64的一个常量,搞定这事儿说过去了好吧,ok收,这并不是特别特别特别特特别值钱的一个东西啊。

然后我可以看一下我这个版本多少啊,嗯这个version是,在前面能看到我当前的版本应该是一个五点点七的。

好吧,说这个因为这节课的知识量还比较多,那么五大y的类型回去自己复习吧,所有的这个value它的使用场景,然后他的一些有用的地方能解决一些问题都给他想想一会儿,如果在有时间的话。

我把我今天想的那个如何用redis,解决12306这个购票系统的复杂度的一个问题啊,这个是基本上就是按照昨天那个bmc来来来来来来解,来来来设计的一套东西,好吧收呢我们来讲讲接接下来的知识知识还比较多。

下面讲一个知识点,这个知识点里面就是关注的是redis的一些底层的,就是其实你可会可不会,但是里面试必问的一个知识,其实这下边很多的知识对于你来说问题不大,看你的这个收入层次。

如果你就是一个普通的一个程序员的话,那像持久化呀,然后集群啊,分布式这块的东西,你可以不会,因为你只需要cd就可以了,但是如果你越往上走,然后你面试的岗位工资越高,然后工资越大。

这块是基本是常问的一个问题,是的是这个是这意思吧,这个这个应该应该都能都能接受吧,然后看第一个,首先讲它的持久化这块的问题,redis本身是一个内存的,它速度很快,但是内存的话就会有一个问题。

掉点一失了呗,唉这就会掉点一失,那么在持久化这个层次,先抛开redis,而任何的存储技术,找存存数据的都有两个维度,无论你的mysql也好,就是即便这种使使用磁盘来存数据的,它都有这两个维度。

一个维度叫做快照,一个维度叫做日志啊,有人说了,说这个买买买sql关系数据库有拍照吗,有吗,有还是没有,或者是你的操作系统有没有快照啊,什么叫快照啊,最low的一种方式啊,最low的一种方式。

什么叫快照,比如说像我还是我好久好久以前啊,就是这个数据库我们都得ed去定期存一个时间点的备份,或者你玩游戏的时候突然玩玩了,然后游戏一卡,然后你刚爆了一把屠龙游戏,卡了之后没了,那个其实就回退了。

对不对,你可以对着一个东西把它磁盘上那个数据给他拷到另外一台机器去,那个另外一台就是这个原始的数据的一个快照,一个副本能理解什么意思吧,所以这个任何技术其实都是有快照,快照是一个什么东西。

就是你这个某一种技术,它某一时刻的全量数据的一个副本,只不过在redis里边,因为re的数据在内存,那么快照就是周期性的,像一个磁盘,把内存的东西做序列化,直接写成一个文件,那么它的优势就是恢复速度快。

因为这个是等于序列化,就跟这个对象序列化反序的话一样,你把它夺回到内存,这个数据就展开了,不需要什么计算和这个这个这个这个这个推导的过程,但是它有一个缺点,缺点就是丢失的比较多,因为你八点做了一个快照。

到九点的时候刚好刚好拍拍照,结果他挂机了,那你就丢失了将近不到一个小时的数据全丢了,这个什么是快照,能听懂,同学来上班一,那么基本上技术都会有日志啊,mysql有blog等等的日志是什么意思。

日志是你所有用户和这个系统的交互的时候,增删改的操作我都给你记到一个文件里啊,喷子喷的追加,那这样的话就会在一个文件里记录所有的操作,这样的话它有一个优势啊,优势就是完整性比较好。

因为你每一个操作发生的时候,我记我都有一个能力给你立刻记下来,但是它会有一个问题就是什么呀,他不是有一个问题,有两个问题,他的问题有两个,第一个问题就是因为它恢复的时候要重放。

你这个日志里边所有的指令重新执行一遍,它内存展开变成那个最终的一个数据的样子,这是他第一个问题,第二个问题,这种日志啊都是append的追加的,追加的会有一个现象。

就是比如说我对着这个redis创建删除创建删除创建删除,玩了10年,就是创建删除创建删除,那这时候你会发现书这个re内存里边就是有k没k有k没k,有k没k有k没k最后创建。

那最后那次里只有一个k内存消耗不大,但是你低头看你这个日志文件,它一直往里追加创建删除,创建删除这个文件可能就几个t了,能理解什么意思吧,也就是这个文件比较这个冗余量比较大,体积比较大。

然后里边记录一些失效的无意义的这种这种操作,注意注意听啊,注意听,这是俩问题,这是俩问题,这是两个独立的问题啊,第一个问题是必然的,你使用日志的时候恢复肯定慢,但是它好吃就完,比较完整。

只不过它的日志和对家的时候会有一种鱼,那么这里这里面这两者会有不同的解决方案,先说啊,常规的对于冗余的一件事情的话,我们可以对它做一个所谓的重写,重写重写就是去冗余的,你就把现在去冗余之前写了。

创建生猪趁机生成建成竹创建,那这个111样的一个发生定点一发生重写之后,把前面创建创建删除,创建之后没有用的东西给它删掉,就留留下一条创建就可以了,明白吧,这是一个所谓的重写,但慢了事不能不能改变好吧。

那慢的事怎么解决,先知道有这两种方案了,那么来来操作啊,再再扩展一下,在日志里边就记时日,这个行为的时候其实只有三个级别,一会我做压测的时候能让你找到这种感觉,它的三个级别是每每个用户的行为来了之后。

然后串行的立刻记记到磁盘上去,就是每操作都完成写操作,写写日志,这个不是默认的,默认的是下一个级别,就是每秒钟会触发release,把这一秒钟之内的写操作刷四单一次,或者是release。

不管向磁盘刷写的事情,完全留给操作系统内核的缓冲区,满了就往磁盘刷,那么它默认工作在这个级别,就是每秒钟会把那那个还没有刷写到磁盘做一次flash,然后最高级别是每操作都要向日志文件去写。

那么其实打如果你开启的时候啊,如果开启这个级别,你会发现你的redis降级就降到了和mysql啊,这种这种使用磁盘记录的这种其他技术的性能就变得很低了,所以要不要开启日志持久化。

要不要开启这个最终级别是取决于你的业务系统的这个这个需求的,如果对数据的可靠性要求不是特别高,其实不推荐开启这个行为,因为你破坏了redis最重要那个那个那个特征,就是快好吧。

一会我一会我给你做鸭子的时候,给你演示一下,这是两个最基本的常识概念,往下走,那么怎么去使用,注意一个版本的变化,在四点叉的版本以前,r d b a o f注意听rgb默认开启a n f默认关闭。

就是现在也是默a f也是默认关闭的,就ready,自己都知道,最好别用这种日了,因为它会有i o的这个频繁的影响,速度比较慢,但是你可以开启它,但是注意在老版本中,如果你开启了a o f。

那么r d b就不起作用了,四下伤害,以前这俩里边只能选一个,开启了a n f r d b就不不不生效,ready,重启的时候,他就会拿着a n f去回滚,所以它的慢这件事情就会放大到这步能听懂。

学来刷波一,这是最基本的一个常识,数据面试就要这样阐述清楚了,但是高版本有一个变化,4。3之后有一个新特性,这是很多技术都会实现的一个一个一个特点,就是将一个将这两者的优势加起来做加法。

去掉他们身上那个不好的一点,得到一个新的使用形式,就是混合使用,混合使用的结果其实还是a o f这个文件,但是注意你定期一开始,比如你开启了f它就一直在追加,追到好大的时候,里边很多冗余,你要把它删掉。

给他做一个规整的时候,你在给他做山种鱼这件事情,这个成本很高,不用它了,直接先来一个快速的内存,卸一个rgb文件到ai文件里边,直接把内存的所有的这个数据二进制的直接存到这个ai文件的文件头。

然后并把后续追加的日志增量日志,再追加的这个aoa o f文件里边,也就是没错,是归档加日志,而是日增量的,那这样的话rei再重启就不是只拿一个简单的af,是拿了一个混合体的af。

先把前面都快速的这个反序列化等内存,然后再把增量的日志执行一遍,这个日志就比上面那个增量日志就小很多了,那这样的话是一个趋向于一个最合理的一种使用持久化的方案,像我们的hdfs也是这么一个概念。

fs一妹子和is lab这个id log日志增量的fc fs一配置也是一个快照,他们会拿另外一台机器去做一个这个这个这个滚动,把增量的日志一直向s位置里边去整合,那么增量日志永远是少的。

只要你的日志体力一直保持很小,你的快照一直是这种这个最最近的一个某一时点的拍照,那么整体的恢复就一定是最快的好,那到这个环节点都能听懂,同学来说一,不只是redis,其实这样的技术技术类东西。

它是它是一个比较基础的,很多上层技术。

它底层可能使用了同一种技术,唉怎么使用,现在我都给你演示一下,都给你演示一下,刚才理论听完了,我们来演示,而且把压测也走一遍,找到一下它的性能的问题点,因为这些点你找到了的话,那我们讲下面分布式啊。

讲一些东西,你就可以get到它的特征了,第一个先找到它的release配置文件,v i t c redis 6379点com,这个配置文件大家走一下,我们先找你回去玩的时候。

要把这个只绑定要这个本地地址,这个事给它注定,然后呢把这个私有模式给它改成no,要不然的话你改成yes啊,别人是连不进来的,来到这这一个slipshot,就是快照啊,存那个r d b的这块。

我是直接给它关闭了,r d b没有什么可讨论的,我就直接给它关了,就是把这个参数三个参数直接改成cf空,把这r d b也关了,我们只是在关闭的情况下,一会儿他的a f混血都能实现。

所以这跟r d b是没有关系的,然后再往下找,找到我们的,af的环节,这里面就是ios的章节配置文件,其实它的文本描述是特别多的,如果你有精力,我是非常推荐你把它的配置文件从头到尾过一遍。

你对它的配置的属性值得越多,你对release越精通,很简单的一个道理,然后注意在af就是append only file这个章节当中,你要先开启append only,开启这个功能,默认是关闭的。

开启之后,然后向下它会有一个三个级别,这三个级别当中第一个就是每操作都要写一次磁盘io flash一下性能很低,我先告诉你,然后最后一个就是re,不管flash,只管right,不管flash。

它什么时候flash到磁盘的,由内核决定,这是最快的一种形式,开启a f的这种这种情况下,我们先用最快这种形式来演示,release,不染指io这个这个这个太太太太多的io的时候。

就只开着a2 f不然是太多i o的时候就没有这个级别的时候,它能最大的这个上限的速度是多少,一旦开启它会有什么风险出现,一会儿给你表表现出来,最主要是看这个配置的区间里边的最后。

哎在这儿有一个a2 f use,使用r d b上面告诉你了,你的文件当中会出现r d b file,在前面a o f的ta追加的,在后边,我们先给它改成no好吧,那么这样的话就还原到4。

3版本以前的release的一个特征了,到这个过程当中都能听懂,同学来刷波一,我们来演示把它保存保存之后呢,是redis server加载,刚才我们改的这个配置文件,6379,跑动起来之后呢。

我们去看一眼他的数据目录是在war,然后live redis,然后6379,这是在我给你预习资料安装章节当中都已经说过了,他会拿哪些目录来做什么事情,这里面会出现一个append only这么一个文件。

这个文件当中我们打开先看一眼啊,它就是一个普通的一个文本文件,而且跟我上次讲那个协议是一样的,哎几个几个几个token那个元素,第一个token它是多少个字符,第二个token是多个字符。

然后又三个token,三个token,他们每个是多少个字符,多个字符,多个字符,这是追加的指令,就是我们之前执行的指令都已经追加进来了,看到了吧,有很多,我先给他清一下吧,然后看了简单一点。

release scl and flash all,然后bg bg就是在后台做一个rewrite f,因为现在我是不是已经把库清干净了,库里已经没有任何东西了,那么这时候我如果做了一个后台的一个重写。

我的a o f这个追加文件,其实他会把那些失效的没有用的指令给你删掉,他们大概就变成零了,这是第一个表象,这段看我给大家稍微一,其实我可以给你做的更更更容易观看一点啊,比如说set一个k1 a set。

一个k1 b set,一个k1 c,那么这时候库里边只有一个k,它只是c,那么在日志文件当中,目前他一直在做,就是第一个问题,他一直在做着追加,他的追加体量比较大。

因为这里面k一的值是a是b是c它都记进去了,那这时候如何什么叫做重写你手工或者根据它的配置文件,它定期根据这个文件长大之后,它会自动的去触发bj rt去重写这个文件,编辑只要一重写。

他需要做的一件事情就是还是存的指令。

只不过无效指令或重叠指令就被剔除掉了。

他最后就留了一个k1 c,这是早期的版本,它a这个append only file文件依然记录的是指令,铭文体积比较大,这个这个回顾这个启动的时候,重启的时候依然要解析和执行它,这个能听出来刷波一。

那么我们现在只需要改配置文件,700多行吧,往下走,把他的混混血模式开启,啊不是这下边啊,在这,把混血模式开启,然后再跑起来,跑起来之后,然后呢再再来实验啊。

先来看we append only file,是有这些东西,然后他现在是c,然后我开始追加继续改啊,继续在sk 1 d sk 11 sk 1 f那么首先文件又被追加了一些指令。

但是这个指令当中最有效的指令是最后一个f前面都应该被清掉,早先的话会留着这个指令的铭文,但是现在如果开启混血了,再触发bg这个指令,这时候你再来看这个文件,它的头部就变成一个乱码了,这个乱码是因为什么。

因为是现在就是r b这种二零制的序列化的一个结果,而再不是铭文了,那么一会儿我重启的时候,前面这一段加载的速度是极快的,听我同学说不一,关键是他除了头部放了一个刚才那个那种2d的序列化的东西。

如果你继续在sk 1,然后歌set k一巴拉巴拉,那这时候他必然还是个aos,也就是后续的增量的日志。

他还hold住,还能继续管理记,那这个时候这个文件af就是二零制的头加上增量的日志。

两者恢复理论上已经是最快的这种方案了,人口多来刷波666,什么时候触发,带你看看配置文件啊,把它结束掉,它会有一些相应的配置,这是你写入写入这个级别的配置,还有一个配置是它触发后台rewrite。

这两个参数,一个是只是起起,起初的时候他达到64兆了,然后呢就给他重写一下,重启完了之后呢,后续又大了64兆了,然后呢再往上涨,超过64到百分之百的时候再去重写。

然后一直晚上只要超过上一次值百分之百就重演,就一直一直晚上晚上晚上就只有一个后台的一个值可以触发,他去后台重启这件事,你不用去管,这是服务器的这点金,用来刷波一,好吧,这是一点给你演示完了吧。

这是一个新特性,就是它的持久化a是混合使用的,另外一点我们再来把它跑起来做一个压测。

为什么做压测,这个压测还是一个,很重要的一件事情,因为你很多理论会让你蒙,首先压缩它提供了一个首先首先就是注意看啊,现在单机内,因为你ready怎么拥有很多的场景,场景不同,它的性能指标是不一样的。

我们先说在一个一个操作系统内,既有一个redis进程,然后呢又有一个benchmark,一个他自己的一个压测的一个进程,都在同一个操作系统里,那这时候他们是不经历物理网络的。

就在内部的内核就来了一个快速的一个访问的过程,也就是当前的我这个note 02里面既跑了一个redis,我又可以跑一个压测,亚瑟怎么去跑,是在你它提供给我们吗,redis。

然后有一个bench mark这个这个这个小程序help它的参数很简单,而且它很多都默认值啊,你不写参数,它都有默认值,刚来是连哪台主机,默认就连本机默认端口6379。

然后这个下边杠杠c杠c是class,也就是你的对它的连接数,connections就是对你的release要建立多少个连接,它默认是50个,然后这个杠n是request多少个请求,默认是10万个。

港d的话,默认是三个字节的一个体量,一个y的大小,好吧,然后我们先看这么多啊,往下走怎么去测,用redis benchmark杠c,因为杠h就连自己这个默认就可以了,杠c的时候注意看他默认50。

我改一下,注意看注意看这个思路的,我用4000个连接高并发4000个连接压一个re,然后杠n给他发个10万或者百万的这么一个请求过去,刚才忘了看了,还有一个杠q啊,一般我们就带着gq使用css静默模式。

不显示那个详细的日志,然后呢还可以带着一个杠t给出你使用哪些指令command啊,来来去做这个单独这个这个性能指标的一个测试,我们就杠q静默杠t只是只测试set的一种行为。

就是这个string类型的一个set,这个指令都能看同学来刷波一,但是注意观察,先观察一个点啊,这还有个小常识啊,走回车,报了个错。

count create socket to many open files,这个是一个常识,在操作系统里边,它会约束内核,会约束我们进城啊,我们一个进程梁是你吗,我突然看到你了,说我打断一下。

那个那个一会儿一会儿下课聊吧,突然看到一个老朋友了,好开心,那个这个一个尝试尝试,too many open files,操作性内核会约束一个进程,可以这个创建的这个socket数量和创建线程数的。

这个这个可以创建线程的数量,这两个是不同的一个设置啊,我们先来说它可以创建这个socket通信的数量是由user limit这个,limit,然后杠a这里边会有很多的限制。

刚才那个说不能用这个open fes,其实说的是杠n的一个选项,open files杠n1024 ,也就是现在约束了他只能创建1024个socket连接,不能太多,sorry sorry sorry。

我比较激动,我这两天吐,一直还老想你来着,想跟你联系联系,然后就一直忘了,下课别走,下课别走,但是好好聊,我正好有事找你,那么这个值是1024,怎么把它变大一点,有limit。

然后杠s h软硬加上这个n的选项给它改成,比如改成是这个6000,那么在unlimit,然后盖伦只看他的话,就已经从1024变成6000了,我只改了这块的值,注意看我只改了这块的值。

我再吊起刚才那个颜色,刚才是会报错,你不能开启更多的这个这个这个socket,但现在再来走就不报错了,看到了吧,但是这个性能来看一眼,先看一眼这个性能,性能对于sd这种简单操作的话。

它的性能在同一主机内是达到47938好吧,那这是在4000个socket连接的情况下,如果把这个socket连接降降降降级降成一走一个极端是一个5万多,如果把它升上来。

就是连接数对我们的软件的性能是否有影响,十个的时候可以达到9万了,如果达到100个链接,就连接数太少也不行,太多也不行,合适的连接数,根据硬件资源,这个是最,这个你要找到一个合适的连接数。

这就是为什么要压测这个过程到你的公司一定是按照你的积极性呢,这个值是啥意思,这个这个值叫做q p s,也就是一秒钟可以完成多少个气球,能砍回来刷波一,好吧,那么记一下,现在是在单机情况下。

我开着a注意啊,我现在是开着a o f,这个日志呢在向磁盘有刷写的一个性能的一个影响,然后但是没有开最严格的级别,然后这是第一件事情,第二件事情是在一个同主机里边,没有走任何复杂的网络。

能理解什么意思吧,你现在看到的一个最高的值将近十多万的一个600s这么一个性能,然后再来看再来看呃,我们把,另外一台机器。

打开弄个零三no 03是什么,就刚才那个测试是这样的一个效果是将近十多万,再开一个的话是,达到这样的一个效果,但是这里面还有一个矩形,这个矩形是叫做同宿主机,就是我现在的这个环境。

我在一个windows里注意听啊,我是在一个windows操作系统里边,我有两个虚拟机,一个是note 02 release,一个是在node 03,我要起一个benchmark做一个压测。

注意看我又起了一个note 03,我要是对着note 02这个redis做一个压测就能看懂吧。

哎那么这个过程当中他会走什么,他会走一个同虚拟化的一个局域网局域网,因为我的那个零三是150。13,我的note 02,有一个ip地址是15012,他们在同一局域网络,这点很重要啊。

性效的性性能是有差异的,那么怎么去做,注意看还是用redis的benchmark,然后注意杠h连谁连的是192。168。150。12。

我自己是幺三,我连那台一二。

系列 2:P55:redis合集:8、Redis vs zookeeper分布式锁的探索pl - Java视频学堂 - BV1Hy4y1t7Bo

如果客户端请求发给他之后,他内部有跟你曾经你设计的算法一样的一个分区算法,它会把数据稳定到散在不同的节点里面去,你为了你未来不同客户端读写,就一定能找回这些数据,也利用了不同的release存。

不同的数据,这个颜色能听出来,这是基于代理层实现,能听同学来刷波六,好吧,那么这是基于代理层,比如这个学习是有方法的,我图都给你画的这么清楚了,release有一个代理层技术。

其实你只需要把这个百度part一搜,这个技术有很多的,不止我说哪几种,关键是有没有人给你梳理出这个结构这个拓扑来,尤其是从客户端实现代理能实现,一直到它的集群分片,实现它各自各自的原理。

那么第三种类型就是客户端不用去做,然后也不需要有一个第三方的一个技术,因为ready自己就可以实现这个算法方面的过程,那么它们两者的差异是什么差异,你在使用代理层的时候,代理层是一台呢还是十台呢。

它的i o瓶颈呢,它的性能和可靠性,它的高可用呢一系列的问题是不是会在这出现,对不对,你是还要对它有一个记忆,就是因因为你引入了一个技术而引入了一堆问题,你为了解决这个问题要引入其他的技术对吧。

那这时候其实redis自身还有一个集群的这么一个概念啊,集群的概念rein什么概念,release他再也不是那个简单的release了,这个redis技能起来之后,它必须制成class模式。

这种模式之后呢,它里边有两个维度,第一个维度啊,它里边各自都集成了一个一个曾经你在客户端写了一个哈希算法,也就是说哪些数据应该放到哪个release里,它算法是用在了每一个re自身内部。

然后呢他并且有了一个映射关系,什么叫映射关系,他为了保证未来可以动态的rehc,还有一个槽位的概念,有一个槽位的概念,16384,你是你看这儿只有两个redis,但是其实它有一一记魔术的时候啊。

就是你的key磨的是16384,那么比如说这个release领领了这个8000,这个rise领了8000,各领了一半一半的槽位,那每个rise领了哪些槽位,你是有一个map映射的。

每个redis的这个自个儿都要知道整个机器人谁领了哪些槽位,且这个算法应该模16384,这个算法应该每个本地都知道,那这样会起到一个什么好处,get ready,看上去还是独立的,你的客户端像连谁连谁。

因为他们都有公共的映射和算法部分,只不过他们的存储部分存了不同的东西,你的客户端想连谁连谁,只要把key带过来之后,你即便给了他,它的算法部分和映射部分可以支持什么,支持拿这个p找到正确算法。

得到正确的槽位,根据映射可以知道是不是当前持有的,还是比别人持有的,如果是当前持有,就在本地直接存储,如果是别人持有的话,直接给对方返回一个消息,你的k1 remove到别人那去。

到别人这一边走算法走云社,发现是自己的,才是直接落地了,这样的话其实你上边代理层只有一个接入点,客户端只能连它,但是下边这个你就发现,如果并发的客户端想连谁连谁,最终所有的请求是动态的。

散在了访问了不同的节点上,也就是他一个集群技术,让re当中集成了这两个功能之后,满足了上面所有的需求,听同学来刷波六,啊有人说单点故障的问题啊,有人说单点故障问题其实还要记住了。

分片集群每个实例存的是你及你公司里边的这么大数据的机子,某一片,对不对,如果集群里边的这个集群里边儿的或者代理集群里边儿的,或者是你的这种这种客户端,集群里边的只有一个八一卦,是不是丢了n分之一的数据。

虽然这边还能取,这边是不是取不到了,所以是不是就我上面所说的这两种技术要整合使用,我现在单独给你讲完他们特征之后,其实你要不要给你的这个分片再做一个高可用h是要结合起来了,能理解吧。

那这个时候听到这儿能听懂,同学其实是可以接受ak f v服务划分原则了,什么叫a k f划分原则,比如这个以redis来说,它有x y z3 个轴,这是a k f的一个拆分的一个一个理论。

对于redis来说,我可以水平扩展,什么叫水平扩展准备的一台主redis多台备机,这台挂了之后,别立刻接上去,那么这种x是冗余的,它的这个这个数据是定向的。

这就是开始说的主从复制集群x轴能系统学来刷波一,那么y轴是什么,y轴是没有,我这里面有我这个y轴不是我讲的东西啊,这是一个根据业务划分的,也就是一个redis做这种准备的时候,数据量特别大了。

那这时候其实可怎么办,你可以先拆库,分库什么类似于分库,我把你rez数据里边的,比如说关于快速查询这种的,放到这个这一套rex里边,然后用另外一个re实力放的是set那种集合的这种推荐系统。

另外一个release可能放的就是详情页,根据业务存在不同的实力,所以你前端业务根据自己的需求,想连谁连谁谁挂了也不会影响另外一方,这是一个y轴,然后y轴拆分之后是等于是基于业务拆分。

然后你还可以再继续做什么呀,做高可用基于x轴,在就在y轴上,在补全x轴,高可用这个能听的同学来刷一波六,这就是x y两轴了,还有个z轴,z轴是什么东西,z轴就是我刚才聊的分片了,分片其实是面向同一业务。

比如说业务拆完之后啊,其中的某一个业务还是比较臃肿,它又不能再拆了,你不能说把这个这个这个这个你们公司这个这个香精液,这东西还拆分了,这这那那不就再再也拆不了了,这个这个数量很大,一台机都装不下了。

那这时候就要用分片集群,就是同一类数据可以分片,因为它之间虽然是分开的,但是他们基于某一种算法能理解什么意思吧,那这时候其实可以把某一个业务,然后比如说按range的range这种区间的。

比如说这个订单的商商品的0100的是取取这个分片儿里边儿,101200取这个分片,对这个分片或者直接用哈希的方式,你如果四个redis的话,直接让你的这个所有的商品的item id id值直接模四。

就可以存到不同的这个四个库里边儿,那这样的话最终你会发现ak f拆分之后,最终的redis绝对是有规则的,存储的是最小的,你公司那个数据片,再回到刚才我压测,如果你知道你公司的硬件水平,产品的水平的话。

那这时候你release要分多少个片,你业务拆多大,每个业务里最终能成多少数据,这事儿你就有可行性了,同学们就是z轴是对着y轴的某一个再给它细分化,万州的某一个业务,再给它细分化,还慌吗。

说说现在你到一家公司说你做一下架构师,设计一下咱们公司应该怎么设置这个这个这个分布式这个这个场景啊,集群怎么规划,为啥叫a k f这个理论推出的一个哥们儿,好像那哥们叫就叫a k f。

我忘了什么意思还是职位是什么,我忘了一个公司的一个哥们儿,就这就忘了这个理论,你会不会,好吧大部分都会了啊,不会的小伙伴你可以明天再去把这个预习的视频,这两天剪的视频好好的好好的去看一看,好吧嗯。

那么其实如果你做一个简单的一个回顾,我讲的哪一知识量还是蛮大的,从给你的预习资料里边,从b l n l o到e poo多路复用,到它的安装,以及到这个线程,它的io线程的模型,它的单线程模型。

然后再到他的五大y6 使用场景类型,然后再到它的持久化啊,然后到他的集群分布式的几种几种形式,这种理论就把这些东西,其实这这几天我讲的东西还真就不少。

连passos c a p a k f分分片集群的几种实现方式,这你别别别把它想成redis,你去想别的东西,基本都是这么一个逻辑,都是这个拆分的方式,因为这个后边的是谁,后边的是来自色试,没毛病吧。

对不对啊,起码说股价给你支起来了,那么这个股价里边蕴藏着很多的详细的知识点,你要把这些知识点如果好好细细研究明白的话,面试无论你面哪个大厂的话,这个这个这个级别能达到这个水平的话。

基本上是呃对方应该是可以给出一个满意的一个分了,讲讲bl nl这个东西,我是之前预习资料都已经发过了,回去看那个视频啊,那个视频是,讲得很强的啊,好吧想不想听听那个想不想听听那个12306那个事。

还有印象吧,12306那个凉火了,哈哈哈,原来原来把一个人炒火这么容易啊,这个是一个小伙伴,今天今天刻意,他就就就就这么巧,他给我发了一个消息,说老师你给我看一下1230这个问题怎么解决,他要去面试。

面试的时候是这样的,就是12366,这个比如说在并发情况下,如果不崩,然后呢,尤其我到因为因为我是北京人,我很少去参与这个春运的过程,我还特意跟几个老师问了一下,我说坐火车怎么坐啊,这个怎么买票。

然后当然了,场景后来我知道很复杂嗯,我只是根据我当时的想法,随便想了一个方案出来啊,大家一块儿跟着过一下,是这样去做的,就是我们的并发的客户端,先刷波666,咱们开始讲这个东西了,别套了。

别别别的没用了,你去思考啊,这是架构架构思维的架构思想呃,通过这个例子,我也想告诉你一个就授人鱼不如授人鱼,你要把我讲的东西应用到你的工作,就是把把我讲的东西你要吸收了,要把它应用到你的项目。

或者你现在这个找工作当中去,你如何活灵活灵活地使用它,比如说在这种12306这种这种情景下,客户端很多并发量很大,然后你去思考一个问题,当并发量很多的时候,其实大家都在干什么事情,这个前置的时候。

你可以把并发怎么忽略掉啊,就是通过什么cdn动静分离啊,然后缓存把这一部分没用的东西给它过滤掉,然后呢通过这个验证码把这种抢票软件给它过滤掉,能理吧,就是最终是人的这种线性的这种这种并发行为。

就是把并发数一定要一定要压低啊,一定要压低精准的有效的这种并发请求进来,然后进来的时候,这个用户的行为基本就分为两类,读写听友回来刷边,一就是用户的行为分为两类,读和写,什么叫读写,用户查查哎。

我到北京到上海,我我我我哪些车次有哪些座位哎,票是多少钱,我这查票对不对,这个查票的一件事情是极其极其复杂的,尤其在1230306里边,因为你的这个他给你查到的结果,这个这个维度是很多的,不光有车次。

这个车次里边有有没有几张,有几个座,这个有没有有没有站票,有没有坐票,然后这个座是哪些座,你可以选,还得他这个东西都得给你,所以他的查询压力其实远大于它的交易压力,任何东西来刷波六。

不是读写其实都是有压力的,他查压力是很强的啊,那么这件事情,我就我其实当时就是先先以这个查这个事情来举举个例子啊,我就给你们一个一个思路,你在reality做这么一件事情,be the map。

还有印象吧,b mm还有他们印象就是那个二点倍图,你看啊,如果你设置这样的一个二维矩阵,什么叫二维矩阵,就是一个be mad,然后我是一辆车,举例子,一辆车这辆车它是不是站一站二站三,有三个站点。

对不对,有很多站点,第一一个一个火车有很多站点,然后这个火车会有作为一座二,有很多的座位,对不对,哎你这样的话横向坐标用多个p,然后呢多个这样的一个二进制组建一个二维矩阵,如果谁买票成功了。

就把他的起始站和经过战,他买那个座位给他勾一就可以了,那么代表周一的就代表这个在这个占三分之内,他已经卖出了,然后那些个没有买的,那就是还是还是回零,那这个时候其实就是没有没有卖掉,能明白什么意思吧。

那你构建出一个二维矩阵的时候,在一个release里,那可以得到这样一个结果啊,就是我们可以用按位或按位或,然后用户我们的用户肯定是查询不同的这个区间的,比如用户想做一站到三站,就是1233站的话。

那么如果安危货的结果都已经不能做了,能明白什么意思吧,就是无票不能卖你了,这个过程是不需要把用户这个查询透穿到数据库的,而且这个过程还有什么好处,你把这个干完货之后啊。

然后把这个最后的结果基于二进制位里边有一有零的东西,这个字符串直接打到这个前前端,前端的js就可以绘出这张图,就这张图那些座位哪些可做,哪些是蓝色,哪些是黄色,那是红色就可以勾出来了,是不是这个道理唉。

然后这时候如果这个用户说我想做二战和三站这个请求,他给出这样一个query,那这个query,然后做安危货的话,会发现诶,作为二没有人买这个座,你可以买,是吧,但是这个我就简单这么简单。

这么说一个这是其实这是一辆车的,那么有人说,其实我查的时候,我想从北京到上海,他会给我很多的车次,对不对,那么这时候我们可以把不同的车次扔在不同的release里。

然后呢你只需要一个外层包装一个service层,就是外层包一个service层,用户只要给出了查询的起始车间,然后并发的让所有的redis调动所有rise,给你返回这个区间里面的一些车次。

他们的这个最终那个祸及这个货及就会展现在用户的前端列表里边,然后用户可以根据前端的判定,然后去勾选买哪个座位,就可以走后端的这个过程,这个过程又像什么,像以来的测试,因为在测试当中它就是多节点。

每个节点里边是一个lucy,一个倒牌索引,你要查什么的时候,是所有的减八一块查,自己做完作文表,然后返回一个结集集合,再根据排序给你返回结果也是一个并发并行的,e快了吧,我这两周周末这周末讲完之后。

下周末开始讲操作系统,i o咱们vip课里边操作系统io还有socket这种,就是底层网络io linun内核的一些个内存的使用,这个讲完之后,然后就开始讲1s1 k1 k还有什么。

还有大数据里边的这个这个平台计算之类的,这个能听懂了吧,然后整个的一个大体的一个框架,这注意这叫机缓存基础,完全,查询这个技术缓存,查询外层,你可以套二层,就2d2 d索引缓存或者二层包装缓存。

什么意思,因为用户的某种query,他如果最终是产生走购票之后,这个carry可以放到二层缓存里边,那么这个时候如果别人说,即便这个车卖,今天老师还那个连老师还跟我聊,他说其实我我买票的时候有一个现象。

就是这个票都卖完了,但是我还可以对着车排队,如果有人退票,如果有人退票,那么我我如果排到第一个,我就可以立刻知道,那这时候其实可以在二层缓存里边做一个什么呀,队列对你的query,那一旦里面有退票的话。

直接查这边,然后触发调调出第一个候补人,然后可以继续买票了,然后还有一个就是你要学风学的什么风,吹的是这个这个这个负载负载量,什么叫负载量,如果一个人因为大家同时看这个的时候,注意听。

大家如果同时看这个查询的时候,大家都发现说诶我这个票可以买,但是注意听啊,如果发现这个票可以买,把这个票可买的一件事情放到查,只要一查出来就放到这个二级缓存里边,放大镜可能放一个hay query。

就跟我们买sql数据库,一般你如果写了一个circle,查出结果之后,它这个sql的结果缓存到内存里边,它这个sql语句会做一个哈,希如果未来查询的时候,你的外表条件没有发生变化,跟那个长得一模一样哈。

一直一样,这个结果直接可以拿走了,能理解能理解大家什么意思吧,有有了他了,并一个人已经触犯,要购票走他了,但是购票这哥们儿可能有30分钟的一个什么呀,付款失败。

但是我可以先把这个query的值放到这个库里边,那么别人只需要再查的时候,先统一个,就从那个二流可能就过滤掉,连他这块查询那个二进制二分计算都可以屏蔽掉,缓存量是不是很大呢。

如果你看过昨天的beat map,你会发现这个缓存量其实并不是很大,都是字节,一个字节,八个二进制位,对不对,其实这个这个是非常省空间的,而且关键是二零计算。

你这块的计算一定比你数据库的计算速度快好几个指数级,换一句话意思就是,如果现在我给你投钱,你买50台机器,这个这个调优未必有把这五台放到缓存内侧来的,更更表现更直接认可来刷一波666,这就注意了。

最后一直在强调,无论秒杀系统,任何交易系统,最终只要扣库存,所以今年交易最终是要让他透穿到db的,就是这层,你是不可能跳跳跳走的,最终最终是要最终最终是走他走,他成功之后。

事务里边会修改这个缓存的这个这个相应的座位,这个时候只需要记住一句话,就是尽量的让有效的请求压到你数据库就可以了,数据库你再做一个分子表,但是把那个所有复杂的查询等等。

那个那个那个那个请求越在前面过滤掉越好,而且这个缓存的这个场景当中,它是单向应用,也就是说用户只会查,用户不会写,只有老师不是,别别说只有这个这个服务扣这个订单。

这个交易成功这个环节的时候才会去写这个缓存,即便给一个缓存开启了a o f最强的持久化,都不怕,就开启最强的持久化嘛都不怕了,尽量他宁可慢一点,但是我绝对让这个就是写操作订单那块可能慢一点。

你就购票的时候啊,等一会儿半天我告诉你订票成功了,但是别人查的那块就嗖嗖的快,能理解什么意思吗,所以这时候你就你就你就站在用户的一个甜度,只要我能把票买上,我前面查票是足够快了。

其实我后面买票的过程其实也就差不多了,对注意听啊,这我就是就是他问我今儿问随便问了我一台,我就随随便便想这么一个方案,这个方案存在很多的不确定性和bug,大家我只想告诉你一个什么呢。

这个不是要告诉你一个12306这么解决就是一个方案了,这未必是个方案,他也未必是个思路啊,有人可能比我更更强大,因为你要牵扯到这个火车路线构做的一件事情,如果再复杂一点的话,今天我还特意问了一个同事。

我说买火车票会不会出现这种这这么一种情况,我从a d买到bd,其实他要走222个火车,中间要换乘,然后他告诉我是有这种情况,就是他支持这个东西,当时我就凌乱了,我这个东西不支持。

因为这东西其实就迁到一个图计算了,对不对,那这时候如果你换图计算的话,可能是另外一种解决方案,但是我觉得你把缓存加到你的架构里边儿,这个东西一定是最直接的,怎么保证最终一致性。

你把真正要双写的一件事情压到最后,压到最后,压到最后全部压到最后去,就是最后真正交易成功的那一刻,这个事物在这块保证住了,库更了,redis更了,给用户返回一个你购票成功,这事儿到这儿的量级其实很小的。

是真实的,是有效的,你在前面用更多的方式拦住那个请求,别争抢,在这还有个小球点,就是这个二级,这个就是机缓存,还有一个二级缓存,二级缓存那个hi query,什么意思,就是你曾经的某一个。

比如说这哥们儿已经是走了一个订单,他是就是排队啊,十个人抢着一个车票,注意听啊,十个人抢着一个车票的时候,那么总会有第一个人产生了这个hit query,就放到这个缓存了,这个high query。

比如就是这个二,这个这个作为二的打了一个一,那已经有一个人抢到那个high query了,那后续的人就是这个所有的一个操作的时候都盯了一个hdcry,那别人只需要盯这件事就可以了。

或者人家就放弃这件事情,就是可以先走走一个一个过滤,然后这个high还支持哪个环节,就是在即便是你可以不让那些人放弃,两人一块儿过来,一个人先是生成这个抢票订单的时候,产生一个high query。

然后他付款成功之后,会把这个high query改成一个码值,改成二,或者改成一个三代专利里边,那未来的流量就直接就被平掉了,或者在这块真正发生交易的时候,扣减库存的时候。

绝对不会不会再有一个多余的这么一个一个一个触发,因为他会撤销掉你后面排的还想买那个座位的人,就是会还会有一个过滤撤销的一个过程,也就是最终你是要靠很多清洁切,就跟a o b切面一样。

切到所有的这个这个路径的所有点上,利用多级缓存,让你最终数据库到达的写操作是最精准的,呵呵呵,脑裂导致的分布式锁重复,怎么去解决这个问题,也没有读懂,多级缓存是个有意思的东西,的确不做有票的情况。

还有现在疫情票都是合作的,咳咳咳,你这个你这个你要玩死我啊,无座这事我也想过啊,没有就是这个这个咱还有站票,站票这事,我这今儿还有点那个啥了,嗯算了,这个思路给给你提供了好玩吧,这个好玩吧。

怎么这个我讲这个过程啊,是要让你知道一个什么什么一个点就是什么是架构师的一个思维,就是呃你可能曾经关注的是api,但是当你会的东西越多越多之后,当需求产生的时候,你像今天这个需求。

我就是我可以可以说这个就是分分钟就随便想了一下,形成这么一个思想,出这么一个方案来,因为我正好今天要准备一个rx赢一个课,为什么讲它跟这个有关系啊,这个这个认可吧,认可来敲一波666。

想他是什么意思,嗯是这个意思,这两天了,然后给大家带来了一些课程,这个课程其实是嗯我是谁啊,我是周老师,我是周老师,然后我是我们几个老师,是和马士兵马老师,一起组建了一个马士兵教育。

这个教育是以马老师名字来命名的,然后我们是想做一个非常重大的一个事情,今天呢也借着这个机会给大家做一个小小的汇报。

就是我们的成长历程。

现在我们所获得的成就,以及未来我们要做的事情这么多。

bt的老师,我们干一件什么事情,好吧,多少年经验了。

我开发了将近十多年了,很简单。

就是我们和马老师要做一个已经完成了第一个小部,就是在腾讯课堂已经拿到了一个最受欢迎奖,什么叫最受欢迎奖,就是在编程类目里边,就在整个程序课堂,编程类目里边加个语言,这个所有的科目,这个所有的机构里边。

我们的好评度站在用户的一侧,嗯是一个最受欢迎奖。

是最受欢迎的嗯那怎么实现的。

其实是是咱们讲课你也听到了嗯,就是这么一个两分钱的训练营,然后呢我尽量是给你玩的命的,给你堆这个知识点啊,从基本上这个从从这个预习资料到两节课,如果这些加起来的话,这个质量是很很大的。

我们说回放可模糊了,回放的时候你可以选它有720p和1024p,1024p就是高清了啊,你要选那个高清的就就会很清楚。

这个我们一直就是一直这么做,才有这个这个这个奖项,那么这么做的一个推动我们的一个核心思想,就是我们想创建一个在在线教育里边的,一个从小白一直成长成行业大牛的这么一个套课程出来,这个课程从四门课的设计。

你可以发现我们是从小白,然后你转行,或者你是大学生,没学过编程的,有一个零基础的后端工程师a课程,你包你从那个课开始就是接受小白了,然后一直学到最后项目死。

ming boot项目光了一个项目就是175张表左右,这样的话学到这个这个层次的话,到spring boot级别,但是现在我跟你有啥说啥,你光学这个课出去找不着工作。

因为你随随便便翻一下现在招聘简历的话,这个招聘如果你面试的话,常常问的面试题,咱们刷一下,小伙伴,咱们刷一下,你如果最近有面试的,常问的面试题都有哪些,就在刚开场的时候,第一面的时候什么我不说。

你们来说,咱们互相刷一下都会哪哪哪些题会问到你,你叫什么名字,像算法jvm调优和smap,设计模式什么锁呀,g u c啊,signt对不对,多线程啊,这基本都是一个常常问的。

所以这个环节学完之后啊啊还差那么些东西嗯,而且尤其技术站各种的redis mq啊,mysql调优性能调优之类的,所以我们还有一个互联网架构师的课程。

这个架构师的课程之前是我们之前设计的时候是一个p7 的一个标准,就是能够达到阿里p7 ,其实有同学知道啊,咱们咱们这个在座的小伙伴应该有有几个知道昨天晚上出什么事了,这个因为他那个一鸣老师打电话来着。

然后那个那个脾气还挺爆,昨天是也是赶上那个阿里的几个人过来,就是马老师约了几个人过来,然后昨天晚上聊到两点多,要去把我们的课程从p7 调成p8 ,这个水平就是经常也是约他们过来聊这个事,咳咳咳。

目前是到港的一两个老师已经挖过来了,就是从阿里挖过来挖过来的老师,目前说现在课程我们讲完的是对标的是p7 的一个水平,p8 的确p8 就是已经是带人,那个就是带团队在这个这个水平代码量已经不是特别多了。

但是你必须有这个架构思维和决策,而且如果感兴趣的话,你可以找我单聊,其实昨天聊的时候也说了一些不该说的事,就是内部关于p8 p9 这个两级别内部有什么东西啊,这是一个互联网架构师啊。

然后我们这边的标准就是带你带你的大带达到这个大牛,这个大牛是什么意思。

系列 2:P56:1 操作系统中的BIONIOSELECTPOLLEPOLL实 - Java视频学堂 - BV1Hy4y1t7Bo

跌了之后,nt无师自通,无师自通。

切到讲课这个这个这个资料是是我最近在讲vip的,关于计算机系统的整套的i o这个环节,我画了这个隋隋唐画的一个图,就是从磁盘io啊,网络io内核pd开始,然后从b o n i o到多复印器。

刚找到刚脚的多路复用器,到java jdk的select到不同的多路复用器的一个映射关系,以及它们的性能的一个对比,而且过程当中还有一些压测。

今天呢我们来也就是其实io这块是一个非常非常非常重点的一个知识,能get到的就是i o,其实说白了你去思考,而不是现在所有的东西都离不开io,都离不开网io一个程序,如果没有i o的话。

这是谈不上它是一个程序,所以io如果学好的话,就是为什么我们要学ei o这个字体大小合适的,来刷一波一合适吗,有问题你就直说啊,就是这个哪方面都有问题啊,你就直接说出来,反正改不改是我的问题。

回音严重啊,这是没有办法,就是这个刚搬家,我把这个麦风离我的身边近一点,就刚搬过来,然后还没有没钱没钱买家具了,哈哈哈,刚报完家,没钱买家具了,然后屋子就挺空的。

然后为什么要学e i o这件事情非常重要啊,有过相应工作经验的小伙伴应该都知道,就是i o无处不在,而且io关乎到我们程序的性能,io是无处不在的,你随意可以想到的一些常用的面试。

常用的一些地方都可能会出现关于i o的一些问题和知识点,热门的一些技术问题,有时候问你了解吗,对不对,然后redis了解吗,然后卡夫卡了解吗,nbx了解吗,其实这块的技术你可以聊出一大堆来啊。

然后基本上他们都会和i o相关,然后他的对于性能,至关重要,是这个吧,这个光度无所谓了,好那么先铺垫一下,就是把心态调整好啊,那我好好学这个我画图的软件,我也给你写出来啊。

我画图的工具是一个在线的网页版的一个p3 ,那我直说了,我要我想要你的图,想要我的图,行一会我告诉你怎么能拿到图好吧,今天我给你们单独随堂画图,这是我讲课的一个风格,知道i o的重要性之后。

那其实i o的整个的i o i o其实是一个大活对吧,就是一个全套的一个大货,那io里边的知识很多,那这两就这两天的两天的课,两天的训练营,我们要学习哪些关于l的哪哪一块的知识。

只围绕注定只围绕网络通信中的i o,也就是偏soft,基于socket之上,你首先理解什么是socket,然后以以至于基于socket之后,然后可以产生的这种网络通讯的i o它的演变的一个过程。

这个过程其实大家都知道,从b到nl到注意下边多路复用器,然后以及在这个io模型就是网络通信的io模型的演进过程当中,变向不同的语言,比如这个gp c或者java他们的a p m。

其中有一些现成的这个产品和框架,进行了对io框架的一个io模型的一个包装,这个像java程序员必须要学要会就是nike,而且这些都是面试的重灾区,常问的一些问题,且其实你去网上搜一些资料。

资料的描述不清不楚,各种描述可能都会有,好吧,这点一定要认可,就是我们今这个这个这个这这整个这条线是我们这两天要学的东西,好吧哼哼,那么在学习这些知识之前,我要先抛一个我讲课的风格啊,讲课的内容再讲解。

把这些东西如果真的想讲明白的话,首先我会帮你在课程当中梳理你要去掌握和学的东西,以及我课上会有一些小工具小方法来协助你更好的理解,但是其实对你的基础是稍稍有一些要求的,可能有些东西你要去补。

第一个需要去补的知识就是计算机组成原理,计组计算机组成原理,那在这个课的直播过程当中,我会简单的介绍,如果你听不懂的话,先听个响,起码你知道哦,这块东西如果我会了的话,那这整个io的可能一大票的东西。

我我就已经可以很容易理解了,如果这块你可以,你就是首先说作为一个java程序员,这块你可以不用去学,但是这时候其实技术你只能学到它的表面,a p i自个儿能敲出代码来,符合自己的逻辑,能写需求就可以了。

但是如果真的想把这个技术力的很深,面试的时候可以和面试官对答如流的话,那你对底层可能要更深入一些,比如说先聊一个知识点,计算机组成最基本的,因为这里面会牵扯到我后边讲io模型演变过程当中。

他为什么要去从bo到neo的多路分析的一个演变过程啊,这这个这点很重要,首先第一个计算机组成组成基础知识就是计算机是如何运行的,我们的程序是如何运行的,这里面有哪些是损耗性能的。

哪些行为我们尽量去避免啊,这个我直接在上面画图啊,咱们加加快时间,第一个知识点是计算机里边有哪些硬件组成,一个是内存,然后有cpu,假设我们只用一颗核心cpu这个计算机,然后呢有计算机不是有个cpu。

有内存,除了这些之外,还会有一些io设备,这个io设备,比如说我们的网卡,网卡是io设备,还有什么是io设备,就是输入输出设备,我们的硬盘也算,其实在整个io体系当中,除了一个网络通信l。

另外一个分支的o就是关于硬盘这块的l的一个性能调整,它的一个实验原理,也就是它的虚拟文件系统以及内核的缓存页等等,还有我们的键盘,鼠标等等,一系列的这些都是我们的io设备好吧,那先把硬件。

这是计算机的组成,有这么多硬件组成,那我们的软件如何在这个硬件的配置下去执行的,首先当你摁动你的电脑开机的时候,其实硬盘里边第一个程序,第一个程序是我们的内核,首先程序在硬盘里边就是个文件。

然后通过读取它进入内存展开,根据他的这个编码格式,根据内核的这个展开,整个这个文件的格式展开之后才会变成进程,所以第一个是内核,有我们的硬盘被加载进了我们的内存。

当然在前面还有什么这个bios进入内存啊,然后这个不是这个引导程序性类型,最终是把内核前面一段就忽略了,我们直接说内核,首先你要明白内核它也是一个程序,这些词汇也都听说过,但是你有没有具体问过。

尤其咱们不是本专业的小伙伴,就是内核,它到底是个啥东西,就计算机里边为竞机操作系统里边为什么有一个内核,而且它还是个程序,首先要明白内核是个程序,它对外管理了我们所有的io设备,那又代表什么意思。

其实是一种分层结构,在硬件和最终有了内核之后,你才会从硬盘加载你想跑的程序,就是top hat等等的,有lication,那么其实内核和程序和硬件之间它是一个中间层,它是一个管理层内核里面。

如果对硬件的网卡驱动实现了,那么在我们的所有程序当中,就不需要重复造我们的重复实践网卡驱动对吧,内核如果对我们硬件进行管理了统一的资源的控制了,那么这时候程序就不需要自己再写一些和别人如何竞争资源。

这样的代码啊,那这个内核就是一个大管家,这个能听不出来刷波一有人说前戏比较长,唉那这个后边你才能飘得更高嘛,对不对,学东西要学明白啊,就在这儿,我一定要给那些个新造的小小伙伴来说一句。

这个中年中年逆耳啊,就是咱们学的是it it啊,其实这里面是一个理工科的概念,这个所学的知识你一定要一个目标,就是学明白,你当你学明白了之后,这个东西不需要去背,这辈子你就你就知道怎么回事了。

就跟说定理公理的一个概念,当你懂了,知道了,真的学明白了,那这个不需要去背,所以我为什么前戏这么长,我让你把这事给他学透,学这个完全理解对吧,好跟我的思路走,整体上有个硬件。

然后呢程序之间为什么分为内核和我们的lication,这给大家去介绍一下,在这里面还有一个支点,就是其实计算机啊内核已经发现了,他对这个至关重要,因为内核就是这么一个程序,一个在这个内存里。

那我们的其他的用户空间的程序有很多,对不对,后面给你解释为什么它叫做用空间呢,那这里面为了趋于安全考虑,因为大家都可能会使用去使用这个内核,那么现在进入一个这个是否是安全模式这么一个介绍。

当其实计算机开机之后啊,内核如果被加载进内存,cpu执行内核的里边的指令的时候,内核做一件事情,注意听内核做一件事情,比如内存是个线性地址,023578 90 11 12 13,一直到最大,通俗来说啊。

注意通俗来说,内核会把内核所在的地址空间,所在地址空间置为这个绝对安全的,就是内核空间,它会在一个叫做gdp全局描述符表里边,标识出它的这个这个这个这个数据段和这个指令段。

然后将剩余的空间划分为用户空间,把这两个地址区域划分出来之后,那么他要做一件事情,它要启动一个模式,叫做安全,这个安全这个保护模式还不让保护模式,这个保护模式是什么意思。

跟咱们计算机那个安全模式还不一样,保护膜是什么意思,就是诶那么在我内核空间里边,如果cpu做到指令了,它可以访问整个内存的任何的地位,但是如果在用户间你写的程序做到一个指令,如果你想访问。

你硬硬硬生生在说想访问前面这个地址框里边东西,它是静止的,或者cpu里边有很多的指令,就是一个指令集,有很多指令,那么有一批指令和有一批寄存器是内核可以完全访问,完全调用的,但是你普通程序是不能用的。

兄弟们,就这样的话,就基于内核控制了,自己可以访问别人,别人不能访问自己,以及cpu里边也要达成这个保护模式的实现,就是比如这个英特尔或者amd,然后有一些计算器啊和指这个指令指令。

你其他程序你级别不够,你不能访问,那这样的话其实就可以减少对系统的破坏,也就是蓝屏的出现的情况,到这一步,什么是保护模式,能听懂,跟大家说不一很简单吧,如果内核可以允许其他程序随意访问。

随意修改里面的东西的话,那这时候你的程序就完全可以分分钟变成一个黑客或者一个病毒对吧,嗯那好接着讲,那有了保护模式,但是要和我刚才说的理论进行一个对对冲啊对撞,我说了,内核其实向下关于我们所有的硬件。

然后程序呢不需要重复到轮子,不需要写这些硬件驱动,那这时候程序我们肯定是要使用硬盘,使用网卡,使用键盘鼠标,那这时候使用外外设的时候,那这时候必然要访问内核,内核要暴露给程序一些调用对吧。

但是这你又加了一个保护,你还不能访问我,所以这里面要加上另外一个知识点,这些这些城市基础知识点啊,首先你明白它有一个保护模式,你程序不能访问我的直接地址。

但这时候我又想给你暴露一些我对下层这些东西的抽象和包装,得让你去使用,那怎么办,这里面有一个概念的中断,第一个是中断,第二一个是内核,内核首先对我们的程序提供了系统调用。

就是内核是给我们程序提供系统调用的,比如说调用了关于i o的读写,那这时候你还不有保护膜,人还不能直接访问我,那怎么办,其实底层靠的是中段,那中断是什么,我简单的介绍一下。

比如说常见的中段有一个叫时钟中断,什么叫做时钟中断,因为中断这个事必须讲中断这事儿你不了解的话,那后边i o为什么变化,这事儿你也只能瞎猜,或者就是别人怎么说,你怎么去怎么去解释。

而且你根本就不理解为什么性能会变低,中断这件事情非常重要,能理解吧,比如说先说一个叫什么叫时间时钟中断,那么在描述时钟中断之前,我先问大家一个问题,刚才我刻意说的cpu只有一一个,只有一个cpu。

那计算机里边我是不是可以内核程序,然后我启动了tom cat,启动了这个and dex,启动了这个mysql,他们都是程序,那么一个计算机里边可以有很多的程序,请问这些程序只有一个cpu。

他们可不可以并行执行,可以还是不可以,但是他们是不是可以同时启动,然后感觉他们感觉他们是在并行执行的,那么他们是如何并行执行的,这点要明白了,这个里边其实有一个没错,有一个分时系统,一个时间切换的概念。

对不对,一个时间片大家轮流去执行,比如先内核执行眼,然后这个程序这个程序哎,我在单位一秒钟之内,然后结果让你们每个人都执行了好多次,那这个一秒钟的对外界的体感,这事啊好多程序都在同时执行。

这个能听我们来刷波,10分复用,没错,就是这些东西,cpu时间片轮血量等等等,但是这时候你要我,我立刻要问你一个问题了,立刻要问你一个问题,你在你写程序的时候。

你有考虑过说一秒钟之内我只能执行1/1000秒,我执行到1/1000秒之后,我就要让出我自己,我把我自己挂起,我通知别人去执行你,你没有写过这样的代码,你没有写过的话,那就代表什么意思,你优惠你的程序。

只要cpu去执行你的程序,你的程序会耗死这颗cpu,这是一个cpu,就不能执行别的人了,别的东西了,这个理论能听得出来说不一,就是你写程序的时候,你从没有让出过cpu,那你的你不让出那一秒钟之内。

他怎么去执行别的这个程序的呢,那么时钟中断这个东西就就就产产产产产生了时钟中断是个什么东西,它就类似于一个物理硬件啊,物件这个物理硬件叫什么,叫精准,如果你去关注过老式那种电子手表的话。

它背面电路板上有一个小圆柱,两两条腿,一条腿进了一个这个电源,然后呢这个咱们呢比如直流电就是啊一直有电,就是你把手啊站着站着唾沫摸那个电源线是直流电的话,它就是一直马,就是啊一直马。

但是精湛这个东西电流啊进来之后,它会以一个非常规律的哒哒哒哒哒哒的方式向后铲铲铲出,就是啊后边啊能理解什么意思吧,别着急,我我我我肯定会给你讲ni o。

但是前面这波知识它是支撑你ni o它到底为什么出现的性能,前面那个那版的b l o性能损耗在哪,所以这个一定一定要好好听,能理解吧,那么这个震荡的这个频率一秒钟,比如1000次或者是1万次啊。

1000次或者1万次,每震荡一次,这个精湛啊,他就会给cpu产生一个时钟的中断,每震荡一次cpu什么叫中断,比如这颗cpu在忙着这个进程读取他的指令,说拿过这条干活,拿过来干活,忙得不亦乐乎,正忙着呢。

然后1/1000秒就是一,比如说1ms,当他震了一下,那就掉了cpu的一个这个真假电压就过去了,那这个cpu会做一件什么事情,通俗来说,通俗来说别别别比较了一个细致了,因为咱们从表面上来讲。

这个东西这个cpu就不执行,本来要读它相处指令就不读了,然后这时候开始把cpu里边这个程序的寄存器里的值动了,然后写回内存,它的内存区域里把它的缓存清空,然后这时候中段一般都会有一个。

它有一个中断向量表,中段有中断号以及中段的对应的这个中断号,对应的回调程序就是中断产生,我干啥事儿,能理解什么意思啊,就中断程度之后我要干什么事,你不能光让我中断了,让我打断,我不去干这个事儿。

但是你得告诉我下一步我要做什么,中段的那个call back回调函数是由内核来启动的时候注册的啊,注册的注册的时候,比如说在通俗来说是这个时钟中断产生之后,内核比如说掉了一个方法。

这个方法叫做进程调度啊,掉了一个进程调度,那这个时候其实中断了这个程序的执行,并让cpu开始执行内核里的程序的调度,程序调度的时候,内核里边根据他的队列来说,刚才执行这个,那下一个可以执行他了。

那这个时候注意听,cpu会把这个程序的相应的曾经的给他保护的那个寄存器的东西,给它拉取回来,放到cpu的缓存里,然后开始疯狂到独一条直线下,读一条直行线,但是到下一秒光刀在下一个这个这个震荡的时候。

八又一阵是不是就开始把它恢复回去,就是保护现场,然后呢再去根据回调调用内核里边该执行的这个回调的方法,能力吧,然后再根据回调方法里边的基层调度选择下一个程序再恢复现场,因为你曾经保护过他的现场。

以上这个根据十分中段可以切换的程序执行,但是程序的切换过程会牵扯到没错上下文或者是保护现场,恢复现场内存和cp之间的一个数据的,考不来考不去这么一个过程,这个能听懂同学来刷分一好吧。

我一层层给你铺垫一些曾经可能比较比较模糊的知识,咱们就给它顺顺出来了,但是也停留在一个这个理论上,就尽量画图给你简单描述一下,那时钟中断程序可以切断了,可以切换了,这个能理解的话。

它里边有一个保护现场恢复现场的一个一个一个性能损耗,你只需要在这放大一下,如果假设猜测一下,如果我进城是1万个进程,注意听啊,如果你是1万个进程,如果是在表面上看,我这些进程都执行的很快啊。

都都都都一直在活动的话,其实一秒钟之内这个精湛的数量是不是要高一些,然后呢让每个程序是不是都要轮询的执行一下,对不对,那随着你程序越多,其实保护现场恢复现场穿插在两个竞争之间的这个事儿。

损耗最后次数会变多,所以程序越多,是不是单位时间内cpu浪费在内核调度上的时间会变多,而在程序内部执行的时间变短,这个最终结论,任何同学来刷波一这个理论结论要记住了。

因为后边讲b l o到n o演变的时候,是用到这个这个这个理论信息,就是他啊,那除了他之外,其实还有因为后面我们的程序啊,你在使用网络编程的时候都会掉内核的系统调用,那调系统调用的时候用到中断了。

那么这个中段叫什么中断,一般管它叫软中断或者叫陷阱,说白了其实有一点只有一点概念,同学都知道这个软中断或陷阱的话,它叫做这个int,八零,那这里面注意了这个int是什么意思。

就是中断那个单词的前三个字母,它是什么,它是cpu里的一个指令,所以说只能积累的一个指令,那么x80 是什么意思,这是一个号码,是一个号码,这个号码就在中断向量表里边,它一共有255个号码,88 零。

这是一个号码,那一旦注意听啊,现在不是时间,时钟路段,是我现在cpu就在一个时间片里,就在执行你的一个程序呢,但是你这个程序啊就想调一下内核里边的一个方法,这个方法最终是要向网卡读写读写数据。

你程序是不能直接访问网卡的,那么这里边一定会有一个叫做系统调用的过程,那系统调用的时候又受保护模式,你还不能直接访问它那个函数,就是这里面绝对不能产生函数调用,一定是系统调用,这注意注意措辞啊。

函数调用系统用这两个绝对不一样的这个概念词汇,那么当产生性调用而不是函数调用的时候,这时候其实你写的好像是掉了一个内核的一个方法,但是在编译器编译的时候,它会把那个调类似于函数量那个方式。

就是一个函数名调用改成int 80,并在前面植入内核里边那个函数的名字放到这个寄存器里,能理解什么意思吧,嗯那这时候其实当cpu一读到里边,你读到程序里边编写给你嵌入的int x80 的时候。

那这时候我说了,这个int其实就是中段的首字母都会产生一个中断向量啊,八零找8080是什么,其实就是内核曾经治了这个i c这么一个回调的入口,那这样的话其实会有一个从这儿到这儿的一个态的切换。

就是中断这个指令会没错,s一身份高会把你cpu曾经你这个程序本来我就在执行你这个程序,但是我却读到了你要调cpu里面的一个int一个指令,这个指令只要我一掉到,我就开始保护现场。

把你这个城区公园存到内存里,然后开始调内核,然后根据你曾经传的参数,我要调系统调用的具体哪个函数,那这时候其实只有一个保护用户,带程序的保护现场和恢复内核的。

就是掉进了这个这个这个这个引用内核里边那个pp,这个是那个地址来加载到内存,这个这个cpu里继续执行,执行完之后再保护现场,让他恢复你程序把防御值带带回,这个就是由程序在使用内核的系统调用的时候。

也会像刚才这个时钟多段产生一样,有这个进行切换和损耗的事情,能听懂同学来说。

系列 2:P57:0.2 JDK中的NIO是什么 - Java视频学堂 - BV1Hy4y1t7Bo

你看整个这个这个过程叫做用户才能看它的切换也非常损耗,记住它就是当程序就最终一句话,当程序使用了内核的系统调用的时候,就会牵扯到一个中断,就是牵扯到程序会调cpu的一个指令集里边的一个指令。

这个指令就会发生,cpu把你这个程序的所有寄存器的值写回内存保护现场,并根据你这个指令后边这个中中的限量号,以前面那个参数来调内核里边相应的东西加载到cpu的计算器里。

这样的话肯定会一个一个用餐那个i一个切换的过程,这个也记住,现在记住两个了,一个程序多切换cpu会浪费它,不能只有你程序的指令,他要忙来忙去,然后一个就是调中断的时候啊。

调这个这个这个信用调用的时候会有一个切换,本来我如果在里面代码一直线下执行的话,其实挺快的,但这却玩命的一个切换内存的那个保护来保护去的过程,对不对啊,这样呢会有一个损耗,那么除了有中断。

这个软中断系统调用,除了时钟段,还有一个东西就是io中断,什么叫i o中断,比如现在我的鼠标在这晃晃晃,我的鼠标在我手上挪动,这个指针为什么在屏幕上移动,能理解我想表达什么意思吧。

就是还有一个i o中断,那么你的鼠标晃动的时候,其实鼠标会向我们的计算机发送一些信号,就是发送类似于这个xy坐标,就是向左移动多少向向右移动的话,那这个发送来的数据,但是你要明白,我cpu只有一颗。

我这个cpu正在执行这个程序呢,那这时候你鼠标发的发送来的东西的话,那我接受不接受你这个这个信息我怎么接收的,其实也走的是中断,那是鼠标会有中断,键盘会中断,硬盘网卡都会产生相应的中断。

这个中段就会打断cpu,你别追他了,先快速接收一下我这个数,然后呢那边如果用这个指针的这个这个绘制的话,有一些回调的里边哪需要刷新,刷新这个鼠标的这个坐标或者网卡的数据要导到哪去,这个回调就会掉下去。

就中断一一般会对应一个回调,但是中段一般都会牵扯到一个切割切换的过程,以上所有剧组的一个通俗讲解的知识,听个响就可以了,好吧,能接受我同学来说,背一,我为什么讲他注意我讲课前戏的确很重,铺垫很重。

到后边儿啊,希望给你达到的一种一种是醍醐灌顶的那种感觉,你说后边哇塞豁然开朗好,那么以上收我们开始讲,网络通信,网络通信io的演变过程。

第一个,那么在点网络通讯io的时候,我们先来演示一个大家应该知道的,应该知道的一些基础知识,比如说bl或者是我们用java java能够写出来的代码,在这里面。

比如我准备一个test socket这么一个java程序,我直接啊我先介绍一下吧,我在这个屏幕是一个什么屏幕啊,因为有有些我们用过,我现在这个黑乎乎的命令行,只在那边敲命令。

这是我们我用了一个插上这么一个连接工具,连到了一个linux操作系统。

啊这是一个连到一个linux操作系统,我的java代码不是跑在windows上,我是跑到了linux上,因为为为什么,因为现在其实你像nike也好等等很多的技术,我们的服务微服也要分布式也好。

他们是倾向于走linux这个服务器的妥协的比较多,像nike这个里边直接因为另另外内核的特征,它就直接屏蔽了a i所协到这个多路复用器e破了,对不对,那么在linux环境当中。

我们先看一下这个jav代码回车,这个代码按理说在座的你们都应该能够读懂这套代码,这个代码还是相对比较版,比比较老的一个版本。

代码为什么你看上面倒的包都是java io java net socket加上net socket,在这里你可以看出还没有延伸到java的ni,注意听是java的nl那个那个层级。

那么这个代码是什么意思。

我要写一个服务端的程序,就类似于写一个top k也好。

写一个什么,你你你能听懂我们服务端的程序,这个服务端的程序啊,怎么去写的,注意上来new啊,我们先new对象用谁,new一个server socket。

这是server端的服务端的一个server socket,然后我绑定了一个端口号,8090,看过预习资料的都应该知道,在tcp通信的时候,服务端是要起一个监听端口的。

那我这起的就是8090得到了一个所server的一个对象的一个抽象,那我用完了事之后,我就系统打印打印了一句话,第一步new socket 8090成功了,打印完之后,注意看下边进入了一个死循环啊。

这是一个死循环,在死循环做一件什么事情,你要server的目的是什么,注意听你要启动一个server的目的是什么,目的是别人要去和你建立连接,和你通信,对不对,所以在死循环里边我会调server。

accept,接收吸收水,得到的是一个socket,前面server是new server socket,但是别人跟你建立连接之后,那个对象那个socket就得到了一个客户端。

client得到可爱的之后让我打印哎,客户端谁谁谁把他的多个号打一下,他已经他就已经建立连接了,已经进来了,进来之后关键看下面这句话,new 100000的起一个线程,我在这儿为什么要起一个线程。

首先在这直接告诉你,结果第一个excel会阻塞,因为别人不连,你就没有返回值,会一直在那阻塞着,它会阻塞,但是如果他从阻塞变成返回,得到client之后,你要做一件什么事,情,肯定想去读取它的数据。

但是注意听读取通过网络读取用户发来的数据的时候,比如说这里面的ss就是我们常见的那个plan,那么传进来之后啊,这个这个这个s就就是客户端那个这个对象的话,那我肯定要读读取它的输入流,得到输入流之后。

然后并打印用户发了什么东西,那用户可能不发东西,所以读取的话也有可能变成什么呀,阻塞状态,能听同学来刷波音,就是其实这里面有两个阻塞,这个代码我不想消耗太多时间,大部分应该都都能懂。

下面接收用户端连接它是阻塞的,然后接收完了之后,代码线性往下走,我得抛出一个线程去,为什么,如果不抛出线程,下边这行代码,如果在当前线程一执行它,它就阻塞了,这哥们儿10年不发数据,你在这组了10年。

但是别人如果再过连接的话,代码回不到上面这个循环的开始,就不能接收别人对吧,所以我要把客户端读取的事抛到另外一个县里面去,好吧,刚刚有人说加群加不进来的啊。

我先简单放一个二维码,就是刚才刚进来的小伙伴,现在人数比较多,如果一会儿想赢取我这节课的资料等等,你就去扫一下这个二维码就可以了,我停个这个十秒钟,20秒钟,大家赶紧扫一下这个二维码。

或者你手机直接啪这个截屏,然后用微信扫一扫,然后从本地照片导入就可以,以后一会儿我课后的资料都是在群里面去设计下发给你们,如果你之前加过的话,就不用再加了,抽奖二维码,还有还有还有你看在这儿看到了吧。

一会我给你展示,咱们先学习,坚持不住的小伙伴都退了,退了之后,剩下的人我们再来抽的话,中奖率会高一点,new线程是什么作用啊,new线程是什么作用,就是如果你不new一个线程等于接收的方法。

调用和读取的这种调用都在同一个县城里,两个都是阻塞第二部的读取会把这个线程一直堵,一直堵塞死,那前面那个代码接收就执行不到。

啊这个改了一会儿,一会儿再扫不到,我再待会我再抽烟,给你给你给你给你发,为了不断片,我再介绍一遍,就是你看这个代码在一个主线程里边。

它代码向下线性执行,这个循环也是我先线性执行完了之后才能回到这个循环的开始上面。

accept接收,如果返回了得到客户端,如果不用线程,你可以在当前这个主线程里边先在这往下走,直接跳过,就没有线程啊,直接去可以通过这个客户端读取读东西,但是读的时候人家不发,你在这一直阻塞死。

这时候服务端再来一个人进行代码,执行不到就不能接收,对吧啊,ok那么其实我演示一下代码,你就知道怎回事了,我们通过演示,其实有时候a p i光看的话没有没有这个代表性,那么演示的时候呢。

我给大家教大家一个方法,听我专业课都知道,就是很多东西啊,我喜欢用一个东西叫streets去追踪一下,先记我下面要干什么事情,介绍一个小指令,对你们未来学习各种io模型,io框架极其有帮助。

和任何的网络通信都有帮助,这个指令叫做这个直叫这个street是谁的指令,不是java的,它是我们linux操作系统中它的一个一个指令,这个指令可以起到一个什么效果。

一会儿后边我会把我的java程序跑起来,跑起来之后他会追踪我java程序有多少个线程,每一个县城对我的内核产生了哪些系统调用,有哪些损耗,都会给你淋漓尽致的给你记录下来。

这也是我们学习程序到底在计算机是如何运行的,非常有用的一个一个指令,但是在运行之前,我们先来看一眼,这是一个java,如果想让它执行,我得先编辑一下,编译的时候注意看啊,我用谁去编译。

在我usr java有一个,g two sg一点四这个版本我用的1。4,这个版本下面有一个b,唉呀呀呀呀呀呀呀呀呀,吓死我了,差点生鲜了,并不落下,有一个java c的程序。

然后接我们的test socket java回车,没有报错,就直接编译出了一个csolar declass,我为什么要用1。4的给你编译,我后边会用1。8的再给你编译一下,这两者编译完的结果。

它在i o上是有一个变化的,好吧,你先记住这个这个点,那么下面我们来执行,用stress追踪追踪的时候,后面参数怎么写啊,ff两个f的话就是fog fog追踪他的这个未来那个程序的所有的线程。

然后杠o是out输出输出什么呢,以alt这三个字母开头的每一个线程点他自个线程id的独立日志文件,那么这是前边streets命令的两个参数,那后边第三个参数是什么,第三个参数就是你要执行的那个目标程序。

目标程序是我usr并线的java,不是usr,这to sk扎了g two i s k,然后b下了一个java程序,这是一个二进制可执行的一个java程序,就是g a m它启动什么。

启动我们test的socket,这一行只能有两部分,一个stress,一个后边jva的启动程序,这个能看同学来刷波一炸了,走了,哎,我用另外一个窗口啊,我有两个窗口都连着同一台服务器。

这边我是在这个目录下要去启动一个什么东西,这边我们先去看见这个目录来test socket,这个目录下应有的文件都是一些java java java点卡,什么点class。

就刚才这些文件先记住这个文件的这个这个这个目录的样子,当我这个指令一一想起起了之后,压制一回车,是不是炸丨药程序跑起来了,是不是也按照我那个刚才代码提示。

第一步new soo socket 8090启动了,但是你看下边在第二步是不是没有打印,证明在这部里边可能有一个阻塞发生了,而且同时啊对这种思路走,同时看另外一个标签页里边,刚才看只有这些文件。

只有这些文件,但是你刷新之后,你会发现咦多了一些文件,这些文件是什么,是不是就是out的开头以一个数值结尾,数一数有几个,12345678,有八个县城有八个形,这个八记住了,因为有了一个可能连接之后。

它会new出一个线程来,就变成九了,那这个时候你就代表着一个java程序刚启动的时候,它就是一个多线程的了,你不用线程,它自身就是多线程的,因为有些线程是要负责gc回收啊。

有一些是需要外界的这个这个soc连过来之后,是要建立这个完了这个这个这个这个这个这个监控等等的,那这里面我先告诉你主线程是谁,主线程是第一个alt 8211,这个县城这个能听懂。

原来说v一就是java本身就是多线程的,你又线程是你又造了一批线程,对不对,有了这个认知之后,我们就来思考程序到底是怎么执行的,什么叫做阻塞就能看出来了,用v打开out 811这个文件。

这就是我们java程序在运行时和内核的所有交互的整个过程,交互的整个过程,我们先来文件就行,第一行,第二行,这是记录的所有的每一行,每一行,这每一行是什么,前面都是一个系统调用的名字,内核的一个性调用。

后边是相应的传递的参数,然后等到后边一般都是返回值,我们先看这个文件的最后一行,对啊,我们先看整个文件的最后一行就是2555行,你会发现诶这掉了一个accept,然后括号一个数字三逗号后边他没有写东西。

然后根据前边这诶这带之后程序没有往下走,注意这个就叫阻塞,就是一个函数被调用了,或者一个性格温被调用了,但是他还没有给你来得及返回,这个方法在这死住了,这个叫做阻塞,能听出来稍微一这except是谁。

其实就是我们在server上面点的那个except,在等待着客户端的连接对吧,这个非常好理解,可能有人说这是什么东西,这是什么语言啊,注意听啊,这个跟语言关系不大。

这里面出现的每一行是你java写程序交给了jvm,jvm最终解是执行我们的代码之后,最终这边是一个虚拟的,它最终要调到我们操作系统物理的内核身上的一些系统调用,这些都是内核提供的系统调用,好吧,那好了。

那么就基于最后一行,我们来开始往前倒,网络通信到底是一个怎样在内核交互的过程中完成的,首先在excel里边有一个括号,然后它里边传了一个三,首先先弄明白这个三是谁啊,先弄这个三是谁,这三往上倒。

其实达到这个2543行就达到这一行,看到这有一个调用了sp的,然后括号传了一些参数,然后注意它的返回值是什么,返回了一个三,先跟着我的速度啊,我帮你把这个捋完了,最终和我们扎个代码关联起来。

得到了一个数字三,这个三有一个学术名词叫做文件描述符,file descriptor,然后这个三得到之后,注意看下边我们先通过单词的语音自己去理解啊,你看上面salt得到一个三,这个三倍哪去用了。

到2545行的时候,弹的绑定,把三绑定到了8090这个端口上,然后绑定完之后,下边listen开始监听三间接,其实在监听8090这个端口有没有这个操作,有没有数据包过来,他的目标东口号刚好是8090。

那就分配给我就可以了,这就是socket bb和listen监听,有了之后,那其实说白了三是谁,三就是server socket,听我同学来刷波666,对吧,然后下边accept 3的时候。

其实就是在some这个social socket上,我要接收一个客户端,只不过现在是服务钢企,还没有客户端连进来,对不对,那整体答案先先先看到这儿,我再让你看到一些东西,再让你看到一些东西啊,咱们一步。

因为程序正好在那阻塞了,那么这个从阻塞到不堵塞的过程中怎么演变的,我正好把所有的细节让你进来看一下,gps,先记住一个东西,tesocket就是我前面跑的一个程序,这个这个java这跑起来之后。

他的这个呃这个进程的id号是8211,然后先看一个命令叫做nike st,看我预习资料pcb的时候都都知道这么一个命令,然后杠n a t p走在这里面,你会看到有一行啊,这行就是8211。

是java程序,它的状态就是listen,然后这个我也解释过,这叫做一个socket,它是ip port,ip port一个四元组,对不对,那么在这个四元组里边是local本,如果来了就听啊。

如果这台计算机收了一个数据包,本机的任何地址在数据包里出现了都可以写,多号是8090的,那么就可以交给这个程序,就是这个listen状态的,就是他的目标啊,目标可以是任何地址,任何端口号。

但是只要你的数据包的目标ip地址是我本机的,且端口号是8090,你来自于任何地区,任何段位号都可以,那我就会把这个数据包交给821,交给java java交过去之后。

其实就会走这个except建立连接了,这就是从tcp到我socket连接这个过程当中,你要想明白的一件事情就是listen,就是搜单,为什么一个listen有一个监听。

好吧这段能听懂的来说说一你看现在关于821的,你只你只看到了这么一个条目,因为还没有任何的建立连接,对不对,哎那么说我们继续走啊,继续走,这个文件刚才是vi帮你打开的啊,我们把它关掉。

接着另外一个小命令叫做tell杠f out。8211,那么tell这个指令可以起到一个什么效果,杠f是这个阻塞,一直显示alt。821bp回车,它默认会把这个文件的末尾的时候给你打印一下。

你会看到看到listen了,然后看到accept accept在这里阻塞了,都不动了,对不对,然后未来这个文件只要多一些什么东西写进去了,他就给你帮你打印出来等等。

等于实时监控这个这个这个文件里面的东西,那我要做一件什么事情,我让你看到当一个客户端连进来之后,我的java这个阻塞有阻塞造成变成非阻塞,它是怎么一个过程产生的,和我们客户端连接是不是有别人的关系。

对吧,这个课这样的讲解方式,是不是不是你根本就没有听说过,直接追到程序是如何运行的,在这左侧边看a a a a asap,三三十九是什么,server socket,就是那个listen。

例子里边到底有没有人来呢,这边我用一个小程序来模拟一下nc,就是net connection或者net cat去这个你就想成是一个网络通信的一个客户端,它能帮你完成tcp的三次握手,和别人去连起来。

然后连谁连local house,连本机,任何本机本,只要你给出本机的一端是这个地d就可以了,动口号是什么,动画是你前面服务的8090,后面给出动口号,用空格8090,注意听,那么这时候走三次握手。

就会连我们的服务,连服务之后三次我都走完之后,那么最终就会把解析完的数据包,然后给出一个连接的事件,就会走到那个三往下就会走,那这时候我回车看,加t回车,你看两边都有叹号了,两边都叹号了。

现在看我前面诶,star一个客户端端口号,记住了59033,说的是我net connection或者nc这个程序,他申请了一个作为客户端,申请了一个随机动号,连到了我这个服务端的8090,是不是呢。

待会给你演示,关键看刚才追踪的日志,在追踪日的时候,刚才是不是在这个三,是不是在这就阻塞住了,但是无论你等多久,等1年等10年,只要别人一连进来,这个方法就会有返回值,是不是等号后面返回了一个五。

这个五也是一个数字的一个文件描述符,三如果能代表server的话,这个五其实代表谁,就代表了我们新连接的这个客户端,就是accept由阻塞变成哎有返回值,六个过程就是由别人建立连接产生的。

比如说accept会阻塞,现在能听懂,原来刷波666,对吧,而且你在这个返回的时候,你也知道啊,给你传递的从系统获得的就是你看对方的断口号的时候,59033对不对,那么得到他之后啊,注意得到它之后。

这是第一步得到它,我们来看一眼看一个什么东西,先看一下网络状态,刚才你看到821这个那就是一个java,然后这个listen对不对,然后再往再再来执行一下那个这个杠ntp走。

你没看到有一个8211java avon,然后8090后,但是再往下看,这是不是还有一个8211java,然后往前走,这个状态是连接状态,注意看这个socket 4元组是不是本地的。

12700是一个ip地址,目标正口号是这个8090,然后来自于谁来自于本地ip地址,且端号是nc那个这就是nc那个进程59033,因为你看到59033是本地端口号的时候,对应的就是我们那个nc程序。

这就是ip port ip port的一个四元组,就搁这jav,这是不是多了一个81,是不是多了一个连接状态,这个这块能看懂的同学来说,六,对吧,程序由开始只有一个三,然后得了一个客户端。

59043多少号,然后做了一个五,重点来了重点来了,回忆一下,在我java程序里边,我在主线程里边accept,因为能听懂什么意思,我在主线程里面接收客户端,当得到客端之后,回忆有代码。

下一步要做一件什么事,我是不是得启动一个线程,在这个线程里去读这个五,对不对,五就是如果扣分的话,我是要先启动一个线程的,那么它是如何新启动一个线程的,往下走往下走,重点就来了,他是如何启动一个线程的。

你看在主线里边又accept,等于他一个学生又回来了,往上走,找到一个系统能用的克隆,啊它因为东西比较多啊,一共得了三行克隆这个内核的系统调用就会开辟一个新的线程,这个新的线程是82818281。

记住了,为什么是8211,一会儿给你讲,给你解释,首先你要先明白了,在java的现成的概念,注意听啊,这个很重要,在java里现成的概念,什么是现成,这是不是面试官常问常问的一个问题。

java当中什么是线程,java的线程是什么东西,现在如何回答,注意听java的线程其实就是通过调用内核的系统调用,然后其实得到了一个在操作系统里边的一个什么呀,轻量级的一个进程,轻量级的一个进程。

因为它有一个线程id,或者进来那个8281,但是你刚才说的不是,这显示是8211,不是8281吗,其实切换机线程,切换机线程他们会有自己的id,但是它们同属于一个最开始的那个进程的那个id。

就是一个线程组,会以他为表示好吧,那先跟我的思路走就可以了,那不管怎么样。

是不是克隆可以得到一个新的限制,那么在当前主方法里没有找到独舞吗。

是不是没有找到主五,跟着我的思路走啊,ctrl c结束,它还记着这个目录,开始让你数过java,它启动的时候,它有多少个线程,是不是123456788个,对不对,那现在看是不是多了一个2。8281。

我们的stress也给追踪到了,这个命令,不,厉害不厉害,对不对,你想想知道,如果这是主线程,主线程里边它就是在while循环,就是在accept,每得到一个客户端就抛出一个线程。

现在我刚刚有一个客户端就抛出了一个,我是不是再连一个一会儿抛出去一个写在这个县城里边,是不是要发生一个读写阻塞的一件事情,所以我们来看vi out。8281,能跟上我思路的同学来说不一。

来看看这个文件进来之后。

其实你直接跑自行了,这个这个这个县城掉的东西不多。

它就到37行,30行,你发现只要后边没有等号返回,这个方法等于就被阻塞了,他掉了一个内核的receive,然后从谁去receive接收,重点来了,是在另外一个性能里边去读五,这个五哪来的。

是不是在主线程里边,主机能里面创建那个五这个50帧这个客户端,所以在主线程里边accept,在新的线程里去读自己那个客户端的文件名符,到这一步能听出来稍微666,那把这个理论我们再去给他扩展一下。

记住现在是九个,最后是8281。

如果我再开一个客户端,是不是还会有新开另外一个线程在克隆出一个来,就是你要想明白啊,整个机整个你的java程序你是怎么运行起来的,稍等有点卡等等,这个这个界面弹过来,在nc连local host。

然后是8090,刚才是连了一个客户端,所以初春春多了一个县城,这边注意看压机,又一个客户端是59034进来了,然后你再来数这个目录,刚才是8281,那多一个客户端就会多一个线程,8304这个线性记录了。

现在是每多一个连接就多一个线程,每多一个连接就多一个线程,如果有1万个连接,就会有1万个线程,听懂了吧,哎那这个时候其实8304刚才把包里边要读58304,不要读谁打开out点,8304到最后一行。

receive 66是什么,就是另外的一个新的客户端连接,以上都能听懂,同学来刷波六,那有人说了,你一直在我们看这个out,其实你表面说的这个逻辑能跟上,其实大家都能跟上,也能听懂,但是就是什么呀。

你再能听懂,但是我不知道那些方法它是个啥东西,为什么管他叫系统调用,excel到底是啥,为什么socket band listen,然后还得accept,这个不懂对不对,这个不懂哎,似懂非懂。

那么你得学,我说你得学明白了,那么怎么去学明白了,无师自通,你根本不需要我在你的linux当中,我刚才说了,那个文件里边所有的开头的一个指令,它都叫做系统调用,比如i'm mad啊。

比如这个执行啊等等的,或者read读取它都叫做系统调用,那这些怎么去学,回忆先告诉你你的性能跟队友menu帮助程序后边接二二类的帮助程序,二类帮同学看什么,看就是系统调用,把你在这个文件里看到的。

前面这个你想学的这个信标的名字写在这个后边,比如刚才我们看到socket回车是吧。

打开了二类的系统调用socket,还有一个解释文档。

这时候你会发现我去系统能用,长得好像我们java的语法格式,其实这是类c的啊,这是c的,java是类似这种语法格式啊,有返回值,然后int类型有函数名,然后有括号有参数,然后分号结尾,那么别的先不看。

刚才是不是返回是返了一个三返回这个五返回个六,对不对,那返回的是什么,你直接往后倒倒,它的返回值,是往后倒啊,达到了一个return value,这个章节没告诉你了,如果执行成功。

一个file descriptor,一个文件描述符,就是我们一个数值的35678这样的一个数值给你返回。

记住就可以了。

系列 2:P58:0.3 什么是selectorbytebufferchan - Java视频学堂 - BV1Hy4y1t7Bo

里面有符,那返回这个描述符,它要干什么干什么,用n q对出再来二,然后后面接第二步是一个绑定绑定,其实好的,也就是绑定我们那个逗号啊,然后还有一个是listen lion的话。

其实就是开启今天状态能理吧,就是listen是要开启一个监听了,这些都好理解嗯,我们看绑定吧,因为绑定里边会有一个小例子,半个绑定就是要绑定我们一个多小号了,为什么看它它其实里边有一个example。

好吧,这还有一个用力,注意听我下面的描述,抛开你的扎了,如果on linux在linux操作系统上运行,无论你的java index redis,只要是个程序相反。

网络基本上离不开这个example里边非常重要的一个顺序,你能听懂表达什么意思吧,就是你学歌要学到,这就把我刚才给你演的时候,在这个代码中都能找到,首先看这个代码是什么代码,这是一个c语言的。

因为它下面是井号,intro导入炸灯,就是import导什么什么类,往下走啊,往下走,重点呢我们挑几个东西,哎你看它也有主方法,再来一个,如果注意听啊,无论是re,无论nbx,无论是java。

如果想使用网络通信,它必须要调哪些东西才能网络通信往下走,要和内核交互的时候,注意看是不是他在这掉了一个socket,返回稍微的刚才也看了,它是有返回值,是不是返回了一个变量,一个文件描述符。

有了这个变量文件标书之后,注意有新调了socket,他下一步一定调查,根据刚才咱们的追踪,是不是下一步一定会掉半的,绑定绑定我上面这个sf d到某一个动号上,调完绑定之后,是不是要调listen。

把它开启监听,能跟着我的节奏吧啊我不知道你们为什么要聊没用的这个课程,你在别的根本听不到,对不对,就这么一次学习的机会,你为什么还要去聊别的啊,先跟着,起码你要先跟着,跟不上。

你要先听到我给你画图就理解了,起码说你再跟不上这三个东西,现在有没有盖,就是你刚才看我给你演示java的系统不用了,然后我给你演示c如果去开发的基于linux的话,它里边必然也这么写。

你就先记住就仨东西,socket得到一个文件标符,然后肯定我要绑定,绑定之后,我肯定要离心监听,今年之后,剩下的就开始读写了,对不对。

那么其实用过画图,这是好理解的,一定要记住了,根据我前面所有铺垫的知识,下面我讲的东西应该能接受,首先计算机里边有application一个程序,然后你知道除了application还有pl内核。

这两个一个计算机组成里边肯定有程序有内核,而且你现在应该知道程序是必然要调一些系统的这个内核的性调用,才能完成程序的一些逻辑的执行对吧,那么这个时候如果你的application是一个server的话。

是一个服务器,这个服务器它是如何坚持起监听,如何接收客户端如何运行的,也就是我刚才的java程序是如何执行起来的,你们有什么意思吗,那这时候我们来回忆一下,第一个,如果你是一个server,要先几间听。

必然先调内核的三个系统调用,也就是先调了salted,调完socket之后,它会给你返回一个,比如像刚才反了一个三,这是一个文件描述符,这个三是谁,就是server socket,然后得到它之后。

然后还要绑定蛋子,绑定我们3~8090这个端口上,然后并listen开启监听,把三开启一个监听,那么注意听,无论是index redis还是任何的third one,这三步是必须这么执行。

无论在任何的io模型下,dnl多路复用器,第三步是不能省略的,主要是服务端,这三步调用必然产生之后再说别的事儿能听出来刷刷一,对吧,这三步是必掉的,要起立要起监听,对不对,那这三步完成之后。

那么回忆我java当中,其实这三部就是谁,就是new server s8090 ,这三步就搞定了,搞定之后,那么你这是服务端,你要接受客户端,而且你要接受很多客户端对应的连接,因为你要对很多人提供服务。

对不对,那这时候下一步要做做一件什么事情,刚才我说了,其实他下一步在lec完了之后,你可以见到的系统交流,旅游accept接收接收。

在这块儿你也可以自主学习,比如退出这个用menu 2类的a c c e p t接收,接收的时候要给出刚才那个soo socket,那个i那个文件描述符传递了之后,它的返回值是什么,主要战斗你看到为止。

反正就是如果成功,就是别人就是这个方返回了,他会给你返回一个什么呀,文件描述符,一个整数型的一个文件描述符,比如说他也会返回文件描符。

这个文件描述符是谁,就是我们新连接的客户端,对不对,比如像刚才如果有注意听,首先他第一个会阻塞,刚才看到的就是他sab 3,然后括号它就停住了,三逗号它就停住了,不动了,这这这叫阻塞状态。

但是如果他一旦有反有等号给你返回来,比如刚才反了一个五,这就是由阻塞到有返回值的一个状态,换言之,accept会阻塞,这点很重要,这个性能标准会阻塞对吧,到这一步能听懂,原来是不一excel干什么的啊。

他是有阻塞的行政特特征啊,那么当它返回一个五时候,这个五就是一个q端连接,我说了,你可以在当前线程当中是不是还有一个性能叫做receive,receive是不是独舞,但是receive独舞。

刚才是从另外一个线程看的,我现在不不把他死在另外一个线程,如果就是在我单身程序当中,如果掉了reserve的话,这个reserve是不是会在这一直阻塞,因为别人可能没有给你发送任何的数据。

那么在这如果一直阻塞,即便你写了一个死循环,注意看,即便你写了一个死循环在这儿,如果一旦一直阻塞,还回得来吗,是不是回不来,那这时候如果第二个第三个第四个人去连接你这台服务器的话。

抱歉他是不是前面这行接收就执行不到了,对吧,这个能听懂的,是不是一,那怎么解决这个问题,是不是可以通过克隆的方式,也就是说程序当中掉克隆,抛出去一个县城,一个县城。

在这个县城里边儿把这个这个阻塞会单去干扰你主线的一个事儿,给它挪出去,您啊在这儿给我阻塞,是不是在这组算,那么这个线程在这堵塞这个县城,是不是没有这个刚才那个举错了,是不是外国学生大帝又回来。

又开始堵塞,接收别人别人了,那这就是主线程接收,每得到一个客户端,丢到一个线程里去,那么这时候刚才给你解释了,给你演示两个线程,两个连接就是两个线程,如果1万个连接就会有1万个线程。

这就是曾经最古老的代码模型,就是基于bo的美县城,美线程对应美连接,现在这个概念接受,我同学来刷波六,对不对,我说了,我前面会给你铺垫铺垫铺垫铺垫最终就是看不懂,但是最终画图就能接受这个东西。

而且这一定要记住了,前面无论你server怎么设计的什么im模型,前面b调b执行,好当这个能get到之后啊,那其实你要先去思考一个问题,这个模型优势是什么,好优势,他能他能他能解决什么问题。

他有什么优势,简单除了简单,它要解决一个根本问题,它要解决一个根本问题,什么什么是根本问题啊,可以接收很多的连接,他是不是可以接收很多的连接,对不对,这是它的优势,但是它的劣势和问题是啥。

就是他是否存在问题,他的问题是弊端是什么,因为你找到了b端才能知道它有弊端吗,那技术如何改变就出现下一个技术也就出现了n他的问题,先说问题是啥,根据我上面给你铺垫,你现在去看我上面的铺垫是有有需求的。

你看刚才说了,如果进程特别多或者线程特别多的时候,达到1万的时候,其实你cpu在单位时间内净损耗在他们切换上了,就中间穿插这个时间,每个secret执行的时间就不多了,对不对啊。

那这个cpu的整个会被浪费了,所以第一个它有两个,第一个是线程内存浪费,因为你开辟一个线程,这个线程在内存里边会开辟一些数据的这个数数数据啊,还有一些一些这个内存空间的占用,一个浪费内存空间。

第二一个就是什么样啊,这个cpu调度消耗消耗了一些这个cpu时间片,对吧,这是它的一个弊端,那这个问题这个弊端其实其根源是什么,就是你为什么设计成这种用玩命创建线程来接触更多它的实质的根。

最远的问题在于哪,是在于这个单词blocking,也就是主色,因为有两个方法是阻塞的,这两个紫色,一个是accept,一个是receive或者read读取这两个方法,或者两个系统调用会阻塞。

我就不能把都阻塞的这种都有可能阻塞的东西放到一个县城里,那就一个阻塞会干预,另外一个阻塞会干预到让另外一个执行不大,所以这才是根,那也就是说,如果想解决当前bl模型的这个困难。

这个所有的弊端其实只需要一个新的词汇出现就可以了,新的词汇就叫做n locking非阻塞,这是你可能想到的解决方案,从bo给你衍生推导出n是解决bo性能问题的,这个逻辑能跟得上的同学来说不对。

661切的推导都是有目的的,前戏还真的蛮重要,无论在生活中还是生活中,对不对,那但是这时候你要去思考一个问题了,是否阻塞这件事情是程序自己去解决的,还是受制于谁,还是受制于谁,其实是否阻塞的一件事情。

谁能提供解决,就是系统调用的accept和receive,它是不是要堵塞路的问题,那其实受制于内核,也就是只有内核向前发展,内核当给我们提供非阻塞的系统调用的时候,这个问题就被解决了,能对我们来说说一。

现在再来思考,你要不要去学习几组这个知识,因为g组不太了解内核是啥,就算机组成原理,他们工作机制不懂的话,一些技术像刚才这个过程当中很痛苦,你根本学不到底层。

你只能还停留在博客或者一些数据的表面的那种表面公司,这时候你如果特别梦想自己成为所谓的p6 p7 p8 ,这时候其实是说空话,对方可能就是在这关上就过不去了。

那会儿怎么去实现呢,回顾一下信用交那边,比如mu to socke,那这里面我刚才让你看到的返回值后返回一个监听状态的那个三,它会从一个三是监听状态来,但这时候其实它里边还有参数,我们往下走一下参数。

找一下感觉,我还会待会我讲,这个时候还会给你纠正一些问题,在这儿注意看,在操作系统内核的系统调用socket里边有一个参数叫做socket,nblock,就是非阻塞内核。

其实后续版本提供了这样的一个功能,而且除了soc得到这个可以视它为nblocking,你还可以对建立连接用sell counter这个第二类型调用,对它同样就是对建立连接的扣分的连接也设置非阻塞。

对吧也是在试制作,那在这儿注意了,注意听啊,你看到了内核里的,但是在这给你强调,首先提到在在这儿马上进入进入几个环节,要进入i o了,但是要进入n i o的话,注意有两个n啊,注意听有两个n。

一个n一个人是哪个是java当中的new这个l什么意思,是new io,这个n o啊,你看跟跟别人聊天的时候,语音啊,非常好,非常专业,你在跟你的同事,跟你的领导,跟面试官聊天的时候,他一定要说。

你给我解释下n l o一定要加一句话,让他感觉到你很专业,你说咱俩聊java的n l o还是聊操作系统n i o,如果聊java的ni o,那么就说的是nel一个新的一套io体系。

就是nl这个包下有channel通道,有这个bad buffer,然后有select这个多路复用器的选择器,然后另外一个维度是,那他说你跟我聊聊操作系统linux io。

那这时候你要知道他说的是n blocking,就是非阻塞,啊这两个是绝对不同的两个语义,好吧,两个都说下,两个都是这样,那就是我下班要给你讲的东西,好好听,都说一下吧,哎那我知道你啥意思。

get到了get到了,但是你首先要明白。

哎首先说了对这个操作系统里边已经看到了nbing不对。

那个number lock是啥意思,啥意思,什么叫做非堵塞,想不想知道它怎么什么叫做非土特,非主色只是一个名词,对不对,但在系统系统特征上,他是怎么表现出非独特的。

或者我们扎的当中是这个这两个东西到底是啥,你不是等会儿我给你解释一遍吗,来注意看啊。

我用另外一个带你看吧,这个在这看,用这个看比刚才那个linux看的是清楚一点,有这样一段代码啊,要注意注意听啊,有这样的一段代码,这段代码当中说到代码了。

说代码了,这个代码怎么领取,我再多说一句啊,给个十秒钟,新进的小伙伴,如果还没有加这个群的,你扫一下这个二维码,一会儿我的代码和截图都是通过这个群里去发放,好。

满了群里边谁在谁在谁就去发一下新的这个二维码,有人在吗,咱们助教的老师,我听到了外面传来哈哈哈的笑声,别光笑了,再次再次老师就把这个二维码发一下好吧,那回来不耽误时间,我们接着讲。

接着讲,别上就even p有点早啊,很多知识你不学明白了,你不知道为什么面试官就是一定要记住,要学东西有仨词儿,这是我讲课的风格,我是希望你们去学,what,what你真的知道每一个技术它是什么。

它为什么出现,以及如何正确使用它,沃特外号,这三个是你学习东西的啊,一个一个一个方法论,那么进入n o那么什么叫n n l o学明白了,找到b端了,就像刚才bo学明白了,知道我要推到n o。

兄弟们找个弊端,你才知道去推导多路复用器好吧,那么soa的n o是一个什么东西,我们先来看java版本的书写代码,书写方式在这里面注意看啊,刚才这个b l的时候就是什么i o就是net的包。

但是这时候你就看到了哎,这里面是不是ort java。n l5 倍的buff,是不是有channels,里面有soo socket channel,有socket channel。

这个就是所谓的java的new io,这个能看出来上边一这就是所谓的jva new io,那么new i o里边这个线路里边其实最终会包含一个什么队,看下边代码旅游就找到了怎么去做的。

我先看一下这个这个最最重要的地方,比如server socks channel,点open soo soo channel,这是新的i o的那个接口。

比如open之后会得到一个sos socket channel s s,注意看下边是不是s有点半的绑定了一个9090的根号,然后重点来了ssr confish blocking,配置阻塞吗。

这里面有两个值,处阻塞和false不阻塞。

那这对应的就是刚才你看到的内核说的是否。

这一行说的是os的nboption,上边的这几个a p i这一个这个类和方法接口说的是new l新的i o。

刚才一小本说这俩面试官都让你说一说,现在会说的同学来说,小贝略略略。

清楚了吧,非常清楚,对不对,那么继续代码往下走了,重点来了,还是不知道什么叫做非阻塞,对不对,我还没讲完,道路中间啊,那我再说一遍,我再说一遍,就是在开发开发java代码的时候。

就是面向n i o这个词啊,面试官肯定问你nl是啥,你得你得问他,咱们聊渣子呢,还是聊操作系统的,java里面说的是一个nl的包,下边提供了一些新的接口啊。

比如socket channel或者是bad buffer,或者后边有多多附体的selector,这是nl的new io,新的io接口的使用的方式,然后在新的l使用方式的时候。

有open得到了一个sos socket圈等s,然后有b的绑定,然后并listen 9090这块其实跟我们底层调用比较相似,最主要的是唉你还可以ss。confish blocking是否设置阻塞。

fs还是非阻塞,那这个非阻塞其实对应到了操作系统os里内核的nblock,nblock没解释出,根本你别着急,你往下听好吧,这个叫杨三阳,这是不是就到了nblocking了啊,那这个还是不灭。

什么叫做nblock,nblocking啊,但是现在是不是可以区分,起码说是不是可以区分出n l nel和os的nblock,那它具体是个啥东西,往下走,你要往下走,要虚心去学习,往下是什么意思。

默认值是啥,默认值处是阻塞的,看我下面注意看啊,现在我是在当前一个主线成立,而且我通篇代码当中,即便有循环,我再也没有虐过ride,那我下周做了一件啥事,注意在这个循环里边看我做一件事情。

死循环里边我surprise sleep睡了一秒钟,也是这个循环,每一秒钟转一圈,每一秒钟转一圈,每一秒钟转一圈,就是这一行可以看到效果,关键看下一套ss。

就是我上面那个server socket china,第二accept,接受口端,注意如果在阻塞的时候,如果在阻塞的时候,这个方法或者停住不动,反之达不到,但是我上面是不是设置了非阻塞。

这块的非阻塞就是内核的那个非阻塞啊,那他fix之后会会有什么现象,就是这个方法不会阻塞住,只要你掉了,就一定会有返回值,给你返回一个所谓的command的,但是这时候如果别人刚好这个链接。

你就返回看看看看,但是别人如果没见过连接,你返回你能返回啥,所以这时候其实就是要么返回一个none没有,要么就是返回一个具体的客户端,就是在java里面是维纳,在linux底层,就是是否是-1。

或者是某一个客户端具体的那个文件名符,567到这一步,什么是非阻塞,天明同学来刷微一,一会我给你追踪代码演示啊,然后层次了,注意听两个层次。

面试官问到你啥叫做ni o jj里边new i o操作系统nblocking,那什么叫做非阻塞调方法,不停住,绝对给你返回,只不过有正常返回给你返回的客户端,别人来了,或者是返回-1,或者那别人没来。

但是我的方法不会停止不动,这个总结能听懂回答上面的六六,好吧,如果现在还没有学会接受我这个这个这个规则的话,这个这个讲课的这个这个这个这个跟着我的思路走的话,你就慢慢适应了,那么接着往下走。

这刚看到了一个非阻塞,我们说except会阻塞和非阻塞,那么其实后面读取是不是也会组成非阻塞,那么注意往下走,如果你返回客户端,但第一这个客户端还不是说还不是说那个访问空和-1,有了法律真的客户端了。

那那这个客户端你要做一件什么事,情,除了我们可以对leon状态那个sol solid进行一个非阻塞,在上面,这这设置s你还可以对得到的一个高端再继续抢分制,blocking设置非阻塞。

那么对客户端连接是废除,代表什么意思,未来我一旦想去读你的数据的时候,就分两种情况了,你发的数据我就读到了,你没发来,我就返回c1 ,能get到这个点吗,那么整篇非主做我给你解释清楚了。

那我整个代码是什么意思啊,为什么为什么写这么多行,我再给你穿一遍,回到第一行,我准备了一个link list,里边放的是socket challenge cos,连接得到了一个class。

这可能是放什么东西,因为注意听,我是在一个县城里得到了server,开始变成非阻塞,在这个一个线程的死循环里,每寻每一秒钟我尝试接收,这时候有可能接收到了一个有可能没接触到,但是一旦接收到客户端。

我把客户端还设置成非阻塞,并把这个客户端还加到那个link list列表里边,按进去为什么,其实在这一个循环里边分为两个区域,第一个区域是什么呀,接收客户端,第二个区域。

因为你每循环一次可能向链表添了一个客户端,每循环一次添了一个户端,这个页面会有很多客户端,在美循环的时候,既要坐着接收客户端,又要尝试着便利这个class挨个去读取他们的数据,但是这时候读取的时候。

又因为你上面对客户的每一个坐端是指非阻塞,所以这个客户端它的读取行为就不会在这长久阻塞住,要么读到,要么没读到,代码会一直向下走,一直循环,听懂的来说说一,这就是在n i o模型下一个县城。

我可以解决很多很多可能连接我不需要开辟更多的线程了。

我们刚才讨论的是不是就是解决bo线程多消耗的问题,是不是非阻塞就可以一个线程解决这个问题了。

刚才这段话没听懂,我再讲一遍,我再讲一遍,我现在整个java程序当中就只有一个主线程,主线程内部准备了一个link link list,这是一个clipse,这里边为了未来放什么。

就是未来我通过接收的锁可能往里扔,然后我准备了sos socket开始监听,并把它制成非阻塞,然后下面用了个死循环,while循环,while循环里面注意做两件事情,第一件事情接收客户端不会阻塞。

有没有都会有返回,但是继续往下走,无非就是有没有的问题,如果有了,就把这个客户端设置成非阻塞,并添加到克拉斯列表里边,那么第一while循环的前半段都做完了,而且没有阻塞,前半段很快做完之后。

那么来到后半段,外媒外美学校的后半段里边,它都会对这个class这个链表进行一个便利,每拿出一个客户端进行读取客户端发来的数据,但是客户端可能发可能没发过去会堵塞,但是因为刚才给客户端设置非阻塞。

这个方法就一定会掉了,就会有返回,只不过是返回读到了一些东西,还是没有读到等等的,它不会阻塞住代码,就是这块很快的打出,可能变了一遍,然后循环又回到了开头,又开始下一轮的接收尝试,遍历所有客户端。

又开始尝试接收,又开始便利所有客观这一个县城就可以把所有活都干了,就回来收拾666。

哈哈哈哈,对吧很多之前可能你只是读博客啊,线性文字的,这时候其实你要参照很多东西就可以就可以理解这个这个概念,那么其实还是前边注意看啊,你要想着这件事情还是有我们的server啊,还是有我们的内核啊。

只要是服务端。

是不是你看上面这一段的搜索socket。

然后open啊,绑定9090啊,是不是前面这三段无论是在必要的模型还是在n l模型前面,这三段只是server必走的,那么只不过外循环就发生变化了,在while循环之前,你要先对三点。

然后number blocking我就写伪代码了。

设置成非阻塞,那我要对这个三这个server设成非阻塞。

然后呢,while true循环里边while处循环,我做两件事情,一个是accept 3,接收这个是阻塞吗,它就不阻塞了,也就是接收他立刻就会返回,要么返回一个空挡五,要么返回一个-1。

也就是所谓的那对不对,代码就会往下走,跟着我的思路的话,有小问题,小问号收一收,跟着我的思路走,被丢了,在一个while循环里边,第一件事情做他,第二件事情是要再做一个for循环。

嵌套这个for循环里面做一些什么事情,for循环里面其实要做一个receive,我们的客户端读取答案,便利你这个客户端读取,这里边比如说便利那个五变成六分,那个七一个while循环里边会有两段顺序去做。

而且这个客户端其实检测上面得到五五,你得设置一个那locking就是listen and locking口的连接,number lock,大家都别阻塞我一个线程就可以搞定了,两类式的接收和读取。

用一个线就可以了,完全屏蔽了之前的多线程,不,这就是ni的模型。

如果不睡一秒会怎么样,如果不睡一秒的话,这个无所谓嘛,就是空转的速度会快一些,这如果不是一秒的话,就玩命的来这么来,但是这是注意了,如果你看这个list为空的时候,那空调的速度比较快,但是随着接触接触。

可能客户端的话,其实这行是可有可无的,这行是可有可无的,我为了怕他输出的太快,每学完一次都都疯狂的输出,所以我加了一个疫苗,这行无所谓,这一行无所谓。

好吧,我用代码给你演示追踪一下,想不想听,想不想看,眼见为实,对不对,可能c c,把这边的目录清一下,刚才的rm 2 rf 2清清表,rm,plus清掉这些都是其实我跟你们讲。

这些都是在vip课程要去讲这些东西,而且其实只是为b i t课上关于io这块模块知识的冰山的一角,下面我们用哪个例子去演示,其实就是socket n i o,我先看一下代码,我要做一件事情。

我得把这个数一秒的事先给它解开。

系列 2:P59:0.4 netty的reactor模型原理 - Java视频学堂 - BV1Hy4y1t7Bo

因为这里如果要发生数秒的话,到下边我还得把客户端如果没有连进来,但是这个方法不会阻塞,我就打一个none,没有扣端键连接,换句话什么意思,跟着思路走,这是个死循环,曾经如果这阻塞的话,循环一秒阻塞。

这好像会打结吗,如果没有人连接,会还是不会,是不是不会是不是不会打印,但是如果设置了非阻塞,那么是不是即便没有连接,是不是你会频繁的看到下面看不到,但是你会看到这行每一秒那一次,每一秒那一次。

其实在真正开发的时候,这个这段分支是不要的,这个数疫苗也不要了,就上去直接接收,然后呢就是如果这个客户端接收到了,就开始添加list,然后剩下就开始便利list,然后回来之后继续接收。

这是一个快速的服务端响应的一个过程,好吧,我现在都解开了,那么来开始做,怎么去做,用javc,但是用它之前我给你对比一下,如果我用usr javg处s k一点四的包,下面的in下载java c尝试编译。

test是这个socket n o,socket n l o。java注意看回车报错,没错啊,这是会报错的,所以你要用什么,要用这个更高的版本,应该是在七之后啊,1。7之后,因为我现在是11。8的。

用java c接socket n l o这样执行就不报错了,看出版本的变化了吧,哎看出版本变化变化了吧,哎ok走,有了class之后,然后我要做一件什么事情,还是用stress这个万金油这东西非常好用。

怎么写,后面怎么写上ff o out前缀追踪啥追踪,用java,这是1。8的版本的执行,我们socket n i o这个类以上在网上看同学来刷波一,啊你回去可以尝试啊。

你即便把所有代码还原成最基本的代码,就是只有一个ni o的包的导用的话,它就一定会报错,好我把它抛起来,加进,是不是每一秒钟会打一个大,也就是说它并没有阻塞住,这就是先给你展示了nl的特征。

对吧,是不是已经没有诅咒了,因为它在每一次循环的时候,这行都被打印了,这个位置没有被阻塞,因为现在也没有人去连进来。

对不对,唉那么除了这件事情,我要让你看到一个更直观的一件事,因为1。8了,注意第一个,这不是中了,第二个是主方法,8506,8506是主方法,我们来看一下v i78506 ,这个文件跟着我的思路啊。

就是前面我的服务已经跑起来了,我现在追踪这个服务它是怎么样去操作的,然后找到socket是不是任何的s o c k e t是不是任何的,只要使用网络编程,它毕竟毕竟会掉一个socket。

调完之后看他返回了一个三三,就是那个server有了socket之后,然后还会有一个,不是这个三啊,我们来找,先先去搜索90909090吧,找到最近那个绑定是绑定四,绑定四,这个四在哪往上倒。

对面已经记住这个通道就可以了,这是不是2821行一,只要是三部曲socket得到一个四。

得到四之后,然后肯定是绑定四,绑定四之后肯定是监听四,这都没问题,对不对啊。

那么四是不是就是server了,那么是不是在四上我要accept 4去接收口端能听出来,稍微一就是sl的三部曲socket绑定listen,然后后边一定会玩命的accept接收这个四。

那么现在去找来看到2856行的时候,accept 4是不是接受了,但是这时候你会发现它返回是什么,是不是-1,曾经accept接受的是谁,是不是要么五要么六,要么七对对,对不为。

-1其实就是那就是没有返回吗,它报了一个错误,那这时候其实是不是没有这个方法,你没有佐助,是不是剩下就是rp 1,那然后这时候这个文件你还可以怎么去看,是不是可以用l杠f08506 。

走你看这个文件是一直在动,这个追踪是不是直在动,是不是他一直就是给你返回,-1没人来,没人来,没人来,没人来,但是我不会堵得住,我代码一定让你往下走,一定让你往下走,这就是n i o非阻塞,好吧。

先跟着我的思路走,那么些东西,我不可能一口气把这个什么都给你讲明白了,你先跟着我,别丢你学,明明一个第二个就好通了,好不好,对不对,我脾气有点爆啊,你发你们总是对学习方法,这就是你们自学学习方法。

总是下雪下雨下雪,一会看这,一会看这一个东西,到最后都没有都没学明白,对不对,那这时候注意看前面这一直闹一直闹一直闹一直闹,后边呢一直阻塞不住,组合不住,然后呢再来看我们尝试一个口罩,是我连接怎么办。

nc local house 9090,我连它变压器连的时候,其实你可以想象到这个accept的返回值是不是-1了,它就应该返回某一个具体的值了,对不对,是不是这道理,我快速的把它加机,建立连接。

这边ctrl c给它结束。

往上倒,他一定会有一个accept,就不是-1了,刚才有续航,他就一秒崩了。

一下往上走,往上倒,倒倒倒倒,得到一个accept,在这好了,这个accept是谁,是不是acaccept,accept之后,他还是反复一,是不是返回一个五了,又返回了一个自动连接,对不对啊。

然后它的逗号是多少,逗号是56180,这边因为太多了,给他给他炸出去了,看到了网上能找到,刚才那个你看是不是有一个客户端。

逗号56180点进来了,对不对,能连一个,注意这是不是一个线程能连一个。

是不是就能连第二个,再来nc local host 9090走,这边是不是有连接客户端,也就是一个线程,我可以连很多的客户端,比刚才那个多线程的版本,是不是接触了很多资源,也能完成这些事儿,对不对。

这是nl好理解吧,ok这块不做太多的介绍了,因为啥出去,你这辈子基本上不可能自主去选这个ni o,我觉得很多事情很复杂,而且他性格也不是也不是最好的,往后走。

我们先去找他,就是现在你基本能明白什么是n l o了,其实n o就是一个东西-1什么叫非因分化不足,不不阻塞这么简单,是这道理吧,明天讲多路复用,今儿都给你讲,多路复用好不好,就看能讲多少是多少。

没必要等到明天啊,这是n o对不对啊,n l o我们来总结一下n l o,注意听nl它的优势,一个两分钱花的值不值,就光到这后面不讲了,就我就讲这么多,就就讲到这儿我就不讲了,你那两块钱值不值。

因为其实说实在的无师自通,我可以真的不用跟你讲了,因为我该给你的学习方法都已经传授给你,剩下真的就拿prise,拿着mu to,对不对,然后一会自己跟踪自己学什么东西都能学明。

那么请回顾io的优势是什么,优势,在群里抢了一个七分的红包,还赚了五分钱,没没没就没天理,真的是不会阻塞,不会不会阻塞,不是优势,如果你就三五个客户端,其实用b i o还是蛮舒服的,还真就是这样。

如果你客户端连接很少,用b o就足可以了,明白吧,用这种i o的优势,这个优势其实规避了,多线程的问题,无论是资源问题还是调度还是性能开销的问题,相对比前面好一点点对吧,那就是在并发量很大的时候。

很大的时候,这时候其实我在这儿抛出一个回去自己看,网上自己搜c 10 k问题,这是目前来说,如果搞编程,搞网络,搞分布式,搞微服务的话,这块肯定能把它禁用一下,这个怎么给他禁用。

自己网上搜一下什么c 10 k,就是当你的服务器有1万个客户端连接的时候,就会产生问题,那么比如说开始说弊端,找到我学习的方法和规律了吧,就是我上面说这个一定要学明白,前面如果nl这块学明白了。

你就好记了,关键是从学会之后,你还能自主推导它的弊端是啥,这才叫学明白了,你才能知道下一个记录是啥,怎么演变过来的,那么b端是啥,请告诉我它的弊端是什么,一个阻塞都阻塞,不一定啊。

其实刚才我用的是一个线程,你那个link的list可不可以切成四段,分到四个线的位置,是不是也可以,是不是可以有一个线程直接就是accept接收,然后有四个线程,每个四个线程获得了1/4的那个客户端。

那个那个例子一段这个也可以吗,你可以用多线程来处理嘛,但是线程绝对不会开到每一个连接一个线程b端是啥放大,假设教你一个方法,就是假设就跟你在听那个左左老师讲课的时候,也其实也有这种概念。

就是你放大你的数据集对不对,然后一来验证你的这个算法到底在变化的数据集,就是在小端大端的时候,数据数量大小的时候,它的一个真正的一个大度假设,如果真的有1万和连接。

就是你循环循环循环循环循环接收了1万个连接之后,自家都都是成人机,然后大家一会给你发东西,我给你发东西,那这时候它的弊端是啥,注意清看见的一句话,用人话,用同话翻译,比如说在每循环一次,每循环一次。

他循环一次做了哪两件事情啊,第一步是不是accept接收,对不对,第二步是不是有一个线的,一个循环是便利所有客户端要调一个它的系统调用,receive系统调用是不是会产生软中断,是不是会有太大。

就是否定了那个恢复现场,那假设1万个连接里边儿只有一个人发展数据,就放大这个这个特征码,然后来看它的弊端在哪,b端就是假设有1万个链接,只有一个发来数据,那么每循环一次,其实。

你必须向内核发送1万次receive系统调用,那么这里有9999次是无意义的浪费,消耗时间和资源,听同学来刷波,666,注意这个循环叫做用户空间的循环便利,复杂度在系统调用。

频繁的用户它连接的切换不跟ok,找到问题,找到b端了,怎么解决它思考你要学会自主学习,我都给你都给你带到这个程度上,我们带你起飞了,那请告诉我这个问题怎么解决,它真正的问题是不是就是如果1万的话。

就是在你的用户空间和条之间,是不是往复跑来跑去,往复跑到在一次循环里边,比如说注册事件event毁掉,no no no no no,不不不,不要上来直接说这个还是没学明白,我都跟你这么说了。

他往后跑往后跑,每一次循环里边有一个o n有一个1万的一个复杂度,但是这里边其实只有一个人发来数据,对不对,你就让他之前跑来跑去,跑得很累,因为什么,因为你循环的时候。

这个for循环的时候每循环一次只能问一个客户端状态,有一半的时候你是要循环1万次,如果能将这个循环的复杂度降低,整个程序的复杂度和性能是不是会提升,为什么,从ni o的下一个知识点要引出谁。

要引出的是多路复用,是多路复用,多路复用里面又分为select pp和基于事件的回调的e和一个过渡的过程,你要学制学拳,别丢东西,技术是一遍眼睛过来的,那这时候其实你就期望了。

如果我这receive的时候不传一个客户端,我传了一一万,那内核我就掉一次内核,但是他告诉我说这里边有仨q端,你可以读了,然后你再具体的去读那三个客户端是不是加起来问了一次,他加了三次毒才四次。

也不会是1万次,能听懂这个简单描述的同学来稍微一是这么个理儿,道理,普通话是不是一个道理,那这时候其实就是谁发生变化才能支撑这个东西,我再说一遍啊,就是在一个while循环里边,除了接收客户端。

你手里呢还有1万个客户端,那么目前这种a的方式在for循环里,基于每一个客户端要调一次receive,尝试着读取,有1万个客户端,就会有1万次调用,那你想好累啊,我能不能我有一个调用。

把1万个客户端传给内核,就是切换一次内核,给我一个返回之说,里边有仨推毒,你再去在用空间调三次receive真正去读,而且这三次一定会有返回值,那加起来一共才有四次调用,而不是1万次调用。

其实根本就是你在三次真正receive读之前掉了某一个方法,传的是1万个客户端,给那盒只切换了一次,这个系统调用,他就告诉你有三个可以读,你就发生了三次receive,加起来一共四次。

这个能听我们来刷个一,是不是是不是这么一个道理,对吧,那这时候其实你掉了一个系统调用,里边不放一条路,而放了很多条路,是不是很多条路复用了这一个系统调用,所以它是不是应该叫做多路复用器,牛逼炸了。

我现在特别想说一句话,这是什么什么什么话吗,来吧报名跟我学,我带你飞,哈哈哈哈哈,看东西看东西,我给你演示啊,我给你给你给你给你找啊,那其实你要说明白是什么东西支撑的,还得是内核向前发展一步。

就内核得多一些东西,多一些啥东西,多一些多落复用器的概念,但是多路复制器啊,版本还很多,有我先给你写了多路复器,有select your po,有一套有这么三种形式多路复用器,但是他们都叫做多服务器。

这仨东西到底是什么意思,一个来说啊,显然pl基本上是一类eo,是另外一类多路复用器。

那时候怎么去提供的,注意看就是都告诉你这个信标用了就是manual select,你找到select,这是内核提供的,内核不提供这个东西,这辈子程序忙死你都达到这个效果,你必须得自主轮询。

select的时候你看就是int select,然后注意看成单词什么的哎前面传了一个int,一个数值多少个文件标,我就知道这电路里边都有都有啥情况,然后是哪些,有两个有三个集合,一个是read可读。

可写一成,你要把那些文件描述符作为参数传给内科,然后也可以加一个是否是现实之内的一个返回,这是属于多服务器,看到正正正经的一个官方描述,这东西是是是是是一个什么东西,select。

它是允许一个程序to监控多个文件描述符,这就是所谓的多路复用器,waiting until one or more,一个或者多个of the fety degrees。

多个文件描述符达到可读可这个可用的状态,然后回到现在这句话的翻译句话能不能听懂吧,就允许你一个程序监控多个文件标符,要多复行器,关键看上边会有一个看这同步的io多路复用器,就是select。

这就叫做同步io多路复用器,注意这出现一个词叫做同步的,其他的是不是阻塞的,取决于你怎么去设置。

怎么设置,snake是多路复用器,它并不是你的socket,并不是你的i o你有什么意思吧,异步的吧,你你你你一会儿我给你解释什么同步异步啊,就是很多词汇,你们都学受网上很多的帖子或者不同人的讲课。

给你带歪了,带错了,有些面试官的确面试官其实也没有懂到这么多东西啊,不管怎么样,我先给你画个图,你就了解了,画一个图,你了解别慌啊,跟着我学,我把东西给你讲明白了,还是那句话,讲明白了你就会了。

会了之后你就不怕了,关键是你得找一个地儿的话,他真学明白了,关键是我们这儿好多人这么去学,其实别人都为我们的vip都学明白了,那么未来你的面试官可能就是我们vip,如果你不学明白的话。

面试你都过不了对吧,其实间接的就是我们在因为我们的存在,把整个行业的面试的门槛整体拉高了,那这样的话其实我们的学员是是有极大的这个生存空间的,对不对,来注意看。

只要是所有端肯定socket find的listen还是绑定这三件事情,注意看,如果你有1万个文件面符怎么怎么做的啊,他是怎么做的,以前在一个县城里边,我肯定是循环,他把一个文件描述符问一遍。

那现在注意看他要怎么去做,其实还是一个外部循环的,不to不处理做一件什么事情,这时候注意它掉了一个select,写在里边,然后放上你的所有的文件描述符。

这个文件描述里边包含我们的那个listen和口袋连接的,假设这个文件名数量已经达到1万了,但是这个复杂度是o就是基本上冲出来说是o一的,o一的复杂度,什么叫o一复杂度,就是你while循环里边叫他一次。

他就给你反,他就给你反了,那个激活结果告诉你谁可读可写了,但是下边注意听了,假设啊,假设你有一半,1万个连接,这里边就是传了1万个对象,1万个30多倍,是不是传进去了,掉到那会儿。

这是发生的性器内核性调用了,在这1万个里边有三个不读,三,一个可读,一个可以读了,那这时候其实下面你要做一件什么事情,是不是receive直接读那个可读的fd,那个文件名复制不就可以了。

这是不是也是复杂度为o1 ,对不对,如果有三个的话,是不是这个下面你要写一个循环便利这三个字去读,如果如果1000个的话,这块一个学校要读1000,但是不管怎么样。

就是一个通俗上来说一个常数的o一加上一个om就是具体的可读的,它整体的话也会小于1万,小于等于1万,除非你1万都来数值,到这一步能听出来稍微一这就是所谓的多路复用器和它的一个效果,不。

它和前面ni前面那个nl是这个差在哪了,差在哪了,它俩具体的差别在哪,以前注意听啊,以前是这1万个fd,我在上面程序里边是要receive,其中一个再receive一个,再reserve一个。

1万就要掉1万次,现在我调一次就可以了,然后具体读的时候再读它,少个excel就可以,如果这里面有一个excel,你还可以s c e p t还可以接收,对不对,接收你那个f d,那么在这儿注意今儿没找。

能大概听明白了之后,我有一个非常非常重要的事情要跟你说一下,有一个重要的事情你先给你说一下,说完之后再给你解释后面的问题,因为现在刚才我已经发现有人已经误入歧途了,有一个什么事。

你说你回顾我从前边b注意看,这是bl模型当中,如果想从注意先跟着我的思路走啊,如果想从io读取数据是谁调用的读取方法呀,是不是程序,无论当前线程还是异步线程,它得有一个程序自己去receive读。

这是b l o替我们来刷波,一程序自己去读的选择数据,你得自己调那个读的具体的一个方法,那么到n i o的时候,想读数据的时候,如果你前面是不是设置四个字,读的时候是不是自己去读的。

是不是也是自己去读的,ok这是n i o到多路风气了,唉多路风气在这注意,听多了风气,他只是给了你状态,这是第一点,你是通过多路复用器之后就把数据读到内存了吗,不是回答面试官常问问是否可以通过多。

是否是通过了多路复用器就可以达到快速的读取io数据,先回答走,不是他只是告诉你哪些文件描述符可读可写,你只得到了状态,然后注意听和前面一样,那真正想从i o读数据程序要自己去调receive。

能理解什么意思吧,ok那么总结完就是一句话,如果程序,自己读取io,那么这个io模型无论d o l还是多路复用器,它们统一叫做同步模型,同步io模型,能接受的来刷一波666,把你所有的问题。

小朋友之前是不是有很多问号,今天是不是都解开了,只不过在同步里边有阻塞,有非阻塞,那剩下的就是一个异步,异步的话,只有windows是真正的异步i o c t i o完成端口。

那这时候其实是程序不需要调receive,因为程序只是注册了未来io上读写这个事件,当到达之后,继状态发生了,且数据从内核就是windows内核应该是内核有现成。

而不是程序里开机线程是那个内核给你抛出一个线程序,把你注册的方法执行了,把数据给你拷贝到程序的内存空间,然后换言之程序不需要自己去调读写l的方法,那这时候才叫做真正的ae不答案e不仅此而已,仅此而已。

还有五分钟,赶紧讲一炮,蔡司,你这是一个我怀疑你在威胁我,好吧,注意你的态度,我这么半天了,我连我连口水水都没有喝,好吧,那这里面注意听啊,在这延伸一下,刚才说了,多路复用器里有select。

它是这么去玩的,这个select其实这个方法还可以把它变成谁,还可以变成p,另外还有一个pop,pop里边其实传的还是bs,明白吧,po和select它们是一类的。

只不过select大家都知道有一个1024的限制,1024 五那边出现的这个和你you limit unlimit,限制那个用户黑大v标符不是一个概念,就是在源代码而不能限制的,但是后就没有这个限制。

它完全遵从于你操作系统的,有limit限制的一个程序,可以打开它的面,复制随系统的配置就走了,懂了吧,这是一类,这是一类啊,但是他们都叫做多路复用器,多路复用器上面没有说啊,多路复用器就是只能给你撞上。

多路复用器只能给你撞上,读不读还得是你自己去做的事情,所以他们同步模型那一步是干啥啊,一会儿再聊,从多路复用器里边的两大阵营死了,套到e破的过的过程当中,其实又要回到我一直跟你们说的方式了。

找cp它的优势在找他的b端,sli他们是多路复用器了,那么他们的优势是啥,又是啥,就是结合了把前面那个那个劣势怎么解决的,就是它的优势回答我,它的优势是什么,没错。

这个其实曾经你前面nl的时候是等于用户态挨个循环便利,然后到多路风气起来,炮的话其实是用户还掉了一次,把所有的文件运符传给内核,内核去便利,优势其实也震惊客户的劣势。

优势就是通过一次系统调用八嗯fd文件标符,扣端连接传递给客户,传递给内核内核进行便利,进行便利标识,每一个文件标符它是可读可写了这么一个状态,最终给你返回,你去把可读写的去处理就可以了。

那有人说不是又发生了便利吗,但是这个便利你就明白了,一个是发生在内核内部的变绿,一个是发生在陷入一个,我调你一次,给一个结果,我再调一次,这种用空间到那个态的这么一个便利的过程。

你说哪个便利更省时间更快呢,是不是,其实说白了就是这种便利减少了,这么一句话就解释了,这是他的优势,这是显示套的优势,124指什么,1024就是你可以建立多少个客端连接。

select上限只能接收1000 0245,一个select,它并不是说受你的操作系统有limit这样的一个限制,然后你可以编译c代文件,编辑它的c的源代码,然后把这个值改成20484096。

但是这事太麻烦了,现在重新给重新重新编编内核,然后炮的话就没这个限制了,这个版本有1。4的,有2048,别纠结别纠结啊,我还可以给你一个3096或6535的,琳琳最多是10635,通过大哥。

通过你们现在所有人聊天,你们对知识底层掌握的根本不扎实,我完全现在有理由劝你们赶紧报个名,真的我的io克里边把所有东西所有的讲讲解,你们现在所有的问题讲得特别特别的细。

每一个我都给你告诉我是代码极限制的,然后是进程用户极限制的还是内核级权利限制,哪个我都会给你讲的很清楚好吧,ok那么这是它的优势啊,这是优势,那么优势有了,那么来思考它有没有弊端,找到弊端。

你才能推导出一炮一个,请请大家随我一起掌握学习方法,根据现在的描述,它有没有弊端,弊端是哪些,它的弊端我可以告诉你两个,他的b端有两个b端是啥,弊端是啥,弊端来一炮,我跟你说多了,服务器只能正常。

他们都是我在给你写的,明白点啊,slack,我非得给你写出来一炮,我说了,他们都是多路复印件,多路飞都是同步的,他们都是同步的,记住了,被死了,他们都是同步的,要想e破它是异步,因为它是异步。

绝对绝对还是同步,因为什么讲到易破的时候,你只能得到文字描述的状态,最终还是自己去读写b端啥,这是你思考啊,哎你想如果第一次循环的时候,也不是第一次,就在一次循环的时候,假如现在f4 已经1万了。

诗中理惠o一复杂度调到内核,把1万个连接从用户态是不是传给了内核,后边处理完之后吧唧外循环一回来,你是不是还得掉sla,是不是还得把那vs再重复拷贝一次,就是一直重复一直重复的把那位传说的脸红。

而且就是因为你每次重新传递这句话的反反面儿,那个意思就是内核不存,你上次给我之后,我就没有存住它,所以会造成你每次重新给我f d s,我那盒重新遍历他们的状态,这是第一个弊端,重复传递。

重复三df文件标符,这个问题b端能听出来稍微一,那么用用大腿想想他的解决方案上,用大腿想的解决方案是啥,不用说了,拷贝这解决方案是如果循环循环循环了10万次,只有在第一次的时候,我把这个vs给你传递过。

后来也没有新增的客户,这个客户端的假设就是1万个了,后续的外部循环,只要我那会开辟空间,全都拿fs,后续是不是不需要重复传递了,所以敌方就是内核开辟空间,这个解决方案能听懂的来说说一,这就是一炮的炮。

里边后边给你讲了,还有一个ecrader创建一个空间,空间里面是一个红黑树,陆陆续续的把新来的所有的客户端扔到红黑树里去,那未来就不需要重复的,就用户态去调什么东西,去咨询这个文件描述了,好吧。

这是第一个问题,第二个问题就是其实由前面他自身那个携带这个造型的,就是每次都要每次select或者泡的时候都要重复,都要重新,电力全量的i d就是你只要掉了一次select,因为你新新扔进来的。

你没有空间,然后呢这select我要内核主动的线性变了一次,告诉你哪些有状态也没有状态,它没有完全基于什么呀,就是某一个f d如果数据来了,那这时候你未来问的时候,我直接告诉你,他可读了。

不是立刻告诉你,而是我先去店里到他那才能告诉你,所以这是第二个问题,那第二个问题怎么去解决,这个就是需要祭祖的深度知识了,机组的深度知识,中断call back回调函数以及增强回调函数的一个处理过程。

我可以简单给你看一眼,但是这节课讲的就来不及了,在这其实有这么一个概念,就是强行插入一个计算机组成的一个概念,就跟我画的图差不多,但是这里边你要知道网卡也会有中断,中断成之后之前是把数据放到bg里。

后续的话你还要把放到80这件事情做完之后,还得多做一件事情,把这f d在它的内存空间的红位数标识一下,那么来调的时候直接返回了,仅此而已,好吧,解决方案给你拖出来了,不,你没看啊,简单看一眼。

不要小看io这件事情,io我还只是给你们讲网络i o从b i o ni到多路复用器的前半段cp,以及找到他们的弊端,然后到最后我们必然要推导出e,因为e才是现在用的多的,相对来说用一个多的多路复用器。

但是它也依然属于同步模型,好吧那么这个事现在讲的话来不及了,因为这个1p我给你讲的话,又开始一大堆,我们挪到明天去,今天这点东西就完完全全够你们复习的了,当一炮这个事真正学明白了。

这个东西真的学了nt太容易理解了对吧,nt就太容易理解了,如果这些东西没学明白的,你理解理解nt的话还有点复杂,只能表面懂一片虚体,再聊底层,他为什么那么去做性能,它性能到底在哪。

你说出来内容官直接把你烫死,能发吗,笔记能发啊,笔记能发,带的小姐姐可以在如果开了新的这个群,那个微信群的话,可以发一下那个咱们那个微信群的二维码好吧,然后我放下咱们抽奖到外面开始出书了。

你看一个学习的过程,给你们顾虑到那么多人,扫这个二维码,330分,多线程与高并发来骚起,我真的真的同学们好吧,我是上课前喝了一瓶水,我这边水完全没有打开,我真的一口水没喝,嗯,刚才那个微信群那边吗。

还能进吗,还能扫进来吗,满了是吧,这帮人在干嘛啊,我跟朋友吃完饭之后再放一个是三二吗,这个,听到我刚才非常凶了吧,到时你直接报我来拿一次,再放一个那个那个微信的那个是哪个哪个呀,我看看,这个就行了。

来扫这个二维码,我把这个两个码,这两个码有点冲突啊,放到这儿,咱们小九啊,小姐小姐咋不看,想看小姐姐的,不是随便给你们看的,你来公司看,咱们公司地址是海淀,但是现在这两天这个vip知道咱们两天装修呢。

在这装修过来吃啊,过段时间,而且现在你进门肯定还得各种各种那个查看你的绿码啊,那个乱八糟的,很麻烦,你过段时间疫情这事完全解开了之后,你再过来玩,因为咱们装修的话就给装修点什么台球,跑步机。

读书室之类的啊,北京的小伙伴们可以过来聊天的,嗯嗯让家吗,这个二维码让家吗,频繁了呀,怎么这么多人呢,我再换个谁啊,我再换个二维码,这方面再加一下,好吧,其实你们来的时候加过微信了,就不用重复加了。

你们之前来的时候是不是有人接待过你们,加过你们几个微信,就不需要重复再加了,不用冲在家,我一会都会给你们,就是你们在那个群里面就已经可以给你们去发送了,我讲的做的这么好,还不是我的贵姓,我姓周,周志磊。

就我没有用,你就记住了,马士兵教育就可以了,兵教育马老师,好吧,那今天我们就讲这么多,一会我整理资料,会通过咱们的微信群发给咱们的小伙伴们,好吧,那今天就到这儿,怎么样,明天都来看,都来听课。

明天讲重头戏,eula nike,露个脸,大家说再见,今天到这拜拜,报名多少钱,问一下咱们群的小姐姐,最近刘老大有活动有优惠有优惠哟。

系列 2:P6:马士兵老师JVM调优:6.根据预估值设定JVM初始参数 - Java视频学堂 - BV1Hy4y1t7Bo

哦他现在已经有问题了,什么问题呢,它是不断的频繁的产生f g c最关键的是在这,你往这儿看好,这是最关键的啊,这是什么意思呢,这个的意思就是说当经历了一次负dc之后。

整体回收内存从原来的妖精198015k回到了1980,198015k诶,这个是198015k回到19198014k只回收了1k,你一个fcc下来,您老人家只回收1k或者0k在干嘛,他在干什么。

基本不减少,对啊,为什么我,好这里面一定是它回收不掉,回收不掉,什么意思啊,你们分析一下,这是我们的old的区,这里面内存满了,我做回收的时候本来正常有有有的对象应该都死了,但是他回收一遍。

居然里边没有死对象,没有垃圾,没有有任何有垃圾的地儿,说明里边对象全有用全有用,又代表着有的所有的人都有引用指向的,回收不掉啊,这个叫做内存的泄漏,内存的溢出好,我这里澄清两个概念,以免有同学不了解。

第一个叫memory leak,memory league,叫内存泄漏,第二个叫out of memory,内存泄漏是什么,内存泄漏是说你你在这块内存里有一个对象站在那儿,他就站那不动了,没什么用。

但是他就跟他站着也不释放,产生了内存泄漏之后才会产生内存溢出,如果这样的对象多了,内存就溢出了,但是如果只有那么一两个,他就在内存里站着,他也不他也不释放,它就占那么大地儿,但是你其他内存还够用。

这个时候就不会产生out of the memory,所以内存溢出和内存泄漏它是两个概念,好get到同学老师扣一,对那个毛鹏飞说的对啊,站站站站着桌子不吃饭啊,属于这样的。

ok从最后的我们的分析结果来看,它一定是发生了内存的泄漏,并且泄漏越来越严重,然后产生了内存溢出,那这时候我就要分析了,到底是什么样的对象占了这么大的空间好,所以我们这个逻辑很清楚吧。

这个逻辑我们看日志日志发现他回收不了这个空间,那就分析里边也一定有泄漏,里边有泄漏的话,就是一定有对象在不断产生,在占着空间,而且还不释放啊,占占着茅坑啊是吧。

然后所以下面呢我就要看到底是哪些对象干的这件事啊,这个逻辑到现在为止应该比较清晰,对不对,那好当这个逻辑表清晰之后,下面我们就来分析到底这里面哪些对象被占了呢,在这个进程已经死了,我重新把它跑起来。

这个,好我在另外一个窗口里教大家弄这个命令。

ok,j mac啊,昨天没给大家讲的这个命令叫什么呢,叫j map,好看这里啊。

在这儿在这儿啊,就这些命令呢我不建议大家都背过。

你手边有一条小的那个呃手册放旁边就可以了,你用多了呢,其实面试官问你,你一定能说出这个命令的名字来,但是参数你不一定记得住,这个事很正常,你要把参数都记住的话,反正这事儿就不对了,说明你背过来看这里啊。

教大家这个命令j mj m map的意思叫memory alas analysis,分析哈,procedure啊,或者叫project或者叫program,或者叫什么嗯,就是分析内存用的来。

j map这个命令呢,它会干一件什么事,他会干这么一件事,他会直接进去进到那个那个那个正在跑这个内存里面,帮你去把那个里面那些对象,一个人又给你揪出来做一个分析,这个很牛,进行这个命令之前。

我首先得知道它的进程的id号gp 2310,嗯history gram生成一个分析图,2310回撤,当然这个,呃就就就就那它的内容太长了,所以我们给它加一个限制符,head杠20,我把前20行给打出来。

ok同学们,你们仔细看这里列出来的是什么呢,这里列出来的就是在这个这个m里面有哪些个类所产生了多少个对象,好比如说有这么一个类,这是数组,这个是数组,你不去管它,它本身只占用了344个对象,呃。

我们来看这里,在这里呢有一个scared future test,你看到了吧,好它产生多少个对象呢,14万多,而我们的abstracutemanizer,这是我们的所产生了28万个。

big decimal,是我们的cut info,那个类里面的成员变量产生了14万多,下面呢都一样的,14万多个最主要的类型在哪呢,其实在这儿看到了吗。

cut info居然cut info在里面有14万个对象,大家记住这个数,目前是14万,再执行一遍,你你会发现它已经变20万了,看到了吗,再执行一遍,你会发现它已经变21万了,嗯同学们看出问题来了吗。

来get到问题,同学给老师扣一问题在哪里啊,对有一个对象在不断的充电,这样你是不是就把它揪出来了,同学们只增加不减少,对不对,唉当然我告诉你,你只是把这个对象给揪出来之后还没完事儿。

你得去查你这个程序的bug到底在哪里产生的,一直没有释放,对啊没错啊,就是这个程序的问题在哪里呢。

腾讯的问题在哪里,如果你没有学过线程池这个问题,你还是找不出来,所以暂时我就先给你扔在那儿好吧,你自己去查,当然你要听过老师讲的多线程高并发这个书上的那种,这个这个你很容易一眼就看出来了。

但你要没没学过这个问题,你找你也得找半天呢。

呃我还是那句话,昨天呢也跟大家说过这些问题了,就是另外一个问题,用这种方式呢,目前看起来并不是特别难,其实oom问题我跟你讲这个问题不难,不是很难,他的步骤也是死的,知道吧,就是你运行起来这map一下。

然后看看哪个对象占的最多诶,接下来就把这个对象呢,跟到你的代码里面看看哪里在不断的产生这个对象就行了,找你的代码的bug去已经定位出来了,这个不难,但实际上呢呃你将找这个bug出来呢。

也没有你远远没有你想的那么容易,有一些业务逻辑的写的非常的复杂,所以在这个时候呢,呃o o m问题,这就是一个相对一个死的步骤了,我们来稍微回顾一下,其实相当简单啊。

别人说你你这个你们原来产生过om问题,你在简历里说,那为什么问你,你你怎么对他进行定位的呀,哎你就说你就别说你用了什么那个那个自己的那个,java自带的那些命令,你就直接说我用了office。

用了一些命令,然后呢我还用了什么,我还用了gmac这个命令,j map不是ars自带的os,没有这个命令,只有这个命令,它的功能没有实现,其他命令全实现了,所以用了这个就ok了,找出来哪些对象呢。

它不断的占内存,然后呢我回去回过头去找bug啊,我发现bug到底出在哪,是有一个现成的东西,线程池的东西没写,对好了,搞定,这是最简单的,最初级的,还有这流程清楚的同学给老师扣一,那。

现在的问题就又来了,我跟你说这map这个命令,如果面试官要问到你的话,这里面坑也特别多,首先第一点,我现在堆特别小,200兆,我只剩一个g mal,他花的时间很短,甚至不到一秒钟。

如果你们家堆100个g,你一个直接卖不上去,这哥们儿里面就暂停了,听懂了吗,好我再说一遍,如果你们家堆特别大,你一个j map命令直接扑上去的话,你们家这堆就直接暂停了。

对j map会把你的现在的进程给你停掉,这个事儿一般是不被允许的,所以你这个命令你如果说你用过这办法命令,你还得要好好的把这事给圆过去,好,怎么圆呢。

有好多种方式啊,这种细节老师都帮你想好了好吧,看这里啊,有四种说法,你自己挑一种灰度,对灰度也可以,你看比如说你有很多台服务器做了高可用了,你停掉这台服务器,对其他服务器不影响,这个牛不牛,这可以吧。

哎这个可以,当然这map还能干一件事,就是直接把内存全导出来,其实他直接就是堆转出好吧,对当你说了这句话之后,a面试官一想,我靠这哥们儿可以啊,不仅懂jvm调优,哎,他还在用过高可用的这样的环境啊。

做个集群嗯,可以给他讲个2000块钱,涨个2000块钱没问题啊,好看这里或者是什么,或者呢你执行了这么一个东西,设定了一个参数叫黑单on out of the memory,一般的情况。

任何的这种实际当中的运行环境,这个参数一般都要设记住了,在你实际运行一个你的应用程序的时候啊,这个参数一般都要设这个参数叫什么,看这里叫hdmp on out of memory error。

就是如果一旦产生了out of my memory error之后呢,它会直接产生一个内存转储文件,内存转储文件的意思,就是说这个jvm哪个堆里面的内存原封不动的给你存到一个硬盘上,放到一个文件里以后。

你就可以拿着这个文件直接来做分析了,关于怎么分析内存转储文件这件事,网上的一堆一堆又一堆的内容特别多,有讲mit的,有讲jb o vm的,有讲,当然这个讲的很少,keep alysis to。

大家听我说,你们觉得有必要给你们弄一个对文件,让你们看看吗,有必要吗,好那就弄一个,但是啊记住实际当中不是这么干的啊。

一定要听清楚,虽然可以弄一个,虽然说往上挖,把那堆书弄出传,传出来给你弄出来,可是这个事儿你一定要圆过去才可以,要理解这一点呃,生成堆转储文件呢有好多命令都可以生成啊。

比较简单,这个你就你就记就行了,就这map gdp for mgb five等于什么p i d就完了,就特别简单,一个g map命令就生成。

那呃除了它可以生成之外,office也可以直接生成,完蛋了,我们的那个哦没有来挂上,我们用office重整,好吧,好在这里啊好来,阿瑟斯里面有一命令,你一看就明白这个命令叫啥,hp down。

就是把那堆诶你给我导出来,导成一个文件里,get down,要看他用法,pdm刚刚live什么什么什么什么,ok就这么用,我就不敲了,可以吗,太简单了,因为所以他不会因此for dc吗,会的。

他会把那个没用的先给你收掉,要不然的话你导出来的东西太多了,看这里,hp dump刚刚live活着的对象,专属到哪个文件里面去,tam目录下面的dumb。hp process这个文件。

这个命令会暂停线程吗,会的会的,莫急啊,我也会给你讲这个命令呢,它背后的意思让你圆过去这件事,好吧好,这个命令很简单,我就不敲了,可以吧,同学们,它生成了之后,我还得从linux上下载下来。

下载下来之后呢,哎我下载到windows上,下载到windows上之后呢,我在用jvo vm版打开。

对这是运维的必备课程的,很简单一件事情啊,主要是太简单了,来也就是说你把这个g v o v m打开,我现在假设你已经从你的linux服务器上已经把这个文件给下载下来了,这样这个假设大家能接受吧。

嗯能接受同学给老师扣一啊,然后呢你就把这个文件打开来分析就可以了,文件,装入,找到下载下来的文件,找找忘了下载到哪了,就原来下载过的啊,呃work,在机组成原理操作系统好像是这里面是有一个的啊。

找那个什么呢,找那个呃堆的dmp文件好,这里有一个叫tim的h process这个文件的后缀名啊,其实你用哪个都可以,用什么都可以,后缀名没有,你也可以,选中打开好。

这个时候呢他就会把这个整个堆转储文件给打开,我这个堆特别小,所以打开起来特别容易,我再跟你说一遍,一个堆特别大,这个文件就在我的机器上分析起来,一天可能都分析不完,我们曾经有个小伙伴。

嗯是什么vip的学员,他是那个鸡肉,昨天我我我聊过我,我跟大家聊过,他一个对帧数文件下来,他们平分f g c,他们的办法就是重启一一直不停的重启,后来他们受不了了,说必须得把这事给解决了,然后我就说呢。

等他那个宕机之后,你一定要把那个当铺文件给我拿下来,结果呢他就把大剑拿下来了,那个大文件多大呢,十个g,然后我教他怎么怎么样进行分析,然后呢第二天我再问他分析完了没有,他说还没执行完呢,哈哈,所以。

这段文件特别大,个的时候,你是很难很难做对他所分析的啊,我在这里呃,这是生成了一个概要吧,这就不多说了啊,好看这个类这个图你就会发现已经从这就能看出来他的fnational,他的实力数特别大,特别多。

大小呢占了多少的内存,在这里都有显示date有多少个实例,16万多,什么eagger lamba表达式,cut infer一堆,所以只要这个图一出现,你就会知道哦,哪些个类占的实在是太多了。

这个分析就很容易分析了,但文件不能限制大小吗,但文件是你的内存呢,堆内存里边全部给你导出来,那你堆内存多大,你到文件就得多大呀,但是我说的是那个堆内存里面占了多大吗,实例数它最好玩的,还有一个什么呢。

还有一个这个o q l控制台,诶,这是很好玩的一件事情,就是你完全可以通过类似于一条sql语句的东西去来查询这些个实力啊,我想想那个命令还记不记得你。

比如说我呢我要查里边的各种各样的string类型的那些实例,每个实例都都什么样的给我拿出来select还phone下拉点儿慢点儿,spring s看是不是这样子写的啊,哎对看到了吗。

就是那个哎把你的这个string类型的各个实力全给你揪出来,它是位于哪个类里面的好,这个实例里面是一个什么情况,它里面的那个属性是什么,值是什么,你怀疑哪个实力不对,你就点去看。

这是你有了堆专属文件的一个好处,就是你可以用更先进的工具图形化的这一类的诶,来看它里边的内容。

好了,这专程文件怎么分析,大概的一个过程该到了吧,网上很多讲那个用mt的啊,那个没什么没什么先进的,我不知道为什么有很多人用mt啊,不知道为啥比jvm不比这b rov m也没有强到哪去。

其实最好的工具是叫做j profiler,不过这哥们儿收费的好像还挺贵的,所以我不太清楚网上为什么很多人讲mmt,你可以完全可以不用,好那好,现在的问题就来了,我到底能不能够随时的就把这个堆给导出。

导成一个文件导出来,在生产环境里头能不能这么干,绝大多数情况下是不被允许的,除非你们说你们整个的服务器是可以被暂停的,如果是那样的话不行,是其他情况肯定都不行啊,你不能说淘宝这边在对外卖货呢。

这边订单还在跑着呢,你直接一个j map或者一个hdmp,直接就把那个堆给干暂停了,你这边有整个暂停了,暂停在干嘛,不停的往外倒数据,十个g,32个g,刚才有同学是19个g多少,多长时间,半个小时以上。

这事你能这么干吗,所以你要跟面试官讲说。

我是把这个堆专属文件给导出来的,大哥你一定要圆过去,怎么远过去啊,有几个说法可以说,最专业的是很多服务器做备份的是高可用的,你提到这台服务器对其他服务器是不影响的啊,这时候呢你需要架构的知识。

需要了解高考用的这种配置好,接下来设定了hp dump on out of memory error,就我刚才说了那个东西是什么呢,那个东西是一旦产生了om之后,会自动产生对转头文件好。

这个可以说就是它确实产生om了,但是我告诉你,这个说法呢并不是非常的专业,中小公司你可以这么聊,大公司,你说oom了才会产生对战数文件,别扯所有的都有监控,他都监控到你内存在不断增长了。

马上就会告诉你有问题了,你这个时候还等他o o m呀,不是很专业,但是可以说,因为,多有,内存增长,就会爆点,但是中小型公司可以说我们中小型公司没有监控啊,没关系,o o m了之后,他才他才报警了。

这个可以,这个没有问题,我看这里在线定位,推荐大家用office进行在线定位,你怀疑哪个类,哪个哪个程序有问题了,去观察他方法的执行情况,去观察它整个那个类的各种各样的一些信息,去观察它的代码。

好还有什么,你在测试环境中压测,这个也可以说,你说呢你观察到了它的om,就是它内存在不断增长,但是我没有定位出来在哪,我们生产环境中又又不能够随便停,我这时候怎么办呢,我把同样的程序部署到一个服务器上。

然后呢我在测试环境中对它进行压测,压测试中发现它内存确实在不断增长,这个时候我可以把它导出来,这是没问题了,好了,今天在听的有面试官吗,用什么做,亚瑟jmeter lorena,面试官可以撤了啊,拜拜。

好几种说法都可以聊好吧。

至少让面试官知道你是了解这个命令,那么大家听我说,在你生产环境之中,你怀疑一个代码有问题的时候看这里,又死了,先把q掉,gps 2310,好再跑进来,我们再把阿三挂上,好了挂了之后呢,还有一个命令。

这个命令呢它是artist的王炸,很牛啊,这个命令超牛,这个命令是什么呢,这个命令就叫做jd拿来吧,第2j a d好,你看看这描述什么东西呢,叫the compel class,这个很简单。

就是给它干完了呢做反编译,jd呢其实原来是一个工具的名称啊,他后来用了这个名字了,所以原来那个g a d呢是一个也是一个反面工具,现在呢其实大家应该都知道啊,就是java自带都有反编译。

java杠p就可以啊,java p就可以呃,它为什么在自带一个反编译的功能呢,这是为什么呢,我们先来看这个反编译功能是干嘛的,呃比如说我们还是,要么名称啊等等类的名称嘛,拿下来复制,我们可以这么jb。

然后呢后面跟我们类的名称粘贴回车,你会发现他干了一件什么事呢,他把这个代码全给你列出来了,看到了吧,那有同学就会说了,说大哥你在搞笑呢,这代码我自己都有啊,我还用它在g a d在这列出来好。

你说是不是啊,同学们来有这个问题的同学给老师扣二,凡是扣二的都是在小p公司工作的,做的都是小p项目,为什么呢,因为大项目你一般用不上,大项目没大项目才能用得上啊,sorry,大项目才能用得上啊。

哎这是什么意思呢,同学们,你们想想看,作为一个超级大型的项目来说,你部署到生产环境的话,你本身就会有好多好多的程序,好多程序员,而拿着好多的程序网上部署,而且呢我告诉你,你写的程序很可能被其他人所依赖。

也许你在这个把自己的新版本扔上去之后,结果呢其他人在呃网上那个什么的时候,gay gay g往上往上传的时候,他很有能直接把你原来那个那个老老的版本,把你现在这个版本就覆盖成老的了,push的时候啊。

对所以你版本follow了,版本不对了,那么你现在运行的到底叫的是哪个版本啊,这时候怎么办,好用这个命令来观察你到底是哪个版本,git覆盖对大家听听懂这个意思了吗,尤其是做中小型公司小p项目的同学。

所以这个命令还是很牛的。

那我跟你讲啊,这个git覆盖代码这件事是经常发生的。

gp是杠f嘛,是吧嗯,一个按一个f管你乱七八糟的,直接就给你干掉再说,还有这个代码里头不写注释的这种,给你查一个新闻,看看能不能找出来。

好玩的呢,突然想起来了啊,你找一下,美国成员枪杀同事,来自己看看,一名成员拿一把伴奏手枪,周零四门,四名工人开火呃。

是因为这个程序员不写注释,不遵循驼峰规则,括号换行还天天的gto,是gf激怒了行凶者。

哈哈哈,不知道真的假的啊,就聊天聊着玩哈,应该应该是假的,开玩笑的,哈哈哈,ok ok ok好,知道就来这回事就行了啊,嗯同时连锁定都没有是吗,没事中国没枪,所以他没有没有什么危险,ok好了不多说了。

好回来回来回来回来,所以这个命令是直接可以直a d,但是只有这个命令的话,我告诉你还不算牛,你这你你们自己想想看,我就算查出来这个代码,这个代码其中有bug,我能怎么办呀,他已经上线了,哎同学们。

你们平时你们自己写个项目,然后部署到生产环境之后,里边确实有bug了,你们怎么办,你告诉我你们怎么办,你是不是把这个代码本地改好,重新编译好,编译好之后呢,再布置上去。

是这样的吗,同学们没错,打补丁唉,重新上,换下去。

系列 2:P60:0.5 netty中使用了那些"NIO" - Java视频学堂 - BV1Hy4y1t7Bo

hello,能听到我的声音吗,小伙伴们。

别说了别说了别说了,可以,你有没有化妆,怎么没有物业的,我刚才禁言了,就是现在这个嗡嗡这声最终没有影响,是,好吧,我们一会让园区的看看哪个声音,老规矩,咱们还是8。05开始讲课,等等,路上的小伙伴。

来得早的都是大伙伴,听首歌吧,这是我能不能七三,what's the point of young year when all our shadows disappeared the animals that i came out to play。

when face to face with all our fears learned that,learn through the tears made memories。

we knew would never fa,he told me,son don't let it slip away to be this time,hard to say,i。

don't you get over you,while,this is a three,he said one day,you know this world。

we are so live a life,you will remember my father told me,when i was,just a child these are the ni,嗯。

the plus all holding down a lot of fire,they can't put out,carving naming to the shining stars。

he said go venture far beon the shoes,don't forsake this life of yours,i got you home,no matter。

where you one day,i'll follow,and will be sl,let it sway,i will see you,he said one day。

you'll leave this world behind,so live a life,you will remember my father told me。

when i was just a child these are the night of the dive,your father told me,he's all the night。

the sky,my father told me,哦哦哦,they will keep your heart,once to heart,she can touch me now。

this this this one,i won't for your midon one,you slay the game of my raiser for you,and your sist。

再开一切成空军恐惧水平,感觉不会,this is not just for you want,this is called for,不爱了就we let your heart,18今年都18。

for him before it would be to tire with the fin there,oh not fit for a king,这这本这本书其实其实就是这个点猪腿。

能能知道这个名字的沐浴之士,能知道这个名字的应该是清火大剧第一节课的,这本书其实没有太大意义,意义不大,fly with me,just fly with me,来,书名是啥,不给你看了吗。

哦我刚才把屏幕磨出来了,我就再再再再再再放点,这本书意义不大,其实,老板,镜像来我给你反转一下,现在清楚了吗,看到了吗,哎我天呐,累死我了,刷好了,去了一会儿就虚了,晚上还装修装修,讲了个蚊香。

蚊子有点多,没错,今天晚上坚持到最后的,我做过,哦哦,算了就跟你们聊天了,没那啥事,哎呀,好开始了啊,还有几秒钟的时算了,不听了,想听的可以自己去下一首歌,那我们来开始讲课了,昨天讲到讲到哪儿了呀。

他这个舌头也不利了,刚才讲到一炮了,对吧嗯嗯数据下1p是个啥东西,理论讲完了还没讲完,一炮到底是个什么东西,vn讲到了这个多路复用器,然后呢梳理了一下这块应该还没有讲到一炮。

只是说了使用多路复用器的时候,无论炮或者是slight这种多路复用器啊,就说到这个,这这主要是说这两个多的分歧了,然后你都要学都要学,为什么说都要学,因为在最终啊。

最终就是我们是java程序,你肯定是要写些java代码,java代码当中,在nl当中,它也有一个多路复用器叫selector,当然这个selector是java当中nio包名下的io记录是new io。

然后在nel当中,然后包的体系当中有一个selector,这个selector其实说白了它既可以是select,也可以是poe,也可以是epo,能理解吧。

就指不定他就是你你这个同样一段代码运行在不同的特质的服务器上,它可能是这三者中一个或者是其他的,比如qq这种应用系统,那这个或者是windows windows的这个select,然后底层的东西它会变。

上层只会给你一个接口的这么一个封装,就是select,所以为什么说学讲nl的时候。

这些东西都要给你讲啊,都给你梳理清楚,这是一个很很重要的一个点,那最终其实用的最多的是什么呢,是一炮啊,这是jdk pvm启动的时候,如果在一台linux操作系统上,如果这台操作系统当中有1p的话。

它是优先选择它,但是你可以手工的切一个jdk,就咱们不用1p,当然这gbm就跑到这个鞋带上也可以,所以这个特点你得明白,那最终的话其实用的最多是一炮,我们要把一炮学的相对明白一些,他到底怎么回事。

而且你还要类比,就是一破到底跟前面这两个都不松气,他们三个虽然都是多路松气,那它到底差在哪儿了,它的性能到底好在哪了,本质区别在哪,简单回顾一下,就是在多路复用器当中,其实我们最简单的一句解释。

如果别人问你什么是多路复用器,就是多分析,首先解决的是io状态的问题,它并不解决你读写这样的一个数据的问题对吧,这是第一句要说出来的,然后询一下询问所有的io的状态,而不是每一个io我独立询问他的状态。

减少了用户带到内核态的切换的过程,好吧,这两句能回忆起的同学来刷波一,这就本质了,那这个里面其实反正就这么两句话,但是为什么要分成两类,一个起来的炮或者是一炮这两大类呢。

那这时候其实就在于slpl这个早先的多路复用器,还有一个问题,就是每次每循环里边都重新传你用空间的所有的这个这个瞄准符,到你的内核,然后内核是因为新传进来的。

他并不知道之前你你你你你你你之前并没有告诉过我,所以并没有给你准备过,那这样的话对于造成重心的这种状态的轮毂和便利性能会相对低一点,那一炮其实就是针对这个问题来解决的,就是我现在写的这几个问题。

它的弊端就是重复传递d,那解决方案的话,好像那时候开闭空间保留就可以了,或者是还有一个问题,就是每次因为你都每次重新传嘛,每次死战的炮啊,都要重新遍历全量的f d。

如果某种方式可以避免每次重新全量的便利的话,那这个性能应该也有一个提升,所以基于这个我们先来画一个拓扑模型,简单简单的去思考一下这个问题,那整到一炮的话,根据我们掌握了b端或许的方案,先自己画出来一个。

然后再去想诶,他这个东西是不是这么去解决的,然后最后我们要从实质从这个系统调用的官方的那个帮助文档去寻找,还是程序,那么是个程序的话,注意听跟我的思路走啊,昨天听完课,今天应该就会了。

你别自个儿先去琢磨什么事,你跟着我的思路,还是我们的程序,我们的程序的话,如果里面随着时间的运行,接受一个客户端,接收一个可能未来会接受很多的客户端,这是为了解决每次从曾经那个多的服务器。

每次都往碗里传东西,那我们可以在我们内核里边开辟一个空间,我就先用这种文字描述先开的一个空间空间里放什么东西,这个空间就是把你程序从运行到你一直没有断开的这些文件描述符,接收到了啊。

这个在完整的生命生命周期里,在完整的生命周期里只会向里添加一次,而不是每次你想问问他们有没有状态的时候重新添加,通常来说就肯定会有fd文件描述符,也代表我们那些个输入输出那种l流。

那么应用程序只接收了一个,我得给你放进去,然后无论每次我的程序每次循环里面,我都不重新给你传递了,也就是这个文件描述符,生命周期里只能往里放一次,那随着随着变化,那么你会有很多很多往里增加。

而每一个文件描述只会增增一次,那这个空间里是不是有这个文件描述符了对吧,这个就解决了我们第一个问题就是重复传递f d的问题,这块能接受同学来刷波一,那怎么创建它呢,怎么怎么回事儿。

这个一会儿我们看信用交易怎么去实现呢,跑一个程序来拉一下它的底层调用的顺序过程,那么除了我往里放,但是最终的话其实我们程序它关注的是什么,我明白程序关注的是什么,程序关注的在使用多路分析的时候。

关注的是io状态,那么这里面你f d代表的是i o i o状态之后,那这时候其实程序是要和我们内核去沟通,说这个你告诉我谁有状态,你肯定不能问一次,问一次的时候,那这个先看结果,结果的话。

它肯定有一个返回区,前面我可能放了这么多的f d在这个空间里边就是增是吧,那这边是增,但是这里面如果一个md代表那个i o代表那个客户端,从外界发来了这样的数据包的话。

那这个时候其实他要把他的副本放到这个返回区去,返回区才是我程序想要的,就是程序呢关注的其实就是一个返回这件事情,这是程程序关注io状态,io状态怎么来的,然后只要需要内核。

然后在这里面有一个逆差的这么一件事情啊,在这注意注意了他这一个逆差的一件事情,就是如果曾经我向那个区域放过这些分支秒词,只要我放进去了,那这时候假设啊假设一个极其好的极其好的一个一个一个现象。

就是如果你有两个cpu,我用一颗cpu,假设这个cpu因为很多的中断,这很多中断,然后有中断成之后,就会把这个i d里边来的数据放在缓冲区,然后把d放到这个区域,也就是一颗cpu。

我cpu 01做了这件事情了,那cpu在做fd以及把这个fd向这边去移动拷贝的过程,但是这颗cpu做的假设我这台电脑是服务器,有很多cpu,那是不是很有可能就是另外一个cpu cb 02。

它其实是在忙着这个程序运行七个代码,也就是他们两个人之间间接的是有一个什么呀,是一个并行的异步的,这点很值钱,到这儿呢,这个这这这这两个概念能看懂,同学来刷波一,我用两颗cpu给你描述。

那么同样类比一下,如果还是曾经这种模型使用seless用炮的时候要注意听,如果你有两颗cpu,能起到这样的效果吗,你服务器还是两个cpu,cpu 0 cp 02能起到一个效果吗。

那么假设这个程序是由这颗cpu一直在跑跑着跑着的时候,那这个程序说我要掉slg或者掉po,我要把一批文件没传递给内核,内核帮我看一眼状态并返回给我,那这时候其实这个调用的过程会产生有一个东风气的阻塞。

是我吊你了,咱们现在的内核去帮我变绿了,然后我在在这,因为没有返回,我在这儿等着,然后这个时候其实你这个cpu根本没有起到任何的效果,因为从这个cpu开始执行的程序的代码,然后一调性标记之后。

他会把这个执行从这个用户空间的程序接到我们的内核过来,我把他拉过,是不是这时候在这个cpu再去忙内核的变异的一个事情,变完之后又返回之后,是不是再从我们那边再回到城市,就没有充分利用多核这个概念。

也就没有异步,也没有这个这个这个并行的一个这个这个这个这个概念对吧,所以这时候其实明显就可以很容易看出内核,只要第二段牺牲空间对吧,然后来换取时间,ok这个好理解好理解之后。

我们来看一眼系统调用怎么去解释。

嗯先不是r先搜的是e po回车,那么打开这是e po的官方的一个帮助文档。

你可以去通片子去看一眼,但是这时候其实我教过你学习方法,这个系统调用在哪,系统调用就是第二。

二手性专用对不对,然后你会看到啊,一炮啊,这是七类砸下menu有八种帮助文档进行看下,就是menu这个程序它自身可以给用户提供八种帮助文档,只有二类的系统调用,所以你在看这个文档的时候。

要关注他某一些指令,后边括号里面标的是几,他说哪件事情,那么相对里面炮是二类和这个apple create是二类的,然后e po还有一个cpl是二类的,还有一个eo wait,为什么窗口太小了啊。

还有一个e破位的是二类的,所以这时候你具体要看谁,看那三个在这儿的话,其实你已经找到感觉了,比如说manual 2类的e破c create一个create这个函数调起来的时候。

中间那个括号的参数先不用管,它能返回值,返回值就是一个印子,这个in的返回的是一个啥,记住啊,跟着思路走,如果这个ip就成功之后,它的返回值其实返回的是一个文件描述符,但是这时候注意听啊。

哎那我之前的所谓的文件描述符,它可以描述什么,可以描述,我们现在给你讲个socket,那现在用apple create这个文件描述符描述什么,那应该是pocreate创建了啥,在描述啥,不是创建了什么。

他就描述什么对吧,这应该这应该能理解,所以这时候其实先记住啊,这一波可以的,会得到一个文件描述符给你描述了,上推出去再来1o2 类,还有e刚才看还有e pc条,这时候看到这个的时候。

其实你已经get到点了,那么衣服可能穿的那个东西,然后一个文件文件描述符描述的在使用epc pl控制的时候,它是控制的或者在控制什么,控制是在刚才那个e poo的fd。

就是刚才那个e pocreate返回那个文件描述描述那个位置,在这个位置里边还好有一个open operation,operation是什么意思。

在origin里边会有一个比如说i的往里添加或者是修改或者删除,那这时候我们来看,如果这是爱的往里添加,那添加什么,就是在刚才evil create创的那个区域里边往里添加i的添加,添加啥呢。

后面给出了一个f,比如说我们先有一个可能连接那个socket m d把它添加进去,先去给你关注的是哪些事件呢,比如毒事件,写着件或包括事件等等对吧,这是e pc t l把这个在心里记一下。

到时候你画图画出来,这个能改到这个点的同学来说不一,大家都是程序员,我相信带你看a p i的话,应该很容易能理解他的这个收件什么事情,最后还有一个就是一破位置,wait的话。

这里面会有还是对着这个ip f d,就刚才创建的那个f d文件没有符啊,然后给出你关心的事件,一个一个一个一个收纳的这么一个集合,你给出一个指针啊,这就是未来直接把你这边有时间来给我考到这儿。

我就可以返回了,那通俗来说就这么三个。

这三个对应到什么地方,比如说像刚才画这张图的时候,这张草图的时候,那么在我程序注意注意听啊,现在开始跟了,我先把cpu这事儿给你删一删,删一删,大哥你还原回来,那么在程序初期运行的时候。

程序是server,注意无论是哪种io模型,前三步他得得得得到第一个f一文件描述符,是雷神的监听的,得到之后才会做一件什么事情,马上这个程序会掉一个吸引将军的epo。

那么ile parade中间这个参数无所谓,他会给你返回一个值,它会返回一个,比如返回一个七,这个七是一个文件描述符,这个七描述的什么描述的就是其实这个在做一件什么事情,就是在内核开辟的这么一个空间。

这是第一个性状用户,而这一个程序里边一博cre掉几次呢,其实调一次就可以了,能理解什么意思吧,eo底层是一个线程接收请求吗,啊一会儿给你解释,从先跟着我的思路走看完啊,那也就是说第一步的时候。

这执行了eo create,好吧,那这个一博create它这个空间其实就是一个用f d的面表符,比如fd 7来描述的,这个字是不有点小啊,微拉大一点,那有了它之后,那上面我们是不是已经有一个文件内容。

三是监听等待别人接收的,那接收的时候怎么办,下一步他要做一件事情是apple不对,加上我刚才那句话,现在首先把这个这个a a p i写完,就为了在在哪写完,是不是要在七里边,然后做一个i的添加。

添加谁是不是把三添加进去,后面不写了,关于关于的事件事件写的吧,它关一个事件,什么事件,是不是就是in equin或者s,这样代码能看出来说明一跟着我的思路走,是不是evil create啊。

咱就给他开辟空间了,那这个f d怎么过来了,这个d怎么进来的,进来的时候其实用掉的是一炮cp,那么只要你放进来吧,下面这点很重要,只要你程序这个cpu在忙着他呢啊,该该该扔扔扔。

然后这个时候下边你其实可以写任何其他代码,添加完成之后,你可以写任何其他代码,你打一个五角星,打一个数组,然后出去上网或者爬别人动,你开始开始爬这些,你这些事情都可以做,就是在这颗cpu在处理程序之中。

但是这个只要这行代码执行完,只要这行代码执行完,你你的你只有多核cpu,只要多核cpu,那这个时候其实你的内核,注意这是内核区域,这个内核区域由于这个文件边符他其实对应的是我们那个i o的网卡。

对最终的网卡读出来的,可能读到这个文件描述,可能读到那个文件描述,只要能光看数据就发过来了,只要你网卡有数据,该机发过来了,那这时候其实你cpu是要处理这个数据,像这个内核空间去存放这件事呢。

那存档的时候,其实这个cpu可以既把数据存到他这个文件描述的八分里,也可以把这个文件描述符再去放到一个返回的一个区域里,那这个区域其实这个空间一般你查上网查的话,顶多会看到出一个红黑树的概念。

这个区域那未来的文件描述很多那个区域里的文件描述怎么去摆放的,就是我就是弄一个红霉素对吧,那这时候其实当你忙完的时候,但是最终我说了程序,你这关注状态啊,你状态这个l状态i状态,你怎么你你程序开心。

你什么时候想要状态了,你只需要执行一句一,那么一部位的话其实就这就这行,那你什么时候程序想要io状态了,直接执行就可以了,执行的时候你用空间带了一个一个指针,一个地址,一个集合,然后执行到这儿的时候。

就把这个区域东西拷过去,那你这个1p weight,其实你不光要说1p weight,只要掉一个e破位置,关键你要告你要改知道这个1p weight其实的时候可以达到什么效果,这是一个oe的复杂度。

就是你掉了就取回去了,因为在你这点这些个代码中间的时候,其实l o状态到达以及这个梳理这块,不是因为你掉了才去往这边挪的,是他那边可能并行的,已经把这东西挪过去了,该到中间来刷过,一不。

网上那些很复杂的一套理解,就是通过这样一个简单的,你要先去理解,学会前边的,如果前面我这个不给你讲,我觉得我说咱们上来直接讲一炮啊,你很难去get到这里面的这个痛点,你他为什么要这么去设置。

非得不等待吧,等待我只是说最优的,你看我每一句措辞都非常严谨,是最优的时候,也就是说你这个代码执行的时候,他毕竟是系统调用,前面那个系统监控直完刚放进去,再进去就来实践了,就扔过去了,那这里边有了。

那这时候你光都给他走了,但是还有一种情况是什么,就是你要你放了,但是谁也不发东西,这边永远是空的,你掉了位置之后,这边因为没有,所以胃才会在这阻塞等待,但是你还可以往里放一个时间。

比如我只是等待你10ms,没有的话就不返回,那么返回上就是-1,没有就代表没有,那我继续往下做别的逻辑,然后我只需要洗循环,一会回来再一投喂,这样就可以,一头胃口啊是阻塞的阻塞的。

但是它可以带一个time out,超时,而且你先记住啊,其实这些东西你的疑问就代表着不知道不应该不知道能不能代表。

如果你写过slater的话,应该知道他身上有一个被看,就是当你调select的时候,叫select select的时候,你肯定用select select,是不是可以传一个时间,如果不传时间。

是不是一直在等待这有i o状态的通知,这个在这当中站着才能往下走,但是你加了个超时的话,那就多少毫秒,无论你有没有就往下走,只不过是是不是大于零,有没有得道而已,就这么一个基本的概念。

其实你先去积攒这些知识,积攒知识之后啊,然后我最终给你对应到咱们这代码,这个有代码,你其实看着更舒服对吧。

嗯比如说selly哥们一样,select也好,炮也好,还有epod wait也好,这三个都是询问状态的,只不过在1p里多了create和c调,往里添加了一件事情,如果e po里没有create。

没有cpl,那就没有这个空间,不能你增,那你调wait一波wait的时候,你是不是要把那些文件描述传递一次,我就退化成select或者po,我感觉啊你前面是不是知道哦,我谁来泡的时候,我是不是掉鞋带。

掉船很多文件名符,那这时候其实e po跟他做了件啥事,现在你非常清楚了,那其实e poo就比他多了两个系统要用,一个是create,一个是c t l一波位的其实还是想取之剑的。

只不过一波位的其实类类比什么一波位的,类比曾经的死宅和泡那个调用,只不过以前slipo上传很多,现在我只需要调一个位置就可以了,就不需要传递那些人,这本书因为传递件事情被线性的打在了他曾经到达的时候。

这样的话每次循环他就不需要重复传递,对吧,我说最优的时候它可以达到一个o一的,比如说你掉了,这边直接取走了,也没有等待,也没有便利的,什么事都没发生,就最优的时候好吧,那这个i o的模型啊。

从我们的b l o l到多次器这两个模型,这几个尤其到多次器的模型当中。

给你讲完了,第八天一炮,我真的想看什么,但是在看了个之前。

我们得先看一下代码怎么去写,你去java代码理论知识给你讲明白了。

如果最终不和代码去这个关联的话,就像说如果不以结婚为目的的谈恋爱都是耍流氓。

哎对对对,那个nsb同学n s b同学很聪明啊,他问了一个问题,如果有新的d,然后注意看,如果假设走走过来啊,就是一波位的时候得到了一个,比如说这个开始的这个文件描述几是不是三三。

是不是关心的就是accept接受了这件事情,如果他被挪到这边,代表什么意思,就是他如果这个f d被挪过了,代表什么意思,跟着我思路走啊,这是在你e pocdl的时候,七里边放了三了。

三里面关键的cept,但是这个这个被挪过了,这个位置也取到他了,代表的是有新新年年想建立连接,对不对,唉那这时候其实一波位置之后有返回之后,一波位置返回,你要做什么事情。

是不是要自己去掉a c c ett去从三里接收一个新的,就是这么一个8f d8 是不是接受一个新的出来,这就是我说的,为什么e破它也是同步的io模型,因为最终还是让你成为自己去解决事件的这个读写。

或者这个建立连接的一个事情,i d你可以了解成就是就是连接它也可以代表文件,它是文件描述符工,在另类当中一切皆文件,他这都能听懂来刷波一,也就是最终程序还要自己去读写,自己去处理,所以这个同步模型。

那当你接受完这件事情之后,你要做件什么事,来了一个新的一个客户端,那你肯定要问这个扣端啥时候给我发数据呢,这图他啥时候给我发数据呢,是不是你关注这个这个这个i o未来的一个事件。

那你怎么去解决事件的问题,是不是只需要再执行一炮c t l在七里面,在i的一个八,爱了一个八,那关注八的什么事件,我关注他的可读事件,那这时候s8 就进去了,是不是进到这个区域了。

那就把它这又一个cl就把它放进去了,放进去之后,然后这时候你代码这个cpu跑,这个时候这个线程可以忙别的事情,但是最后你肯定写一个死循环里边又要掉一炮位置,一旦你掉了一波位置之后。

那这个时候下次的时候有没有可能f f t3 t82 个都被挪过来,有没有这种可能两个都被挪过来了,是不是有可能又有新的连接,且这个f t8 有数据可以读取,那这个e破位的返回里边,它的返回你可以动。

你是不是要再写一个循环便利f t3 去执行accept,然后遍历到f8 执行锐的读取,是不是可以继续操作,操作完之后,然后ag 3肯定得到一个九再添加,然后再循环,然后再一破位置。

就反正就是一个一群人循环,但是每次预防你发现不需要重新传递所有门那边服文件描述旨在创建,得到它的时候,我给你添加一次词条,一次理论理论上来说,对吧。

整体的ip这个从它的最开始原始的只能把一个listen放进去,三重进去,然后通过有利森有状态之后,为了之后,然后从伊森上面接到了一个新的,可不可以的一个连接的客户端,把他踢进去。

然后到最后技能键的连接就能读取数据,这块是不是走错了,边缘触发。

水平触发,那是另外一套。

系列 2:P61:6 Eventloopgroup、pipeline、han - Java视频学堂 - BV1Hy4y1t7Bo

你先把这个epo这个学完整学明白了。关键这还不是这个还没有真正把群里面,我只是理论给你讲,到底他怎么去运作的,和大JDK的API怎么对英文的才那个那个才是重要的。

apple win是app调用还是 kernel调用,是我们的app调用。这个箭头方向吧反了。这三个是系统调用,都是提供。就刚才带你看了man进看的时候,都是内核提供我们程序调的。没关系啊。

这个理论听听个大概了。然后呢有些小问号的话,先停一停,把问号放在脑子里,放到你的疑问的列表里。然后我们先去把API过完API怎么去实现,怎么去对应的,全想明白之后,然后跑它用sp追踪它。

然后根据我们这java的代码是怎么回事。然后他的API是怎么跑的,没事给它这个看明白,好吧。

同意吗?同意咱骚66666啊,来讲这个东西。好,你来看。首先回到我们java代码当中。java当中呢,刚才说了有NIONLO当中除了有channel,然后有be bufferffer的概念。然后呢。

它还有一个概念叫做多路复云器select。这个现在我要写一个服务器端,我先在你整个左一边这个代码。现在写一个服务器端这个服务器端呢,然后呢我还是那句话,主要你是server端,你要绑定端口号啊。

该做的事情做这个在这啊在这就是schan open得到了server server呢然后给它制成非主色。

然后呢server点绑定绑定到我们的9090这是绑定900该该有这个listen这个list就已经有了。list之后,然后再往下走,注意这种select,它就是select点op。

但是这时注意了lect点op的时候,这个行为你虽然在java当中所谓得到的一个se。但是这个java当中lect是我操作系统到到底到底是哪个多路复用器呢?它可能是你的select,可能是你的po。

可能是你的Epo,也有可能是你这个unixing当中的Q。嗯。我没了我把电脑走完,你就知道多久掉一次一port位了。那么得到了一个select依据形式,然后这几个我都会给你往下捋捋一下。

因为这些东西其实底层也知怎么回事的,只不过它他们肯定有差异。但是这个一套AP怎么实现的,我都给你列举。那么通俗来说,select open如果供在一po的模式情况下。

就约等于掉了我们一po create在那核里边开辟了一个空间。这就能理解同学一就是在的时候,这没有没有任何效果。他顶多在java里边进程里边开辟的一个空间。

未来你要存所有的ID未来调时候就给那核传就可以了。但是如果是易的话,那这个这个这行open的话,其实在那核里边开一个空间的就这么一个异而已。

那么代码继续往走刚是个上得了个serv listen一个监听比那这时候他reg注册注册到哪去了,注册到了这个注册的时候注意听有有差异有差异因为你不器你很多了。

你也不是经那个只是说就就知道NL这跟单词的这个这个这个小伙伴那和个和个。slect和po是一种多路复印器。Epo是多是一种多路复音器。那reger到这个slect的时候,如果seide po的话。

其实就是把这个listen的文件面符放在你jajava这个进程的空间里边了。并没有做任何的操作。因为刚才说这个open的时候,如果是在s po的话,其实就扎紧那边开屏空间。

未来攒单的那边服以被你调s来到后的时候,能一口气传给那块。那现在其实就是开始攒先攒了一个离森。但是如果是易po的话。

其实按理来说就应该把这个list森的文件面符传递到我刚才你open在那核可瑞的那个空间里去了。听我来说个一。就在不同的多路数据模件下,同一套接口,其实里层的忙的事不一样,但是趋于趋于结果。

最后最后都要做做那个那个那个状态便利的一件事情。那前面就是准备就in serverer方法里要做的事情。那回到star方向,一旦调起的话,你ser跑完上面跑完跑完之后注意看服务器已经启动了。

那这时候注意注意看啊,where to死循环。啊,所死循环每一次循环每一次循还做一件什么事情?没有执行eleCTL吗?添加进去不是CPL吗?艾特就往里添加嘛,对不对?先往下看先往下看。

上面这两个先不用管,往下走到这步,在循循环里边我多做了一件事情啊,再做一个循环wellwell里边做一件什么事,select select。哎,那slect这多西复文器开始调s,调select的时候。

注意它有返回值。那其实在JJDK的语语义当中,就是多路器查询一下有没有哪些曾经reger注册过的IO可以读写了,有几个是不是大于0。能理白什么意思吧?就是这个它的这是它的JDK的语义。

但是这时候其实JDK的语义,它是叫GDM虚拟机,最终是如何和我们的这个物理操作性内核挂挂上钩的。因为多了分印器又分为两大类spo和Epo。所以这个s的过程又分为两件事情。如果你是在slash后的时候。

其实slashslash就约等于调了slash或者调了po,把你在java里边注册的那个reger那刚才那那些文件面符作为参数传递给那个。这是一类。

但是如果你是这个这这个DVM启动的时候选择的是Epo的话,那这一行代码其实约等于掉了weightit。能该到同学来说个一。对吧这就是我说为什么一old wait约等于曾经的slect或po标用。

是吧这就这能ge到的点了。哎,那么当如果大于零的时候,当大于0的,就side返问结果说哎,无论调了side po,它阻塞一会给你返回了,还是掉了wa,然后那边最终给给那个有可能阻塞就能立刻给你返回了。

哎,有大于零有有有那么几个了。啊,你可以设置超时间,当大于0。有了几个之后,那么再往下走,在这个这步slect点点s key就是最终返回那个你不是告诉我几个了吗?那几个是谁。

然后他拿到之后在他身上得到迭代器,也是re。那这时候开始逐一便利你的每一个IO这个这个过程是要逐一便利你的每一个IO的。那么拿出一个IO拿这个K之后。

然后这时候看判断你从英了里你你关注的它事件是什么事件,他有可能这个是一个listen的,你可以接收它,有可能是某一个你建立连接的客户端,你可以读取的,这时候就可能会有不同的处理方式的。

但是在这里面非常重要。但是在在这里面非常重要啊。因为你要想成一件事情,就是如果是一个leaing的accessible或者是一个可读的readable。那么尤其在accessible的时候。

我们先说这个啊这个是最最最最重要的。就是你你是leasing的状态的文件面符那个那个server它有人建立连接了。那这时候在处理的时候,其实你要处理哪些事情。

我们跟您去看啊ac handleler把它可以传进去了。你要做一件事情,就是在他身上拿到曾经那个serv channel。后第一个接收这个想都不用想。因为别人来了嘛,你就是同步的IO模型。

你一定在程序里面自己去接收这个客户端,并且呢再给它制成一个非注册最重要的是你要把个客户端还要再做一件什事g个谓多器里。但是完就刚才是er注册现在客客户端注册。那客户端注册的时候。

其实跟server是一样的。如果底层是或模型。它其实就在DVM里边那个空间里边存一下这个FD这个客户端,以被未来你再调时候,能把它从用户空间传递给传递给内。但是如果是模型的话。

其实这个时候又类似于调一个艾进我们个的客户端内核里去。就是多路分析不一样,它的实际践逻辑可能不一样。啊,这个到现在能在代码逻辑上知道javaNL包中的sl代码编写逻辑了。你现在在看这个编这个代码逻辑。

是不是就不是说等于被动的别人嚼完喂给你的。你是在在这种审视的角度,我已经知道底层IO模型是啥了。你这到底怎么去把它实现出来的,我一定要弄明白这件事情,这感觉是不是出来了?😡。

大家都是在学习改两种学习方式是不是不一样?Yeah。实际的nty也是这么用嘛,1令I就是这么去。没有区别没有区别。而且它其实复杂了一点,它里边有一个现能值这么一个概念,我给你演示一下。🤧或头能分享的?

好好听啊,后边可以分享。哎,这个是从这这个代码当中,就是你为什么要去写无缘无故?就是有人说过啊,说其实用javaBO代码好写,你要用java的NIO去管理网络IO通讯的时候,代码写的好复杂。

又得干这事儿,又得干那事儿,你还得干这事。其实它停留在什么呀?就是不了解多复用这个IO演那个过程,只是停留在我要拧着头皮去学API好像这么写,好像这么写,开始死记硬背这个API。但是其实你要扭过来。

先学IO模型啊,把多多分器的模型学明白之后,才能做电研试。嗯,我给你最终吧,就是。我们再再来看一个东西啊。因为最后其实这两天你也发现了,用那个st追踪的话,反而更容易理解这件事情。

用哪种多路复文器是根据操作系统不同实现的吗?我刚才一再强调,像linux有兰po一po。像unix的话,它有kiQ,就类似于我们的epo,像windows有IO完成端口,有这个这个还有它的s。

而且slash是属于p标准的po标准就任何操作系统基本都支持slash这个系统标用。这种多路分印器。嗯。然后我们看一下啊,这有一个单线程的版本的,就是socket登录复印器,单线程那个版本的。

这个其实都是我前天嘛,还是周几周二的时候,还是我忘了周几了,讲正好VIP课讲完。里边的一点点。啊,这个就是我。它这个代码you select open,这个就是我刚才那个代码,然后今天做口是9090。

这里面用了slect,然后呢,代码当中会有一个。嗯。1那个是。小啲爸你好。这样给他去了。然后到这selectselect之后,然后我这是不是零了,就没有没有组没有没有这个没有一个。比如我50毫秒。

就直接再再让它循环一次,就一直在这阻塞的,就一直等到它这个所有代标当中最少有一个I有实件了,就可以就可以返回了,直接让让让代码在这阻塞啊,就并没有并没有让他去。有一个超时的概念。

我为了是把性标用帮帮你们追一遍,看他是不是这么去跑的,跟我那图得对得上,这是目的,向下走都没问题。应该不得。好,我们先跑一遍吧。怎么去怎么去做呢?down了C。第。然后再去要追踪了strs杠什么呀。

是不是FF所有现程杠Oout输出文件开头,然后追踪的是我们扎了这个程序,然后后边加了这个字典码是。好。cllan为什么要重新注册?cllan不叫做重新注册。cllan不是重新注册,注意看张图啊。

你cllan就是开始开辟空间,空间是空的,只有第一个有leaen,先把listson放进去了,完件没法符。当你得得到客户端,客户端第一次被except被得到的时候,他要第一次放进去,它不叫重新注册。

它只会注册一次。

走把这边跑起来。跑起来之后,然后我们来追踪了。能这个我在做什么事情,能能听懂吗?这个不需要重新讲啊。😡,看刚才那个大程序已经跑起来了,这个就是主线程,而且我那个里边也没有使用多线程。

就是11641这个out。那么1641里边做了哪些事情?VIout点1641。其实你只要在把这步走完,注意听啊,我想教你们学习方法,在座的所有同学,如果你这节课好好听,把我现在所有操作的事情以后。

你也这么去学习的话,你才能真的理解这个知是一件怎么回事。比如像现在我其实我也怀疑啊,他到底是怎么怎么执行。但是只要我把系统调用给它捋清楚了啊,你这个代码就就是这么跑,比说打开它。这里面我搜什么东西。

搜1个9090这个登录号。在成立当中,我是sber第一件事情肯定要建立监听,他他肯定是围绕我们90有办的,办的时候绑定谁绑定个4上4上肯定要绑绑定9090,且4上一定要开启监听。

上面一定会有一个scket的是要得到4,这个事儿我都不掩示了。这就是我画图上面说的前三部曲,无论哪种L模型必走的。

这个能盖造下来说个一。Yeah。

嗯。对吧这个有了之后,那跟着我代码所维逻辑走的话,那这个时候其实你有离的话,你要把它放到哪去,要放到我们Epo的一个空间里。那epo空间是不是一定会有一个epo create。

那Epo create在哪?我们来往下走一走啊,或者你直接搜,先记住他这是2899哈。😊。

以后。C。2872行,这是不是一个Epocurate得到了一个7。对吧得到了一个77有了之后,然后我们找是不是有一个EpoC条,中就就就就看看这看这啊。E口C条在7里边添加了,只添加了一个5。

除了有5的外,它应该还有一个4。但是因为咱们还有一个4。Yeah。是不去了。我再搜一遍整本啊,它是开辟两个吗?一个是。4。只有这一个我再看我再我再我再看一眼啊,这有一个,刚才不是他往里添加的是。

5、并6天4。半的。4到909年。切。我把原始的行像找到吧。socket,然后点儿。行。Yeah。等于4。小俊好,是2642号。IPV6得到了一个4。

咱们做笔记吧。平き?就是用户空间里面掉了第一掉了这么一个指令。

得到了一个文件描符4,然后再。还关闭了关闭的话,代表这个不对啊,这个这个这个四又被关闭了。4往下走。这还有个4啊,这个是IPV4的是内行。

是2802行,掉了这样一个,得到了一个4文件描4。往下看啊,除了得到它之后,是不是有一个Fc控制,然后看这个单词什么意思。

是不是非堵塞了?跟着我思路走啊,能看懂吧?这个前面客户是不是说过一个非组色,而且这个上面这一行,然后它然后这个非组色什么意思?这个非组色约等于我们GDK代码当中是不是有这么一个配置?

就是在so的时候,你是不是设置过?

他约等于什么?就就等于他。什么意思?是不是控制我们是listen,它是一个这个com blocking堵塞吗?fis不堵塞okK吧,接着往下走。

登了它之后,就是2805行往下走。哎,到这是不是要绑绑定和listen了?然后在这块的话,我就把它复制出来,后边不不复制了太长了。

根据程序的线性执行,在一颗线程里边下一步执行的话就开始办的绑定9090了。这在我JDK代码当中,其实就是在做办的绑定我那个炮的9090是不是对应上了,听我同学来说波一。

绑定完之后开始离升,开启了监定状态。

嗯。这个5十是啥?昨天一直有人问啊,这个其实在我VIP课里已经讲过了,这个50叫做backclo。

再搜一下什么是白浪。好,那再往下走,有了监听之后,往下走,它的易碰壳位以置。

哎,直行到28702的时候,ele create得到了一个7。

这个七直行到7的时候,执行到7,你你就执行到这啊,你跟我左边这个图比一比。是不是set绑定listen,然后呢epo create,然后得到了一个7,这个7是把指向这个空间了,这个空间是不是有了。

跟我代码这个图跟我代码,这个代码这用逻逻辑是不是一模一样?

有了它之后,然后再往下epo,再往下是epoCTL。但是这一步为什么添的是一个5,先不用管他们先看啊,把它啊就在这了。

他做了一个pa应该啊他是做了一个pa应该。这是在epoC调里边的7里边是不是开始做艾特添加了?添加的时候是不是添加了一个5,这个数值我说了,你不用管它这个数值你不用管它是不是添加了一个5。

这个五是怎么来的。但是我们上面是绑定listen的是不是4,这个四和这个5上面它应该做了一个。

绑定的一个pad的一个绑定的。五和6一个绑定。Yeah。看返回我。好的,第二。搜的是等号,后边有一个5。这是200多行,不是2600,在这儿open。healthy net interface这一个。

就这样。你整理。net65,然后得到了一个5,这是控制5,然后怎么找到它和我前面那个四是一个关关系。那是。这还clolo5了,clos4。四也被关闭了,然后再往下。我去看一眼这个文件描符,稍等。嗯。

GPS我们当现的进程是1640,对不对?啊。それよ。四是我们监听的,看有我吧,我说他是一个pad,它是一个对接的。这个五是和这个四是有对接的,就是他俩是绑定应该是绑定在一一起的才对啊。

5和665和6去绑定一个管道56,然后在7里边,刚才在7里边,我们只是添加了哦,我知怎么回事,我这道怎么回事了。

sorry算,这只添加了5,这个五是谁,先不管了,这个五是添加了这个一个管道,这个管道是要获取一个。县城那核一个通信的,这个先不用买,后边一定会有一个不不不着急,我带你看啊易炮。

少少跟了CTL后边一定会在7里边点星4。也定有这样的一个调用。看这了吧,只不过行数多了点,刚才2800个行,其实其实到这行这行才对,在epoCTL里边一定会在7里边epo艾4。

那个五追追追错了,五五不是啊,你就即便追了一个5,他后边是不是也依然是在后续当中做了一个在七里添加添加四四是谁?四是不是就是我们那个监听,这就对了。5不用管的551个pa是一个管道啊。

这是不是一定会把4天进去?没错,哎,源码这是会创建一个pad,的确会创建一个那这这这个到这步能看出来设微一就这样很很重要,就最终是要把4天进去。

天去之后,然后再往下走。嗯,把它添进去吧,然后再往下走的话。往下走到2906行来了,重点来了。

开始一波胃痛。啊,中间这些乱七八糟东西不用管它,做减法全部丢掉。最终我们梳理出来的,像paP那个也给它删掉。

是不是当我一个程序启动的时候,我把它梳理一下,公作左边图梳理一下,开始我程序启动的时候,是不是得到了一个4,并把四设成非主色,并把四绑定到登口号上,并把四接定起来。然后呢。

我是不是得到了一个7的一个个文描并里把进去之是是开始阻那是什么是不是就是我们首先跟图对上的话,就是程序肯定完成切三步得到7得到了一个空间。

然后呢并把这个这个7里边添加我们这个监接的文文件描那到我们个的时候开始给你讲,注意看我说这里面open了得到了如果是的话,这等于得到了一个空间。然后呢在注册的时候,其实注册了CL那调的候其实约等于调。

我是没有设置time out,没有设儿那过期时间的啊,没有设置时间,所以他一直一直会在这阻塞。就代码其实刚才。你要明白java代码,你能写出这么多来。

且现在你知道java代码的执行逻辑也应该是这么一个逻辑。其实你也看到了java代码底层是真的这样去执行的。而且你相应的这个代码的这个底层这个调用,你还能给它切出来,已经已经到位在这了。到这儿现在不懵了。

能听懂同学来设个一。

很清楚吧啊就是从开始学理论啊,学到GDK的使用,到最终它的这个这个应用。

嗯,往下走啊,咱们还得看客户端是不是还得注册进去,这是2906哈,这是一个位子紫色了,我把它关掉。😊,用tel这种动态追踪的方式,outt点1641。动态追踪的方式赶紧走。那么是不是动态追踪的话。

这文件刚才就组合在这就就就到这儿。那么因为前面是没有人和他建立连接,对不对?那如果我一建立连接,代表着这个epo wait epo wait在做一件什么事情。

其实epport wait就在等这个空间有没有东西,我可以去走。但是目前来说是没有这些东西。

因为没有人建立连接,也没有人发来数据。连第一个客户端都没有的,是这样的,是这样的一个状态。

那这时候如果我标击和这边建了一个连接,连接进来之后,那这边wa可能就是因为有连这个这个你想建了连接嘛,肯定会产生一个事件,这个挪过来,然后wa了才会有返回值。

一步位的就有返回,返回的时候就可以执行ac,对不对?哎,那这时候我们来做一个演示,连接一下NC local host。

9090能能听懂我想做一件啥事的来12波一。好,走先看啊。第一个这边是不是新的客户端,53687进来。那一个连接过来的话,一定会造成连接建立连接这个事件,这个事件一定会被谁捕获。

被epo wait来捕货。我们找上面刚才那个一po wait。就是开始我跳的时候,十行往下走走走,到一po位的这T加4,然后到这时候开始阻塞了。阻塞之后,然后看我找连接进来之后,谁产生事件了。

是不是产生了一个Epo in的事件,就是输入端的一个事件,这个这个in一po in既可以是建的连接,也可以是这个数据到达。那是哪个文件描符呢?是不是4号文件面符,四是谁?四是不是我们监监听那个文件描符。

看这张图。

是不是四就是我们监听的,你是不是刚把4先进进去,一位的时候,是不是在这个wat返回的地表里边,是不是收到了4有一个事件,这个事件是不是就是in?

对吧那么进到进到这个in之后,再往下走,那你有这个事件了,那下边我们代码要做件什么事情,是不是要接收这个从四上就要接收这个in的事件,就接就叫accept这个这个4。所以你代码往下走。

它就一定会有一个accept。是不是会except在4上去接收一个新的客户端,得到了文件名从8。

看懂了吧?就代码执行往下走的话,那这时候要接收接收得到一个文件描8,我把这个相应的没用的给它删掉啊。得到8之后,你现在告诉我,如果excel得到了一个8了,在我们这个多数器的在代码中得到了一个文件门8。

得到了一个客户端,下周应该执行什么东西?😊。

下面应该做一件什么事情,把八给添进去,对不对?所以这时候往下走。你就一定会看到一个。这是我屏幕打印的,也现在打完了EpoCTL在7里听见吗?刚才我有人问,那,如果新的连接怎么贴进去的。

代码是不是这么往下走的?

龙是不是又把八听到七里去了?那这行你要真正的明白,当这行执行完之后,请问。请问七的空间里有啥回答?没错,有四有8。

能学到这儿就很聪明了。所以这时候在epo位的时候,为他在为了谁为在7里边为他那个4个8,到底未来谁会有事件,谁有了光能就返回了。所以下面继续执行epo位。

e wait一 wait随着有新到达的就添进去,然后接着一 wait,随着新到达就添进一 wait。那中间ee wait有了结果之后,到下次e wait之间。

就是你所有的接收和所有的数据处理的这个这个这个这个时间线。那在这儿也可以得出一个结论,在这个wa和这个wa之间,如果隔得很久,十年执行了时间代码才到这个。

系列 2:P62:0.7 netty如何解决粘包拆包 - Java视频学堂 - BV1Hy4y1t7Bo

wait,那其实weight里面那些事件,红的菜都凉了,能听懂我这个小意思的同学来刷波一,所以要做一件什么事情,所以要做一件什么事情,如果我这个程序你发现比如在这个wait wait得到一个事件。

我不是accept,我是要去读取谁的数据,但是我读了好久,读了好久,读了好久,读了好久,一直在读,一直在读,然后读完出来东西一直处理,一直处一处才才能轮到下一次轮选择一个位置。

那这时候其实你这个程序既负责了io的读取,又负责读取后的计算,那这时候其实我们可以把什么呀,这个程序尽量的做什么呀,只是把该读的东西读出来之后,或者把这个读取的事扔抛给另外一个现场。

不要阻塞当前的接收事件,建立连接这个事儿,那这时候其实你能听懂这个,你再来思考一件事情,我给你佐证,你曾经学nt的时候,或者你有信心想去学it的地方,放弃的时候,你是不是都看过第二个图形。

什么这个reaction,这两张图是不是都看过啊,有的说什么这个连接和建立我们可以打到一个县城里边去,然后有时候我们接收的和连接的可以是两个数字线程,tom cat,是不是也有这样的一种说法,对吧。

就像刚才有同学说老师你给我讲这个i o这个selector,那net底层是不是这么去写的,其实现在找有没有找到感觉,有没有找到感觉,对不对,就这个意思好吧,ok那一炮这块我代码也帮你追完了。

从原理原理啊到画这个模型。

然后呢到带你追这个a p i啊,他为什么这么去写。

和底层的怎么去对应上呢,一到最后咱们验证这块都听不出来,说略略,学了好久的nt还是没学会,就是因为你对底层io这块不太不太不太懂,不太懂。

好这块能了解之后,那我说的nt了,咱们上演nt看一眼好吧,io这块没啥了,其实io还有很多的知识,你可以看看在vip里边有单线程的,其实还有一个多线程,多线程这块看造化吧。

因为这个东西如果是咱们这种训练英文公开课这样的一种想法的话,他其实来不及讲那么细腻嗯但是呢我给你尽量的去展示一下,展示完之后我们再过nike的话,你可能会有一些感觉,老师ctrl是谁监听。

谁没看挪那挪的那一块是内核去做的。

就听啊,你要真正理解这张图,分钟我说这车呢这是内核挪动这块,挪动那块是内核这个那那核怎么去做的,你要相对的就是我前面说的,要对自组的制有点了解,你如果入学到咱们咱们咱们的课程的话。

其实在我讲i o讲那些东西之前,你看在我讲这个相应的i o之前,讲到io多路复用器dnt这个过程当中,前面会有pc,然后会有这些东西,而且还会有马老师的相应的计算机组成的一些知识。

而这些知识第几节课你把它看完,看到这个多隆重器的,那才能真正的理解我在说什么事情,如果你还不是计算机相关专业的话,那块听的确有点复杂,但是咱们一层一层的来,一层一层来,那如果没有祭祖。

那没必要先去补剧组,那你就先听我这节课,就先听到我这个这个这个层级,起码你知道哦,我缺一个知识,缺什么去祭祖,我对底层还不太了解,我起码现在还上,我都懂了,我现在就一个小问号,这个消防证他怎么过去。

到这感觉了吧,就他怎么过去,你还不知道,那我也告诉你不,那不是可以把我的课前面那个课看完就能懂,但是但是你要看这个课的话,肯定是要报名去学习咱们的课程啊,那是另外一回事,但是我可以告诉你。

有地儿能把这东西讲得特别的明明白,那为了保证你们能多学点东西,在这个这么一次短暂的一个两分钟的训练,在训练营里边,那这个事先放一放,我把后边给你穿起来,刚才我们是讲了多路复用器。

是用一个线程使用一个selector,那这时候我在为了给你讲了个一炮,这个讲的nt就是nt这个reactor这个模型,其实我要告诉你一件事情,而且给你让你亲眼看到一件事情。

就是selector selector,他是可以有多个的,目前来说刚才我们的代码这个api当中。

第一版代码当中是单线程切单c ecture,其实我还有一个多次electr,可以吧,那这有一个问题啊,这有一个问题,我为了讲这个版本,其实我要问一个问题,那么如果像刚才的代码,我只有一个select。

那这个select负责了哪些事情,能不能理解我的想表达的意思吧,中国想上这节课,你多学一点,所以你尽量跟着我的节奏走,有一小问号啊,可以先放一放,如果真想解开的小问号,一会儿咱们可以聊聊买课这个事。

这个课程可以肯定可以保证他先跟着我们节奏走,来告诉我这个当前这个这个这个这个模型当中,这个代码当中,这个塞拉斯做了哪些事情,没错,既要等着建立别人的连接,要别人读写的事情多大都由他一个来处理的。

一个来处理,那这时候如果连接数很多的话啊,有1000个1万个10万个有很多连接进来了,注意听啊。

注意注意听,刚才我我那个讲那块是挂上钩的,如果你这个一个位置给你返回了好好多好多事你要处理,所以在下一个位置之间是不是会加大了很多很多复杂的工艺处理,所以你为了一个位置之间的距离越来越远。

越来越远,时间越来越长越来越长,那这时候其实你可以怎么去想这件事情,假设有1万个连接,我可不可以就是这个计算机系当中啊,我一个成语里边可不有两个c或者三个或者四个或者十个。

这个selector就负责这一批在一个cpu上,一个线程里,另外一个selector在另外一个线程,在另外一个视频上负责另外一批,人家没有符,然后专门我可以找一个县城拿一个flag,就负责建立监监听。

建立连接的一件事情,这个这个过渡想想要真的去想啊,是不是应该是可以的,对不对,不光是可以,我给你看看代码,你比如说啊注意看,比如说我这段情节我准备了三个select。

那我未来不仅要准备三个fletter,我要把三个ft放在放在三个县城里边,能理解什么意思吧,这个代码不是不是nt,就是我从用java代码去写的,用三个select,然后三个材料全都打开啊。

在堆里面变成对象,就全部打开过中间直这个支起来,然后呢我准备一个server,这个server的监听960跟刚才一样,只不过刚才那单单线程单词来着,现在多线程多次来着,有了三个之后,然后注意看。

我把server注册上去了,我把sr注在其中的一个就踩踩了一身上去了,能不能理解吧,就通通过注注到cl一生去,注册完之后,然后注意看我主方来做一件什么事情,我准备了三个线程,我写了三个线程的代码。

就是下面的类里面这三线程我先梳理一下干嘛,我把三个线程跑起来,第一个县城里边,我把这个这个slider一放进去,第二个县城里边把sa放进去,第三个我把三放进去,而且他们还有一个概念不一样。

就是第一个县城里边除了有一个cs 1,还有一个数字二,这数字二是什么意思,也就是说你这县城工作的时候,你在select上刚才注册谁,是不是注册了一个server监听路人。

那你这个这个县城里边的select是不是可以得到建立连接的销售量,那建立连接是不是只有accept可以得到客户端,那得到客户端,得到的客户端应该注册到哪个selector呢,向他注册一个。

他向他注册一个,再让他注册一个,再向他注册一个,到这一步能大体能听懂什么逻辑的,来刷波一,那这样的话如果我是多核操作系统,这三个线程就可以跑在三个cpu核心上,那么一颗cpu就是疯狂的去建立连接。

和别人把建立的连接都轮询的丢给另外两个sdc的身上去对吧,然后让他跑起来,那这时候其实你关注的时候,我ios ride里面的逻辑,那么n l sy里边逻辑就是看它有两个构造,一个构造是带n的。

一个构造是不带n,然后这里面我用的最简陋最简陋最简陋的方式,但是最简陋的代码应该最容易理解,首先select为了接收的,然后这准备了一个thetic,一个select,原来是一个零。

后来传唱的时候我给它分成2/2分之二,然后这里面有一个i d i d为零,这个这个信不管下边还有一个准备了一个东西,叫做blocking q阻塞队列啊,一个q组队列组队列是放什么东西的。

因为你有一个接收线程,未来向两个线程去分发,进来了个客户端,那你那另外的线程忙不忙呢,我线中间通信或者线程间数据传递,我用一个block通q就一个q,而且他会看它是一个数组数组。

也就是我主线程里边给下标为零的,那就是给0号线程的那个斯莱特下标为一的另外一个线程啊,这是一个对立,然后下面一个py这个integer的一个id id叉,这是作为一个两个这个工作的两个selector。

他们自己那个线性增长,这个id用于为什么上面这个带两参的构造方法里边,我把select传进来了,把二乘进来了,然后q的大小这时候就等于二了,就等于二,有了它之后,然后注意看for循环。

然后这里面i然后i等于零,a小于就是小于201,然后这里面开始购到初始化这个new blueq一个对象,到这个这个数组里,这个boss就启动了,就启动好了,这个主的一个线程,第一个线程。

另外两个工作线程,他们只穿slash,但是从slash的时候注意看,他们会掉自己的这个这个叉叉的话是一个静态的,他们有这个形式增长,所以一个人就会增程从零,这个111个人会增程是模磨取取模取二。

一个人就磨成了零,一个人就磨成了一,因为这个魔术值是2c的数量,那就是两个工作线程的i d,一个人是零,一个人是一到这个不构造,能看懂同学来说一说为什么这个赌这个线程的线程,那个写了一个线程的一个类啊。

其实有时候往下看,主放运行运行的时候,其实这个运行起的话,三个线程都会跑啊,注意听三个线程都会跑,那三个线程的话,其实只有第一个县城里边的csselect里边有东西,因为只有第一个现成的。

第一个是这个第一个cm里面注册了一个例子,所以他在这selly的时候,然后看我做了一个十秒睡10ms,这么一个一个一个睡眠阻塞,然后这一个死循环就是一圈圈转一圈转一圈转只。

但是只有第一个县城那个主的那个塞拉斯身上有可能大于大于大于零,能理解吧,因为这是个复用代码,三个形式都会用,这里面如果答案零的话,第一个自然的生存就会得到一个exce accept。

之后就接收一个客户端,关键是看接收客户端啊,当接收客户端的时候走accept tember,接受一个这个论证,肯定是得到一个新的脱单,得到新的投资之后看我主要看下面这件事情是随机分配,随机分配。

看玩哪个对哪个哪个队列去分,就是向另外的哪两个slider去往那个点去放放了一个后端,这就是当前如果第一个只有第一个现成的select可以得到一个exceo事件,写自己的接收的行为的里边。

需要把这个接收的客户端丢丢丢丢里边,好让另外一个线程能知道有这个客户端的存在,到这一步能听出来说的一,还有一大部分是能跟上的,就是这个这个跟不上的,这个就先先小忍一下,先小忍一下,那么给丢到这里之后。

那这时候其实再来看上面这个while循环,为什么是一个组这么一个一个一个一个死循环,选择设了一个10ms,刚才说了,第一个主线程里边他注注册了一个listen。

那另外两个县城里边是不是selly的时候永永远得不到大于零,对不对,但是这就会有会永远堵塞,但是我是一个10ms,那就另外两个人都有可能把这行代码跳过,就这个while循环得给他跳过,不执行里面的东西。

而从而执行到下面这个死循环里边,也是这个死循环里边有两件事情,做一件事便利来的事件,另外还有一个关于任务的处理的运动环节,到这一步能听出来说明一,这个代码写的极其简陋,简陋代码其实相对容易看一看一些。

所以在这部代码里边循环里边,如果另外两个线程还没有任何的这个客户端住在死人身上,所以他们会跳过来的代码到下面的时候,他们会根据自己的这个q来取出所谓的所谓的客户端。

并把那个客户端注册自己的select身上,换个太老了吧,听明白没听明白,是不是就是开始分发这个任务,对不对,对吧,当这个能听懂这代码有兴趣的你可以自己写,然后下面跑我们来看nt。

来看nt那代码我带你走一遍,有对一个原始代码的一个印象之后,然后再那个那个没跟上,无所谓,重点重点在这儿,重点在这,nike,你们尝试都去学过,你们曾经都死记硬背啊。

第一步我得写第一行代码叫new nl event to look bro,然后呢后边要跟数值或不跟,请问这个数值要写几个,请问这个数值要写几,写一写五行不行啊,再往下走啊。

然后我是不是还可以在你有一个是不是得这个返回值,其实就是这个类型,你要而且还特别的根据你网上查的东西,可以管它叫boss,对不对,对不对,你还得给他起名一个boss。

然后是不是你还得再用一个nl group,然后呢后面写,请问这个要写几个,写几个,对不对,唉不管怎么样,你你你你有通过通过不同的学习,你这个事你也没弄明白,应该写,不管怎么样。

访问者你管他叫walker的,然后这个听完之后,然后注意下面是不是你要跟a a i的规范,你说new一个server boot strip,然后得到一个boot。

然后注意下面到了不点group里边是不是要把boss和worker放进去,是把boss和worker放进去,然后这时候其实你要把两个都放进去,那这时候请问我放一个行不行,我放一,他不给,是不是也可以。

那放一个的话,那请问第二个会用到吗,是不是第二个就用到了啊,那这里面到底什么是grp,他这到底做一件什么事情,注意听我给你讲明白了,第一如果在现在这个东西就是把下面的行给他助教,不用它。

如果你只用了一个i o mtt group,然后在这里边传了一个一,注意听啊,如果传了一个一,且将这个group这个线程组这个group放到了boot它的grave两个参数位的话。

那代表着未来会在一个县城里既接收又读取,就是咱们开始写的这个single thread版。

只有一个slider在上面,既要做读写和接收。

他只有一个select到这样它就是一个逻辑关系,能关联起的同学来说一,然后如果注意听,如果我把它写成一个大于一的,比如写成三,那在三的模型下是一个什么概念,如果这为三,并把这个boss付给了两个参数位。

这个是什么意思,他这种模型下是什么意思,也就代表着未来会就是我的这个这个并不是我这个多线程版啊,是我多线程版的另外一版,我现在这个多线程版当中是分工的,谁就对谁来依旧负责接收。

剩下两个是不是就是工作就是读取对,那像刚才我这个代码,如果这写成三的话,然后把这个boss放在两个位置,其实实现的是由三个线程,其中一个线程接收和读写,另外两个是读写,就和咱稍微一,对吧哎那在变化。

就像这一种这种就是在一个你一个i o一个gal作为承担的时候,这种场景两种情况要么为一,要么大于一的情况给你解释完了,那么这时候再把它扩展一下,看一下,这时候变成两个了,那这时候我一个穿boss。

一个传walk,from work,那在这种文件下,其实就是我的多线程版本,就是分工版,分工版分版,前面boss注意听,注意看前面那个boss,你这写几没有意义,如果未来你只监听一个端口号的话。

未来这个代码未来你绑定的时候只帮一个端口号的话,那么这时候你写体没有意义,在这个所谓的group里边,它只会有一个线程,你写三写300都没有意义,他只会有一个线程拿来。

而且他只做access接收第二个参数为这个worker,这个线程里边你写多少,那么就有多少个县城未来会跑起来,他们只做读写,而且是由这个gal里面的一个县城轮流的,或者按规律给它分发的这些work。

分发这个所有的连接,病毒来刷波666,对吧,那那这样的话我们来做一个啊,做一个小小的一个演示,是不是这个概念是概念,比如说我在boss里,我写了博客里边三,那到底是未来是不是有三个线程的。

然后这边我写一个,这写一二吧,上面写二写小点的,上面一个二,下面一个,那也就代表着这个程序现在boss里有两个线程,worker,两个线程有什么定义的,那么这个这个代码跑起来之后。

到底一共有多少个县城boss写大于一的没有意义吗,你在下面看你绑定多少,你要监听多少个号,能明白吗,就监听端口号,这个事儿是要压到上面这个select去的,好,有人说了,你已经说了,是三啊。

他就这么跑起来,跑他之前啊。

我们做一件事情,找到你的,c盘,然后找到你的jdk,就直接的方式,最傻瓜的方式,然后呢它有一个b,然后它有可视化的一个工具,哎呦我这个鼠标的慢好了,现在他看到了一些我们这台本机跑的gbm这个这个进程。

然后把尝试把代码跑起来。

先听的是9090,对不对,把它跑起来哎,跑起来之后是不是多了一个,比如马士兵cni o nt l o双击它,然后看线程,这里面线程我们来看一眼,跑起来了没有,找nike这个。

看他刚运行起来是不是多了一个n o do,比如我二杠一的圆啊,有这么一个线程啊,那还有没有啊,然后这时候我们开始建立连接,手抓啊,现在有一个了,然后再来一个连接。

nc连的是我192。168。150。1t i7 的,然后90999有四个九。

因为那个考了四个九进来之后,然后除了他是不是多了一个nl,因为tgp 3杠一上面组二里边只有一个线程,组三里现在多了一个县城,能看懂吧,哎其实这个过程是主二零那个boss给walker里边开了一个。

而且你也发现一个特征,就是随机连接它的一个线程会创建,然后再来一个连接,n c然后标准2。168。150。1。

然后99994个九,在三里面又分配了一个,这就是二我在boss那个worker里边是不是定义两个线程。

如果再来一个的话,现在就不会多了,哎没错,再来一个这个互动感是不是有了,你想你就是蛇头油,是不是有很多问号的没你如果未来这么玩多好。

还多吗,现收税不多了,所以也没有使用boss那边的县城去站出来,其实就是扔在了这两个县城里,对吧,能看懂的同学能干到这个这个本质和精髓。

同学起码这个nt入门这块你是明明白白的入门的,不,但是你要get到这个点啊,这个点这个点是是我讲课好吗。

不是是你找到了一个学习方法,就是从最开始很头疼的把所有事情捋清楚了,你知道了这个东西就是这么一个原理。

那么越往后摸,越往后摸,这事你都知道怎么回事,他不是要给你教明白,对吧都给你们看一眼啊,多给你们看一眼,就是因为刚才在这个一破位的,这其实以前我也给大家演示这么一个事,情,追踪一个事情。

后半音乐给他结束,加上一个资源。

再来给你演示一个想听吗,哦我这有一个nbx,像用e poo啊,像使用多路数学器e po的地方都有哪些呢,像n ex里是不是用了一炮了,我再给你讲,release是不是也用了,等一下让我来。

我找一台release,release,我这台是,没有跑,这边的话,他endx没有跑起来,有没有好啊,这这不对这不对啊,我是说这个第一台,第一台是没有release,那在第二排就有。

上面写的我们先来看endx,看mix,那么现在请问endx有没有用e poo,那他e po是怎么去用,怎么去用的,那现在我想知道我你想知道这件事情可以怎么去做了,有没有用,它怎么用的。

你是不是可以去到sb目录当中去追踪它,启动了一个进行的所有的追踪的过程,是不是可以用rts到ff杠all out,然后运行本机的index走回车,当前目录好诶,他跑起来了,他他跑起来之后。

你只需要去茶叶,这里面有三个i d18101811 和1812,js杠f grape endx,这里面呢注意看1811是master,1812是walker n这个词。

懂的同学应该知道你的worker可以用多个method,只能有一个能理解我什么意思吧,啊那第一个其实是一个过渡的一个线程启动的一个建筑,那我们来看一下哦,点1810,看到最后还有一个退出啊。

看到最后他一个退出,那这里面我们来搜寻一下,不用说直接在上面可以看到它上面是有一行代码,就在第一个进程里边,他已经做了一件事情,绑定6号文件描述符到八零端口,就是n这个词是真听八零的。

你看到了一个文件名是六被被监听,然后绑定到八零,就是你观察的第一件事情,所有server前面一定有这件事情,然后再看2。1811,打开181的时候,注意181是一个master。

那么你一定要明白inx master做些什么事情,你看这行代码。

这个视频里面的代码只有22行多吗,这里面有所谓的e破create吗,没有master只是负责接收我们的相应的信号,然后来维护热更新热部署,然后重启我们worker监控。

监控这个worker的这个健康状态对吧,这是nbx它的进程的分工分类的一个特征,那真正干活呢其实是我们的worker,那就打开vi out,点18121812里面会发现这这里面的代码可能多一点。

到23行不关的问题,我们来看看这里面做一件事情,e pc d到八里面添加了一个七和e pc添加六,这个八里面添加了六,刚才六是谁,六是不是刚才在第一个技能里边开辟了一个监听,这个八是谁。

是不是e破水位得到一个八,这个有没有用e炮啊,用了在这看到了,且他是不是在用io的阻塞,对吧,先把这个特征记录,现在能看懂这些东西的同学来刷波666,我带你看另外一个东西,release我给他填一下。

听到了cs到s d和我同一个id,有380不用管,我跑了一次机九还是用stress去追踪到ff杠o2 ,追踪谁追踪我们的嗯,我直接把它跑起来o p t。

然后bgrid 5里边的定下的realis conserver,把这个程序跑起来,且加载配置文件a g c,然后会有一个redis通路线,一个6379的一个配置文件,后边这个就是redis启动的过程。

不用管,最终我是能够追踪到这些个记录的,我把这个前面文件,因为在当前目录啊,我前面加一个realready is out这么一个文件名,然后走跑起来了,能get到这个点吧,哎release跑起来了。

看是不是跑起来了,没错,跑起来之后,这里面会有一系列的redout的现成的记录,对不对,后面这几个不用管啊,主要看前面的主线程,worker线程,它是单线程,单worker result,1335。

好了你们告诉我第一件事情做什么,来互动,我想教你的学习方法,现在你要做的第一件事情是什么,等会多少6379啊,大哥你要先定1~6379才对啊,他在绑定到6379去找到那个位置。

是不是你因为你要知道这种类似的那个文件,找到那个文件密码符,它是不是放到了io create里面,对不对,那六是什么意思吧,哎先找绑定里边是不是保他诶,他绑定6379,他在谁身上吗,是在六六。

是不是listen,对不对,然后这时候六,然后listen这个都不用管,你看六字哪来的,是不是从上面来的,那在网上看多看一眼就看到了,他是不是也epod到了一个五,五是一炮,六是listen,那往下走。

对六是不是做了非堵塞,然后再往下走,然后下面多了一poc t l在五里边是不是添加了六。

对吧,听完六之后,但是但是重点来了,看这个文件怎么1万多行了,关闭它,现在记住它是10370811031130,又变又变大了,而且你用tar杠f reits out。1335,你看到了一个什么现象。

没错,这就是设置的time out,这个就是设置了开帽子,因为他要一直循环一个,为什么,因为它是redis是单线程,它是一个单线程,他在一个县城里边,他不可能在这一个紫色的,有人发了消息,他还工作。

那这时候像l l r u fu的内存淘汰啊,它的持久化呀,它的一系列的事情就来不及做了。

系列 2:P63:TCP合集:01,TCP,IP应用层协议原理 - Java视频学堂 - BV1Hy4y1t7Bo

我们先讲先讲课好吧,io是网络通信的,你nl要站在哪个层级去聊,想想聊io这事儿的话,你也可以找机要,之前讲专门讲过一个i o的课程,从b o到n l o到e poo。

多复用ni o站在操作系统的话是非主色,站在jdk的这个api里边,是新的io系统,啥录屏软件,这个就就就别来了,想看看码来看,没关系,二维码一会儿如果出现了,说这二维码加不上人了,我待会儿给你换码。

你们直接就说你说老师诶,这个二维码加不上了,你就告诉我就给你换一个二维码,二维码多了去了好吧,好吧不说没用了,我们开始讲课了,真的要开始讲课了,这时间就浪费了,别着急啊,我们学学东西就怕碎片化。

通过你们现在聊天也是你过来听一节课了,然后问的东西很多,就怕碎片化嗯,你学东西其实时间成本是有的,比如听一节课,我在这,如果东东说一嘴吸出一嘴的话,其实这节课你下课之后什么都没有,没有没有学到。

因为你不体系,我强调的知识要成体系,就是你要拿出两个小时的时间来学习,那你就踏踏实实两个小时的听一个人讲,也别东串西串的成体系,量了之后,你来评估这俩小时你是不是学到了一个比较完整的通透的。

从上到下的一个整体的一个东西,即便这个东西无非你感兴趣不感兴趣,但是只要有一个整体性的话,那么这个东西在你未来的学习的条件反射当中,就会起到相相相对比较重要的一环,就是知识要成体系。

而且它体系的东西要支持条件反射,条件反射的意思就是让你学别的东西学得更明白,认可多人来敲门,六,思路很重要啊,那么今天我们要成体系的学一个什么东西,一定要成体系的学,这个要学的东西就是tcp通信。

我们要把整个的网络通信的每一个环节走通啊,然后对socket要一个正确的认知,为什么,其实学他你为了条件反射,你未来要啃了一个非常重的一个骨头,面试必问的关于io这一块的。

尤其关于网络i o这个这个点是必问的啊,如果你要在学这个架构方面的层级的话,那么你肯定负载均衡,高并发等等,其实离和这个链接都是有一定的,就是这个网络网络通信链接是有一定的关系的,没错。

如果你想把nike学的很好的话,这个这节课也是必须要听的,这是这个重要程度,那么收那么回来进入主题,那么讲到网络通信的时候,有两个东西录屏了,有有录播,有录播,别慌啊。

第一个东西一个单词会叫做osi 7层参考模型,一个叫做tcp ip协议,那么其中三个模型是一个虚的东西,分了它只给你分出层次来了,并没有落地的这种开发成这个成品的东西出现。

那么tcp tcp ip协议是一个已经是协议级别的东西了,相应的内核软件啊,程序标准参数一大堆东西已经出现了,那么要研究的也是关于tcp ip协议站里边的啊,从这几它的划分层次也好。

然后它里边实现了相应的协议,具体的细节,那么在七层的时候,先说一下,有应用层,表示层,会话层,传输控制层,网络层,链路层,物理层,那么这是一个七层的一个东西,到tcb的时候就缩减了,就变成了应用层。

传输控制层,网络层,链路层和物理层,那么为什么要把它缩减一下,其实应用层到表示到绘画的话,这个其实都是我们应用程序要去做的,因为不同的功能的软件,你打游戏也好,你访问网页也好,你聊天也好。

其实他们里边就是在这个三个里边有区别,但是无论是你打游戏聊天,它下面的东西是比较趋向于稳定的,所以这两个层次又划分到两个空间里去了,一个空间是交给用户的程序,就是程序员去开发它。

完成这个应用层的一些协议的使用和这个逻辑的开发,另外一部分,无论你是你是什么软件,最终你们通信的时候都得牵扯到传输里边,我控制他怎么传输,然后网络当中怎么去寻址,联络当中怎么去传递的一个数据。

物理层以什么样的特征去把这个这个高低电平的东西,变成一个实际的信号发出去,下面的这些东西就就到内核层了,因为一个计算机有一个内核,但是上面会有不同类型的通信的程序。

这个划分层次又划分划分到应用层和内核两大层次,这个能听出来刷波一就是你要从高建瓴,从宏观一直往下看啊,然后我们会展开细节,先不展开太多的细节,从这两个层次分工来说,我们来演示一下,想给你秀一把。

演示一下,常用的举了一个例子,注意看啊,我们可以用一个指令eec,然后呢模拟一个什么场景,模拟一个这个百度通信,就和百度请求回一个页面,我现在是在一个linux操作系统里边。

然后执行了一个ec的一个指令,然后准备了一个八数字,八八后边大小于号,这个大小于号代表的是输入流和输出流,这个一定要跟着听啊,因为你要明白,其实在通信的时候,通信是双向的,有输入输入两个方向。

如果有点知识的话,然后你可以间接的条件在这推条件反射一下,比如说你在学习jdk的n i o,就是新的i o这个这个这个这个这个接口当中,你知道有一个东西的channel啊,channel就是通道。

channel的话,之前我们用java编程的话,你有输入流,输入流是分开的,是分开的,但是有了这个新的l o t之后,他把输入输流合成了一个东西,一个抽象的channel,这个channel既可以读。

也可以写,听同学来说,二不一是这个意思吧,就开始原先的时候明显对象把输入输出两个流分开了,但是现在的区域给它合并到一起了,这样的话其实一个china代表了一个socket,如果我多说一点的话。

就是一个china china代表一个socket,你只需要传递传递的一个channel,未来的读写他们是绑定的,因为就来自于这个客户端的读和写,八是什么,在java当中你可以用一个对象啊。

就代表一个channel,那现在在操作系统当中,我现在用用用用的命令行,他用了一个数字来代表了一个输入输出,两个流,你就理解成它代表了一个channel,这个channel指向了谁。

后面呢给出在操作系统一切接文件,比如说在dv设备目录下,同一个tcp的一个模块里边,你要给出的是3w点,百度点com,然后是八零端口,看上去这是一个文件的路径,其实这是操作性内核。

一切接文件它有几种文件类型,普通文件块文件,然后字符文件还有socket文件和管道文件,那么这个路径看似是一个pass,但是它其实内核会把它转成一个对百度80端口的一个tcp socket连接。

那么用了一个八就指向这个连接,从链接里边可以拿到输入流和输出流两个流,你就想成八就是一个channel,只不过现在我们用jdk没有扎过去写好吧,而且我这就是用一个操作系统,用一个指令来完成。

回来之后什么事情,还有这个网可能有问题啊,哎我今天这网的确有点卡,不管怎么样,回来之后啥事没发生,但是这个八就已经存在了,china已经开启了,那我怎么去用它,刚才这一步注意听是和百度建立的连接。

有了连接之后,有了socket之后,我们是要通过socket去和百度通信的,发送东西,读取东西,那这时候其实现在其实就属于用户层次,因为连接传输这块儿已通道已经建立好了。

那么应用程序我需要和别人去说什么话,那这时候每个层次都有协议,在应用层的协议当中有http协议,有ftp协议啊,有s s d协议,那么现在和百度如果请求回主页走的是htp协议,对不对。

哎那么hd p协议什么叫协议,什么叫http协议,其实协议就是约定双方我们说什么话,说什么语言,如果写信是以什么格式,是以什么文字,是以什么字体,字符串怎么封装,能理解什么意思吧。

那现在如果我现在和百度已经有链接了,我要给百度说什么,他还能听得懂,那就一定要说一个hb协议,a b协议,我先打印一下字符串,它的标准是怎么封装的,先打一个字符串。

这个字符串里边a b协议规定了请求头需要给出一个方法,比如说get空格,必须用空格分开,应该要做spa切割,然后给出一个ur i就是资源斜线根目录主页后边再用空格切割,然后他要给出。

因为h b协议协议有版本号,你要给出的是h ktp,比如一点或者1。1的一个协议,关键是a b协议还约定了,你必须在琴头的第一行后边要加上一个杠n换行符,因为整个一个请求头里边可能会有很多的头。

里面会有很多的行建设,对他是用先用换行符去切割出很多的token,在第一行里边还有用空格去切割出方法资源和协议版本号,这个能听出来说一回收的话,我们先诶人工就是有应用层嘛,有应用程序。

有人我可以组建一个字符串了,但是这个字符串是打印在本地了,我需要给百度发过去,而且发的时候这个斜线n啊,它是要变成一个换行符的,那么这个eq是打印,就跟csc点奥迪a一样,它可以接受加一个选项参数。

更e小写的意义就可以识别这个杠n杠n就识别出来了,这就符合现在就符合hb协议的文本的封装了,这个文本协议稳定之后,你要发给百度,那么echo打印的话就不能打印到屏幕,也要让它的标准输出。

一是标准输出重定向到八,这个八就是那个对百度那个channel那个文件描述符,这个八啊这个变量上,但是后面如果是个文件描述符,你死记硬背就必须要加一个and的符。

那也就是让echo的标准输出只传递给了同定向,到了八这个对百度的socket channel里边去回车加机,这个东西就发出去了,那么这个是符合ap协议的,百度应该可以正确解析它。

解析完之后就发现你要请的是这个主页,对不对,那你要请求主页的话,他找到主页之后会给我们返回主页的内容,返回主页内容,是不是我这个八就是channel了,它既有输入输出流,有输入流。

所以返回也是通过把这个channel回来的,那我只需要读取八是不是就可以了,可以用cat,然后标准输入来自于,哎等会儿来自于8号文件描述符,一会儿我给你解释这个and是什么意思啊。

这么长时间socket应该断应该断开了没错,先看结果,在第一回车,我往这慢,稍等一会儿,今天不知道为啥,找感觉啊,这些东西看不懂无所谓,我都会每天都给你解释,其实你要这最终的语义就可以了啊,这么慢。

八是什么意思,你就八想成是一个channel,这个ping的是pc,这个三层的网络层是通的,但是这边,来自于8号位的面孔io,它打印到八去了,channel通道,我这给你解释,我先把这个问题解决一下。

然后快速的走一遍这个过程啊,先去到plc,我先验证一点,今天这个网不网不好,到socket指向已经有了,我给它关掉啊,重新走一遍,第一遍是我要给百度建立一个连接,就用了八对着百度建立一个socket。

一如果都听的就是跟百度建立了一个tcb一个socket,这个socket的输入输出流就被八代表了,被八代表之后,然后我要对着这个socket里面去发送消息给百度,就是把这个起牛头通过八给发出去。

发给百度了,发给百度之后,然后通过百度这边读取走哎就回来了,刚才应该是断开连接,有点有点慢,往往问题,现在如果我操作的还算比较快的话,跟得上的话,没有超时的话,返回头是不是也要有hb协议,就是两者。

我现在linux和百度之间用的就是hb协议,我发的时候得符合hb协议的,头发出去回来的时候是不是我你百度也得跟我说g sb协议的,我这边才能才能读懂,对不对,那返回头的协议是不是也ap一点零。

然后200k就是状态,后边就是这个响应头里边的各种的建筑。

对这一定有一个换行符,一个换行符,下边是建筑队就想投了。

想投完事儿之后,注意听整个上面是响应头,响投的八数据结束之后,它必须有一个换换符,两个换行符,两个换行符结束之后才是你想要的数据data。

想的数据data其实就是给我返回的一个主页。

这个主页是一个html的一个文本群,里边儿问问足下,这边不完图不完图片。

图片你还得再单再去请求,那么返回的h html html里边它又分为害的头和巴黎体两部分。

好吧以上这个我给你总结一下吧。

因为刚才网的确有点问题啊,来咱们总结一下,我刚才做了一件什么事情,首先我使用了一个指令,有点卡,没事,我给你做总结的时候,一边来第一个事情我是触发了一个指令,在操作系统当中我没有装任何的浏览器。

什么chrome firefox,什么都没有装,我就用了一个e i c8 ,然后输入输出,然后指向了一个一个地址,一个pass,首先一个给你解释,这个地址代表什么意思。

这是在操作linux操作当中或者类unity当中,一切皆文件,一切皆文件,你看似它是一个文件的路径,对你看它是一个文件路径,但是它其实代表的是一个socket。

要通过一个tcp传这个三次握手之后建立的一个连接,我们可以去验证刚才八是不是已经这行已经执行过了,这个八在哪,你去到c d p r o c,然后两个dollar就代表的是当前这个解释程序。

解释程序的斜线,f d就是文件描述符,这个目录下就可以看到012和这个钢铁801指向了一个书,这个其他的设备,但是八指向的就是一个socket,所以我说通过ec 8通过这么一个路径文件路径。

但是他却用八指向了一个开启的socket,就是这个语义,这个能看懂,原来刷波一五,不管怎么样,你现在知道了八是不是指向了一个socket,这是第一步。

第二步你要知道socket里边是可以得到输入流和输出流,得到两个流的,你在java编程的时候是不是可以得到一个客户端的client,一个socket,然后在里边是不是可以可以得到输入流和输入两个流。

所以上面那个大小于号和这个八八是什么,八就是文件描述符,文件描述符也就是f d file descriptor,f d这个词汇死记硬背,它约等于我们java当中的变量,就是类似于java中的变量。

变量引用,你在jva当中肯定是用一个字符字符串的一个变量,引用了一个一个一个socket,然后可以在里边这个比如引用一个channel,可以right可read读,像操作系当中就用数字了,用八来指向了。

刚才我们准备这个socket,它是一个文件描述符,这个死记硬背就可以了啊,你可以理解成指针,然后再来看这个大小于号代表的是这个大小于号代表的是输入输出流。

也就是说我约束八指向呢是输入输出两个流的一个socket,整个的一个完整语句,后面那个,那么前面e x e c是什么意思,想听吗,给你扩展一下e s e是一个什么意思,就是现在我是没有装浏览器的。

这是给你扩展一下linux的一个知识,e c你可以用type e c看一眼,它是一个shell building的,什么是shell,就是外壳程序,有内核有外壳,我现在交互的这个软件是一个外壳程序。

ez是他一个是一个是要building的,share building是什么意思,就是它集成的,然后是集成的,你就可以用help来学习e a c,用help学e的时候,这个e c程序是一个什么意思。

e c的意思就是replace the shell,就是替换那个shell with,使用什么呀,the given command,语法当中你是要使用它,然后给出一个command。

但是它在中国号里边就是可给可不给,当你给出一个指令的时候,用这个指令替换当前这个shell,在这我给你画个图就非常好理解了啊,首先你要知道操作系当中,我们人和他是不是可以敲命令,你敲命令字符串交给谁了。

交给了一个软件,这是我用普通话,就是你敲的命令,比如ios也好,或者cd也好,这些个字你敲的字符串交给了谁,交给了一个软件,你要把这些指令交给一个软件,这个软件叫什么,它软件的种类有很多,有图形界面。

有命令行界面的这样的软件,他们统一有一个标识叫做外壳,像外壳,它是一个程序,是一个软件,然后这个软件根据刚才的描述,这个软件这个shell里边这个外壳里边这个程序里边标停了一个e a c。

也就是这个这是如果是一个软件,它里边有一个指令叫做e a c,就带了一个本地方法,这个软件有一个方法,这个你如果对这个vc软件调用那个方法,后边如果given command就给出了一个命令。

如果你给出了一个命令,这个在操作的命令就是程序,命令就是程序,比如说你给出了一个ios程序,那么ioi的程序其实是在磁盘的,跟着我思路走啊,就是如果在他的时候后面给出一个ios的,给出一个给出一个命令。

这个命令会替换,就是替换当前这个上这个程序就会覆盖当前这个这个这个外壳程序,那么什么叫做外壳程序,外壳程序它其实要和用户交互,它约等于起了一个死循环,就是一直在read read,等待用户的输入。

这是外壳程序的特征,像ios这个指令是一个什么指令,ios是操作当中显示目录的,类似于这个dos dr啊,显示一个一个一个目录的,它一定是你执行的一个命令,显示显示完显示完你的目录之后,它会有一个退出。

其实这个程序会被退出,所以先跟着我搜索啊,如果使用外壳程序里边的e i e c要给given command给出一个指令,这个指令会替换你这个进程,那这个伴随着这个程序替换之后,它会执行显示和退出。

那整个县城就会消亡到这步,能替我们来说不一,好吧,那什么意思,比如说呃崩溃,你先你先小小的崩溃一下,你要找的是最后这个醍醐灌顶或者特别high一点。

比如e s给你演示e i e c given command,给出一个ios,我当前这个程序是不是可以一直就,当前这个esc是归属于当前这个解释程序的,这解释程序可以一直接受我的,接受我的指令。

但是我告诉他ea你要执行你的e ac并不跑向ios看看效果啊,回车显示了目录内容,并断开了连接,这个连接断开了,为什么断开了呀,因为当前这个死循环接收命的那个程序,被你e这个e z后面给出这个程序。

这个command ios替换了ios,这个程序就跟我们写的加入程序,最后就结束了,主犯退出了,他会退出,退出的时候,因为他是替换了那个进程,所以整个这个技能就消失了,消失了之后,我们这连接都没有了。

到这儿能听同学再来再来刷波一,现在能感觉到这个点了吧,这并不是重点,这并不是重点,为什么,因为你要注意啊,我再重新连回来,连回来之后,你help e i e c的时候,注意它的低,in command。

command是一个中国号,在一般看linux命令的语法的时候,中号是可给可不给,为了把可可不给,也就是说我是不是可以执行ea不给出不given common了,不给不给的话,那么他说replace。

那就没有命令替换,那么这个程序就还是他自己,他还是比较喜欢等待,等待着你的输入就没有任何变化,这个能听同学来刷波六,也就是说我可以在我的命令当中,我就ec我就ec我就ec不给出命令,啥事都不发声。

对不对,哎这个如果能听懂之后,如果这个能听懂啊啊我可以给出,我可以不给出,给出去替换,不给出我就不给他,但是我可以做一件事情,刚才我做了一件什么事情,我后面给出了这样的一堆一堆一堆东西。

那么e s c没有给出命令,后边的东西不叫命令,但是后边那个叫什么,这是操作系统另外一个知识点,这个知识点叫做重定向,这个东西叫做重定将,大部分应该你只要用过linux都知道什么叫重定向,什么叫重定向。

比如ios本来显示当前目录内容,我可以按ios,然后让他的输出用大于号代表输出,重定向指向到一个a a。t i t的一个文件屏幕没有了。

但是重定向到a。t i t了,这个就叫所谓的重立项,但是如果你想对重定向有更深入的了解,我告诉你一个基本知识点,就说刚才那个八就开始挂钩了,就转回来了,任何的一个程序都有输入流。

如果你去细思极恐一件事情,如果一个程序没有留,没有对外界的任何的输入输出流,这个程序是有问题的,因为他跑完之后啥事你也不知道,他的数据计算结果也存不下来,你也不知道发生了什么事情,这个能听懂。

原来刷波一,是不是能听懂了哎那么这个程序比有输入流,那么留在我程序开发者已经写死了,比如这个程序就往文件你去写,但是注意了,操作系统给了我们一个界面,一个什么界面,比如你去到p r o c这个目录下。

就是根目录会有一个plc目录,这个目录当中很多数字代表的进程就是一切接文件,每个程序都会有一个目录来表示。

那么随便进一个进程,比如1355这个里面会有很多目录,它会有一个文件描述符的目录。

进到fd这里面就会有012,这个012代表什么意思。

就代表了我当前的这个程序,它的输入流,输出流和报错流三个最基本的流,任何程序有java当中也有,比如说system。in sim。out,sim。error,这叫做文件描述符。

如果你的一个程序打开了一个socket,那么就会出现一个,比如一个四,一个五指向了一个socket,这个文件描述会无限打开,能理解吧,那程序里边有i o i o在操作系统会用文件描述符被表示出来。

那这时候如果一个程序写死了,像文件写或向屏幕打印,那这辈子就像这个位置打印了,但是操作系统给了我们一些操作符,比如大于号和小于号,这个叫做重立项,可以让一个程序。

比如说ios ios其实也有0121是标准输出,你可以让他的注意听啊,可以让它标准输出一就是ios也有012,它也有标准输出,让他的一指向到一个文件,那么回车之后,虽然你ios曾经你写的是c。

二打印到屏幕,但是那个打印到屏幕那个东西其实是用e表示的,你又让e指向了一个文件,所以ios输出被重定向到了文件里去了,刚才我这个这个这个这个文件乱七八糟的文件名就知道这个文件了,好吧。

那这个知识点加起来之后,把两个支线加起来,就是操作当中我可以用e s e来替换命令,这个当前进程我又不替换它,但是我会在他后边给出什么呀,给出重定向的绑定,就让我当前的程序的多了一个8号文件面符。

输入输出多一个八,然后让它输入输出指向到一个dv t c p,然后3w点百度,然后我就简写了一个八零,那么现在这行语法你就明白了,哎这行远程用了一个ez,又没有given common,没有给出命令。

所以当前技能不会被替换,只不过让当前这个shell程序多了一个文件描述符八来输入,输出指向了一个socket,就是这句话最终能听同学来刷波六,所以你看啊,如果cd到p r o c。

你先看打印echo两个dollar代表的是当前我这个解释程序回车,当天解程序叫做2640,续到p r o c下边的2640的目录当中,然后再去他有一个f d,去掉f d,任何程序都有零一样。

目前我这个外壳程序有零有一有二有三个,然后这时候我再加一个指令,就看当前程序只有012,然后我给出e i e c,然后指向上一个八,指向输入,输出到d e v t c e p3 w点,百度点com。

然后八零回车之后有点慢,大哥快点有了,有了之后是不是多了一个八,而我这个不用管它是不是多了一个八八,是不是整了一个socket了,也就是说通过巧妙的a c我不让你替换程序,但是我要执行你一下。

为什么我要给出绑定的行为,让当前程序绑定到了一个对百度的一个新的链接发上,好吧,那这个绑定之后再往下走,当绑定完之后,刚才我做了一件什么事情,我是不是用了echo刚毅。

然后后面接了一个get是ap的方法,对不对,然后后面给出协议,巴拉巴,这我就不给你演示了,这个协议输出的时候。

关键是看我刚才我在这给你记笔记啊,就前面那部分有了之后,下一部分是什么e i e c,不是这个echo杠e,我要让大写的get斜线,然后http一点零这个协议杠n,然后注意看echo也是个程序。

它也有标准输出一指向了,是不是给八打回去就可以了,听懂来刷波六,就是你现在刚才看我已经有一个八了,八已经指认socket了,我现在是不是需要把一个hp协议的头通过这个八。

这个socket 8你可以不用记,你只需要记住它,只能sl,我给通过sl打出去就可以了,现在抑制了一,就是这ex的标准输出指向了一个八分成一样,但是注意了后边是文件描述符,如果后边是文件描述符。

你知道加一个and就是大于号,大于号是输出中项到文件,然后大于and是到一个另外一个文件描述符,就这么一个死死记硬背的一个语法,就pg就发出去了,发出去之后,刚才我就说了,八其实是一个完全面符。

它是一个双向的一个流程上的一个socket,我弄i发,我通过八这个socket输入流能读,所以后面我做了一件什么事情,是不是用cat这个指令,cat也是个程序,是程序就有012。

我刚才是不是用它的标准输入零来自于后面放一个文件描述符,谁八就读到了百度的主页,现在刚才我的所有操作都能看懂,同学现在你真的明白了,就刷一波,cat是读取文件用的啊。

那么整个走的过程当中就用了一个简单的命令替换,绑定一个新的文件,描述到socket,socket是输入,输代表两个流,它类似于我们java中的china,类似于一个channel一个通道。

这个通道有输入流,输出流,然后呢我对着这个输出这个通道里面即发送又读取,利用的是重定向的第一个相关的知识就读到了,那么这些注意听为什么讲它,因为我我刚开始跟你说了,在通信的过程中,有用户同要做的事情。

有内核层做的要做的事情,那么把刚才这个整个操作,你去想想这两层我是在哪层操作的,首先在用户空间那一层,我做了一件什么事情,这些东西其实都来自于用户先做的事情,我对内核层其实就是这个八。

他是要触发一个socket这个过程,当中是内核帮我们建立了一个socket,但是剩下的我无论是组织协议还是读取,这都是用空间做的事情,用用空间才会关注http协议,就是找个协议的感觉啊。

就是虽然大家都说用户也能怎么着,然后用用户有什么协议,你能找到用户空间是要忙着完成hp协议的,什么叫tp协议,就是有标准,那之前怎么通信的,其实你只需要给出了我想跟谁想跟谁通信。

用空间的应用层协议也会调用内核里边的所有传输的环节,这两个是分开的,我想让你get到的,先get到这两个层次的分工对吧,这个分工完事之后,那用层的话就是我们程序里边代码,你你要发什么,你要读什么。

你要怎么做,剩下的事情,其实面试面的更多的就是哎那下面这些层次完成了什么事情,现在开始梳理整个内核里边那个传输控制能往下走的事情,那么这整个这个我的目的能能能get到我来刷波,一就是你你听我的课要忍。

你别看我前面做这些事情没有没有意义,但是一个完整性,一个体系有了之后,我举的例子我都给你讲明白他是怎么回事,你就忍耐一点,听完之后你知道哦,原来是这么回事,你会通通透,对不对,太慢了,老师没有办法。

因为这个并不是给一个人讲课,我给大部分人讲课,我需要把这个整个体系建立起来,那这个层次你要觉得简单的话,你就往后听,后面难的好吧,前面这个层次通了之后,那在这你要注意一下,软件是工程学,它是分层的啊。

这是分层的应用层,其实他没有写什么,我要跟谁去建立连接,你代码根本没有写,写了这么一行,给出了地址和域名和地址和端口号,那么所有的行为是透穿到内核内核层去做了,这个就是层分层,就是软件工程学解耦用的啊。

我任何的程序员啊,那么连接的事就掉内核层,等于你的浏览器在这堵塞住了浏览器,如果你给了一个地址吧,g回车,浏览器先别动,那先调内核去建立所谓的传输控制,建立连接,那么往下走一层就到了传输控制层。

每个层都有协议,在应用层,刚才说了rtp啊。

系列 2:P64:TCP合集:02,TCP,IP传输控制层原理 - Java视频学堂 - BV1Hy4y1t7Bo

SD那传输控制层有什么协议?每层咱们一个来解释,在传输控制层。传输控制层有哪些协议?常见的,比如说我们的UDP协议和TCP协议这两个协议。UTP不讲,我们只说啊TCP把TCP和s的讲明白。

他们到底是啥就可以了。而且它为什么叫做传输这里边还有一个词叫做控制。其实传输会让你误解。因为你可能发现这个传输这事是不是就已经由这个传输控制层决定了,但是传输不是重不是重点,重点的事控制这两个词汇。

也就是TCP里边在控制什么东西,它在控制哪些包是不是会有一些控制包和确认包等等这个这个概念。那么在传输控层之这个进造这个层当中,我们只聊TCB如果你出去面试,面试官问你什么是TCB协议,你要怎么回答?

一步退档。什么是TCP?文件描书可以是8,可以是9,可以223311555都可以。那文件描书只是个数字啊。一旦你去面试的时候,问到你什么是传输共程层的TCB协议啊。

然后你要告诉他这个协议有两句话必须说出来,一个是面向连接的。一个是可靠的传输。协议这两句话注意听这两句话一定要说出来。那这时候首先有一个词就放到你眼眼睛里边了。什么叫做连接连接是物理的吗?

就是你的电脑上面插了根网线,物理的连接到了百度上,你俩这靠着个网线个通信了,这看似简单,但是却不是这么回事,这个连接应该是一个虚无的那连接到底是什么意思?往下推导啊,知识往下推导的。想讲清楚连接。

你就必须要去聊一件事情,叫做TCP的三次握手。这之日其实他这个有人说三次握手就独立回答,不不要独立回答。你的三次握手的回答,一定要和TCP的面件连接这事儿挂上钩。四次是分手。那么什么叫做三次握手。

能跟着那个节奏吧?就是你你要在大脑里梳理这个逻辑关系啊,就是所有的知识点,它不是碎片的,它之间一定会有某种因果关系。你要想讲清楚什么是TCB你要说面向连接,什么是面向连接,就要聊三次握手。

因为最终三次握手我会告诉你那个连接它是虚的还是物理的。那么什么是三次握手?那这时候你要给他解释了。如果我有一个客户端,然后呢有一个服务端。有一个服务端。那么客户端如果想和服务端建立连接的话。

第一件事情客户端会发出一个包,这个包是谁创建,谁发出的,就是由我们传输控制层。他去创建了一个第一个包,从那台机子里边啪发出去了,往下走啊,发出去发出去之后到到达你另外一台服务端,服务端会收到它。

收到之后,我们一般管这个包叫SYN。s net就是想跟你同步,想跟你建立握手。发了之后,服务端一旦收到了这个数据包之后,会给客户端返回一个数据包。就基于这个收到的包,返回一个包。

这个包一般就叫做SYN加ACK。ACK这个包就是acknowledge。哎,我知道了,我知道你这个包了。那这个时候注意听什么了三次一次了,两次了,第三次是客户端再给服务端回单独回送1个ACK呃。

我也知道你回来这个事儿了,为什么是三次。还是强调IO尤其set的IO通信是双向的,站在客户端有输出,有输入。那么其实前面两步客户端已经明确了,我到服务端能去,而且他能基于我去的给我返回。

那我的输入输出是通的,但是站在服务端,我能收到别人给我发来的,那么客户端面向我的输入是通的。但是我给他虽然回了一个数据包。但是这个数据包对方有没有收到呢,他不知道的,他必须要再等一个确认。这样的话。

双方才能确定自己的各自的输入输出是通的。所以他要经历这么三次,就是为什么握手需要三次听懂同学来刷波一。UDP的话,它就没有这个确认的机制了,就是我就发了,你爱收入搜着收不着。😡,好吧。

那这个三次能想明白之后,注意听,当三次握手建立完事之后,才会你的这个传输控制层。比如这三次都有了之后,开辟资源内核里边的结构体,这个内存的对象的开辟和给你的客户端应用层程序返回这个连接通了。

会有资源的开辟在两端。这句话很重要,有资源的开辟。一会我会让你看到在内核里边也会有相应资源的这个表示和映射。因为一会儿要聊sockcket的,就是双方必须有资源的开辟,代表为对方服务。

就是完成自己的后续的输出和对方。如果发来数据包的话,我有资源接你这个包,后续的一个包。那么双方资源的开辟这个都开起来了,这个连接就有了。如果一方把这个资源不小心丢掉了,你在发出据包那边就没有资源接收。

这个连接就等于是连不上了。就像我现在跟你说话,你咱们网不好,我也看不到你刷一刷6,那这时候我就慌了。所以双方开辟资源就是经过三次握手。双方开辟了服务资源之后,这个所谓的连接就有了。这就是面向所谓的连接。

连接不是物理的,是开辟的资源对称,听不回来刷二波6。happy资源包括哪些?一会儿一会儿我带你慢慢看,一会儿带你慢慢看。然后面向连接连接有了之后,下面还有一句话叫做可靠的传输。那么它什么叫做可靠的传输?

其实已经代替出来了。也就是说一方发送的数据包,这包到底到没到你那儿,它必须要等于acknowledge要等确认这件事情,就是我发的,你得给我AACK我发的你得给我ACK确认机制是它可靠传输的支撑。

三次握手啊三次握手带来了带来了这个这个连连接,然后。确认机制,保证了可靠的传输。好吧,那么这是当这步你经听懂之后,三次握手连接这件事你听明白了。那这时候再来往下思考啊,总结总结一下,总结出来之后。

也就是说两个端点客户端和服务端,两个端点间想通信的话,整体的流程是必须先建立三次握手。然后三次 word之后才会有一个数据传输的后续。因为三次握手之后,双方的资源建立完之后,双方资源开辟好了。

然后你的应用层才会传输数据,说我的请求头给我发出去,然后给个确认,然后这边把响响响响应体再发回来。哎,我再接收到,那就是数据传输是一定要在三次word手之后的。三次握手是四层内核完成的。

数据传输是端到端七层应用完成的。啊,这个概念也要梳理出来,这个概念有了之后,那么还有一个除了无握手有数据传输,最后肯定要牵扯到一个关闭,还有一个四字分手。这连接不要了,我要关掉他一个4次。分手。

那他为什么有一个四次分手?在这儿先不说四次分手,在这儿其实在传输控制层这里面就在内核层对传输控层这个这个东西啊,它封装出了一个词汇。这个知识继续聊啊,就是你要先聊出三次过程。

什么是它什么是这个TCB面连接可靠传输。再往下聊的话,其实还有一个东西就是在传输控制层里边。向你的内核向外暴露了一个新的一个词汇,这个词汇叫socket。很多人就是哎我只知道socket。

我听不说过sockit,那socket到带到底是什么意思?把这个事儿是不是得学明白了?我到时候都会会以给你带你抓包去看啊,先跟着我的思路走,不是channel嘛?channel是你JDK抽象出来的。

在计算机当中,在操作当中是给了socketsocket可 do可写。在传统的我们这个GTK当中,哎,它scket有了之后,它可以拿到两个对象独立的输入出对象和输入对象。但是在JTK1。7之后。

它有一个NIO就是new新的IO体系。它用了一个channel来代表了这个scket,你就再也不需要得到所谓的独立的输入输入流,你对着个channel可都可写了。就像刚才我对着那个8可都可写一样。

其实回归又还原回来了。因为这样在你的所有的线程方法传递的当中,你传递一个channel,这个对象里就包含了scket的输入输入两这个两两个方向的流,就是都说了,听懂听听不懂无所谓。

你先弄明白什么cket好吧。因为这两个层次,一个是IO层次,一个是这个这个这个这个内核层次,就通信层次,网络和IO是两两两两回事儿。首先啥是scket的,刷一下,哎,刚才说了,也是套接字,对不对?

那这个套接字只是一个中文解释,这个套套什么东西,谁套谁。你对骚费者要怎么去理解?😡,插座啊,这是马老师一般会说它是一个插座啊,是谁插上谁了,对不对?那s给的是套接字。那我先告诉你结果套接字怎么去记它。

你就这么去记,它是成对出现的IP。Port。然后再只剩一端的IP加上portt。那么它可见不可见,在操作系统里边能能看到它这样的一个指令。

用net state。杠NATP。

这个是网络状态,然后显示所有的TCB关于关于TCB协议的,然后打印出是哪些进程开启了使用这个连接,所谓的连接,所谓scket。那么这个表格当中哎,比如说有TCB协议啊,这个发送的合集序列号不用管。

关键看后边有一个本地的IP加端口号,有一个对端的IP加端口号。然后呢有相应的这个sty的状态,有listen状态和联通状态,未来可能还有断开等待状态等等的。好吧。

那这里面是哪些进程在使用了这个所谓scket。我们分析一个东西啊,首先看有一个listen,这有一个这有一个进程叫做SSHD这个进程,它的进程I号是1010,它这个进程起来之后,它list了。

就是服务端只有服务端百度om来之后也是状态。它百度比如80或者8080SSSD远程连接的话,它就是22端口,所以它在本地监听了22监听8080,必然有一个监听的状态。这是第一步有一个监听。

就是服务端刚起来。如果一个客户端起来之后,跟他要做三次握手完成一个所谓的连接,得到一个scket就是这时候看下边,比如这有一个SSHHD有一个新的2451,这是另外一个进程。但是这时候注意了。

是本地的一个IP端口号就是本地的logo的也是22端口和你的客户端1个10。1,它的一个随机端口号,这就是IP端口号IP端口号组建了一个。套接字一个socket。

这个socket完美的代表了这一个客户端连接。为什么你会发现下边你注意看一个特征,下边还有另外一个进程,也是也是SHD是2638。它的服务端本地的IP地址登录号和刚才那个连接一样。

就这两个s的服务端logo的都是一模一样的。看客户端的IP地址长得一模一样。但是套接字里边一定会有一个维度能够区分这个连接和别人两个连接是可以区分开的。先找到scket啊,它完全可以独立代表某一对连接。

这一对连接必须有4个维度IPportipport缺一不可。你说我如果就看这个,对我就我我就说IPpo就代表scket了。你看这俩是不是一个scket,你区分区分出来,他发来的,你还给他发或者给他回吗?

是不是区分不出来了。所以sockcket什么叫套接字,俩得套上成对套套起来,一定是IPportipport。不我都给你讲到了,什么是随机断号,什么段号都给你讲,而且断号都这是数量关系。

到这步能听的同学来刷一波一。😡,s的套接字一定是IPpoip的这个套全套上的啊,而且它是绝对唯一独独立能能代代表的。

当这个知点你能接住之后,我们再来思考,刚才又带出了一个词汇,就是词汇都是慢慢慢慢带出来,它是知识成体系的。刚才在IP portIP port里边出现了两个词汇,一个是IP先简单说一下。

一个是IP一个是port的端口号。IP是起到什么效果的?IP是互联网的中种主机定位用的,就是你通过IP可以定位到主机。能理解什么意思啊?就是通过1个IP可以找到一个主机。然后这个时候可以通过端口号。

它为什么一个泡?这个端口号可以找到谁?你先通过IP找到主机,从主机里边可能会有很多的进程。你要跟哪个进程通信数据包交给谁,是通过端口号来代表你的进程。或者是县城。哎,找到那个应用程序。

最终你要明白端到端是程序与程序之间想通信,对不对?哎,最终是要命中这个程序的。那么在这里面端众号里边,根据刚才套一次app or a port的还分为两类,一类是服务端。注意各着听啊,一类是服务端。

服务端,它需要比如刚才1个22或者是8080。服务端只需要开辟占用一个端口号,你的百度服务器它就占用了1个80。然后你的客户端。服务端是明确要占用的。服务端是明确要占用的。服务端是明确要在这个操作5。

我这个我这个进程就占22,就占8080或者就占80了,这是服务端。那么客户端什么什么特征?😡,把自己音音放大点啊。客户端是随机的。随机的申请断口号啊,那这个端口号的取值范围是多少?

先告诉我断号的取值范围多少。有一个一个操作系统可以申请申请到占用多少个账号哎,65535个。就是0到6535。这些都是你们曾经听到的知识,这些知识我觉得应该都是常试能听懂。那么现在我开始出面试题。

下边出面试题了。如果说有一个百度百度的IP注意IPA。IPA是百度,它的端网号是80。那么注意听啊,这是一道面试题啊。如果你有一个客户端注意听,如果你有一个客户端成客户端,这个客户端的IP是B。

客户端的IP是B。那么这个客户端当中,这个IP可以对着百度一共建立多少个连接?就是他们之间可以建立多少个连接?你就是通俗来说通俗来说,大概一个数就是6535,对不对?

那假设你这台IPB上已经对着这个IPA有6535连接这个这个每一个连接啊,就是你这个这台主机里边的每一个程序,每一个程序每一个线程发几个连接连它了。那么实习生的一个端口号,那么消耗了6535个。

那么这时候如果又多了1个IPC注意听又多了1个IPC的。比如说腾讯腾讯的主机,它是IPC也是8个根口号。那么请问IPB还能够对着它发起连接嘛?还能不能。就是你前边这台主机已经对着百度已经用6535个了。

那现在对着腾讯还能不能?可以还是不可以。你看答案就不一样了,你要真正理解什么是sockcket,什么是套接字,套接字是4个维度的是IPpoIP port不要只看其中一半。

那这时候其实IP port的IPB加上一个端口号,对IP的80,那有6535种可能。其实IPB对着IPC依然有6535个可连。也就是IPB到IPA。可以使用你这系统的65565535个登录号。

然后另外1个IPB到你的IP。C依然有65535个连接,可以创建登众号可以分配。你不要认为端个号重了。你说哎这个对百度我申请了一个8号8号一个C登号,那我对腾讯就不能再申请申请8了,不是的。

明白我什么意思吗?就是这台主机里边可以有两个8号登录号,给了一个什么呀?IPP到A的,一个给到IPB到C的。因为是IPP的IIIP端号IP登录号,这是4个承对出现的。没错,整个只要这个维度是唯一确认。

别人没有使用就可以创建出来。唯一K。到现在解惑能听的同学来上2边6。你说你怎么重复,你这边IP到C了,那边IP到A,你登号随便给他俩重复不了,因为会受那个IPC和IP来区分出来,对不对?

只有在一对的IPAB里边,你不能说IP8号到AIP8号到A,你该该创建这么两个,这两个是创建不出来的。哎,这是第一个维度。第21个维度。刚才你看有有同学问了,说那如果我呃这是客户端,这这块能想明白了。

对不对?那么请问在你的这个服务端端口号的消耗,比如这你现在这台主机相同的BIP里边,对A对对百度有653个连接,对腾讯有653个连接,那么请问服务器里边消耗多少个端口号?就拿A来说。

这个台服务器会有6万多个连接连它,它会消耗多少个多口号。没错,只消耗了80,它只消耗了80的一个。为什么?因为它是IP80,但是每个过来的人会带着它不同的IP的不同端口号。他会有一个。

就这张表能映射出来,在内核里边你是能够现在就是他看测有内核嘛,是能够看到他们这个映射关系的。虽然我本地的我都是只只开了1个22,但是你来了一个链接。这个整个说一遍,比如说现在如果下边这几行没有。

先不看它进台服务器起来之后,只有一个leaen的状态。那么这个客户端如果带着握手的包过来了,带着这个顿号,把握手的包过来了。那三次握手跟先跟他去走通,走通之后,咣当开辟资源fo进程。

或者java里边就抛出线程去了,一个线程或者一个进程就持有了这个sockcket。为它怎么持有这个scket。注意听sockcket是不是可以映射成文件描述符一个81个IO对象。

那这个进程只要来回读写八就一定只和这个客户端通信,它就不会和别人通信了。因为在程序的视野里边,我有一个流叫8,这个八其实代表的是一个sockcketscket是IPport加IPport。

是一个稳定的一个独立连接。所以我程序这个2451,只要对着八玩命的读写,就只能在我这个客户端的通信里边通道里边是不能刷到别人的,听懂同学来刷2波6。

多层映射唯一路径。现在你还觉得我开始讲那么多伏笔,讲那么我开始跑埋了那么多伏笔是没有意义吗?一定是有意义,对不对?你看这个。🤧PWB只看到我当天那个外壳程序的个FD啊。

好吧,收现在你应该对什么是传输控制层TCP3次握手,然后什么是这个socket以及sockcket的各种组合情况,以及服务端。其实它只需要一个端口占用。来了之后。

根据scket唯一映射sockcket在这我给你多写出来啊,sockcket其实会socket。现在你知道scksocket就是IPport加IPportsocket会在操ing的内容当中映射到1个FD文件标符一个数字。

啊,一个数字这个数字其实会交给通过for的时候,会交给某一个进程,绑定起来一个实际的一个worker进程。啊,那一个进程里边持有哪个数字,那对着一个数字读写文件边如读写,就一定会符合这个scket。

另外一个scket一定会复合或者是克隆出进程或线程,就使用另外一个工作的进程或线程去持有另外一个scket,他们是清晰独立的,对不对?那这是第一版本,后边还会说可不可以多个scket对应一个。

这就是排抛出一个问题啊,就是多个socket。对应一个进程,就是你现在现在你看啊现在你看的是一个socket,对应了1个2451,1个sockcket,对应了1个2638。

那多个socket可不可以对应一个县程或一个进程,可以还是不可以?

可以,那这个知识点不在当今天的课来讲,这个东西就叫做什么呀?多路复用器。也就是slaide或者epo了。这是在我专门讲IO的课里边,这个知识体系又搭上边又串起来了。你能说学通信和IO没关系吗?

你看到这儿,其实这是曾经最传统的什么呀?每县程或每进程对应一个连接。但是现在的通信这样太浪费资源了,一定会使用多路复用器,一个进程,一个线程对应多个客户端,谁有了,我就跟谁跟谁通信。

这些东西都能大上边都能连起来,就支点一直串一直串一直串。因为现在我再给你讲的就是什么呀?传输控制层和应用层这个界面上内核在这个界面上会包包装各种的多路复用器,side pull一碰。西不哎,屌不屌?

好收。只是支持多个连接,想时间就变长了吧啊,这个这个问题没读懂啊,先跟着我的思路走吧。我为什么讲这块知识,就是把知识传完之后啊,你只有登录号了。其实我们要讲四字分手,为什么资源总是有枯竭的时候。

比如说就拿着这台机子,我对着百度还真就不是想发起6万多个,我想发起更多的连接,那其实其实前面一个链接连完之后,我已经请回主页之后,然后这个连接我可能不用了。比如说你想对着百度开启10万个标签页。

你想对着百度开启10万个标签页,你是开不起的,你只能开启6万多个。那前面这个标签页我已经请求完页面了,我在那个标签页就对着百度查别的东西能能能不能行,可以可以的。是不是可以。

你只要让前面那个标签页把这个连接断开了,顿号还回来。我这边再拿着新的号,我再连一次,再去取去请求请求回一次。展示完之后再还回给系统,所以断开是一定会。存在的那断开为什么是4次分手,就要聊这件事情了。

那么断三次握手是为了双方开辟资源抛出现城响应对方。这个就就是所谓的一个连接。这个如果听懂,你才能真正理解分手为什么是4次。因为四次分手要代表着释放资源。但是注意听释放资源不能单方面释放。

我光当我说释放就释放了。那这时候人家还想给你传东西,这边就没有响应了。所以资源三次握手好容易建起释放资源要同时释放,大家预定好都不发送数据,都不接受数据了。没用了,咱们咱们咱们得连接。

这个时候是不是才可以释放。定夺来烧边一。所以4次分手是怎么分手的?这里面就有一个大家伙都得同意离婚这件事情,不是说你单方单方面想离婚。想离就能离对不对。是不是这个意思?

所以四次分手是一个大概一个什么过程?客户端说我想和你断开。FN断开final里结束,或者是这个finish结束了。我想和你断开数据包发出去了,再加上可靠图传输。这个时候其实服务端并它会回送一个什么呀?

服务端会根据你这个收到这个哎,我会我会回一个。基于FN的一个。ACK acknowledgeled就是我知道了,然后知道之后,但是这个时候他并不代表说我也想分手。我只是告诉你,你发的包我收到了。

这时候取决于服务端。服务端如果发现咱们之间真的没有啥事可办了,再发送一个服务端还要发送一个什么呀FN我也想finish断开这一个连接了。那发出去之后,客户端说好的,我也知道你的一个数据包了。

ACK只是确认数据包不代表任何的意思意思必须要主动说出来,你想跟我那啥嘛,你就主动说出来嘛,你想要你就说嘛,你想要你就说嘛,你想分你想分就说嘛,所以1234。这是一个通用的一个知识点。

分手是要经历4次的。听懂来刷波一,那这些过程我先给你简单抓个包演示一下,再重新说一遍,一边演示一边说好不好?啊,你从实物当中去看,我们开始抓包。

加包的时候,我们这样来做啊。需要抓包的话,是需要一个程序的一个小命令,这个令命令叫做TCP。dump这是一个抓包程序。这个没有的话,你AP get或者y么去inst装一下,装完之后啊。

注意后边写参数杠NN是未来抓到的所有数据包里边的那个IP呀,端口号啊,全都变成数值显示,然后呢,杠I你要抓的是哪个接口,比如我抓一个ATT值0,通过值0可以访问我的外网。

这是一个端口interface接口的名称,你要抓谁抓数据包里边是80端口号的。因为我要通过访问百度的。整个请求页面的过程。把所有包抓下来,看是不是和百度有三次握手,是不是有中间的数据传输。

是不是有4次分手。跟我讲的这个理论是不是对得上,这是一个抓包的过程。好吧,然后前面怎么去抓,我先给你演示一下,怎么抓包啊,可以通过Cl这个命令CURL后边给出3W点百度。

其实这个小程序就完全可以取请求回主页了。但是今天这个网怎么这么慢呢?你看主页是不是请求回来了,只不过这个编码我改一下,因为现在不是UTF杠8换一下编码。UTF杠8。重请求一下,是不是百度一下。

你就知道这请求回来了。然后这边我也改一下。

UTF杠8。

两件事情我有两个窗口,一个窗口我会打开监听抓包回车。那么现在看listing on ethernet0号网卡。

这个是开始监听了,另外一边我会实际的触发去访问cl这个命令。cl其实基本不用装,系统都带访问百度,注意看走。

跑通了,但是没有抓到,为什么?我告诉你为什么呀?因为我这里面有2块网卡,一块网卡是ET0,是我的150。12本地的,一块是ETH1,这是走nice的,一个是ETH1,他走的10。242走的我的物理网络。

它有2块网卡,刚才是通过ET1走出去了。

明白吧?所以这边我监听的时候只需要做一件事情,改一下监听的网卡。

算了,我把那个if扛废,我把那个E1给给它断掉了,ETHE给它荡掉。

这样看的比较清楚,就是ET20啊,就是1个ET20。这个环为接口这块也给它断掉吧。

很干净啊,我这台主机只有一块物理物理网卡,你甭管它net还是直连的,就是150。12,它是E70网卡,然后再重新跑这个监听。

最主要就是TCBd。走再把它坚定起来,再继续坚定也是0啊,然后这边再去请求cl。哦,诶。稍等我修改一下root杠N应该是少了一个末认网关啊,现在到百度出去,待会给你讲root。艾嗯,然后。

这样怎么怎么怎么加网关了呀,root and。然后这W192。168点150点2。热情降恩,我得有一个网关,这数据包能出去。能出去之后,这不叫翻车,我刻意的安排了一个翻车,秀一下我的root指令。

然后。在pro百度是不是请学回来了,包是不是这样了,4分钟一搞定啊,这这都这如果都搞定不了的话,怎么能给你讲课呢?

好,crl C给它接收掉。这里面我们来数包,刚才是不是注意听啊,分析下,刚才是我用Cl这个程序先把它跑起来,访问了百度取回来页面,并最终退出了这个程序。所以这个程序一定包含了启动连接。

请求数据关闭断开链接关闭程序的过程。那么在网络行为当中就一定包含了注意看,先是本机的150。12,1个随机端口号,到我们百度的IP地址的80端口号发送了一个SS文想建立握手,这个包的长度为0,看到了吧?

这个包的长度是为零的。因为它并不是要数据,这并不是应用程序发送的。它是我们传输控制层产生了一个握手的包它发出去了,所以大小为0,发出去之后,是本地给给百度百度给我们回了一个数据包,是S万N加ACK。

这个点是ACK加了ACK这个确认包大小依然为0,因为这依然在传输控制层在建立连接的过程。回来之后,然后我们的客户端依然又给百度回了一个简简单单的ACKacledge这是三次握手才有了连接,这是第一步。

看同学来上二边一,大小都是0,这叫传输控制包,是由传输控制层双方建立的,一来一回带一回搞定传三450有了之后,然后才是我们cl这个程序应用层的程序。他要发送的是请求头。

所以我们的本地的随账号要发送给百度一个有大小的包,len是168。这是从本地给百度就发过去了。然后这个屁是你收到这个包立刻处理,不要停留,因为我没什么可发的了,这是一个请您头发过去了。发过去之后。

百度立刻先回了一个大小为0的acknowledgeACK。这是基于可靠性。然后这时候百度立刻处理完你上面那个包里边内容,请求资源之后,给客户端返回来一个有有大小的,这个大小是1460这么个字节。

返给百度给我们返回了一个数据包,我们要对它给一个零大小的ACKacknowledge确认你给我发的东西到了。但是百度又给返回了一个数据包是1321个数这个字节。

然后咱们又给它返回了一个acknowledge,这一共有4步,就是百度给我们返回了1个1460。我们一个确认返回了1个1321,我们给了一个确认,这四个是两个交互,11460加上1321。

就是整个页面的大小的字节数,因为数据包大小是是被受到限制的。数据是被被切割成package,切切割成包的。听能来刷2边一,这跟滑动成号没有关系,跟滑动窗口没有关系。你要先知道,我们通过网络发送数据包。

数据包不可能无限大。数据包大小是有是有是有限制的。比如说数据包大小是1460,已经约定死了1460个字节。所以一个网页很大的时候,他先把上面拉的1460一发过来,再给你补全后边的1321。

能列吧哎协定的先跟着我的思路传传所有啊,这个确定完之后,最后你看有4个包,还有4个包,因为已经发回了1321和1460拼出来已经是这个主页的内容了。显示完之后程序要退出。所以看下边这行。

就是我们本地和百度说哎finisher拜拜,我想给你断开连接。这时候百度给我们回一个,哼我知道你想断开链接这事儿了,但是不代表他想断开,为什么百度还得说,其实我也想跟你断开fininish。

然后这时候客咱们客户端跟他说好的,知道了,4次回手。😊,三次握手数据传输,四次分手都得给我加着确认的机制。好吧,那这个指令监控的过程,我们可以再让它复杂一点。

TCB大幕这里面我们呢可以再加上一个选项是杠叉,我忘大大S小S了。我们先先先看一眼啊啊,大加一个大X,然后同样的再去请求一遍百度走,然后这个时候注意收到的东西就相对多一些contl C。

你来看再验证一遍这个。三次握手,这个包都抓的就有有些包里边这个东西就显出来了。第一个是握手的包肯定大小为0,不用管。然后后边是一个呃也是一个握手,这个握手的确认的包加ACK了。然后呢再来一个确认的包。

这里边都看不到数据,因为这是传输共程,是不是没有数据,关键看下边咱们本地给百度发了一个数据包,这里边是不是有get斜线HTV1。1的协议user这个客户端版本多少号,这就是请求头。

这就是百咱们给百度发了一个请求头这个数据包,然后人家百度给了我们回了一个很小的一个acknowledge这个数据包这个确认包大小为0,然后百度开始接着给我们返回1个1460大小的,为什么是1460。

你注意看这里面是不是有响应投H1。0200O然后想投里边是不是想投,然后以及到它的HH开始到下边这个包它其实没有接数。这个页面还没有还没有给你输出完,就到这就卡住了。因为先满足1460。

然后给我们返回之后,我们给他回送了一个acknowledge确认的包。然后人家接接着给我们返回剩下的1321个字节,这里面是不是就开始页面的剩余剩剩余的那些个字节开始返回了,这是1321个返完返完之后。

我们又给人一个acknowledge一个确认的包。然后这时候我们已经打印出来之后,我们才开始跟人说finish断开,然后确认,然后人家也说断开,我们也说确认。啊。三次握手数据传输,四次分手。

所有的包帮你抓到了。和我描述的是不是一模一样,对不对?那么在这儿扩展一下知识。当你能够听懂这个知识之后,我给你扩展一下。新的知识先新的知识咱们先不聊了,先把整体梳梳理完。当这些知识你明白之后。

我跟你说一句话,这句话叫做三次握手。然后加上数据传输到4次分手是一个不可被分割的N最小力度。不可被分割。这句话能听能听懂吗?为什么叫不可被分割呀?哪个场景你需要注意或者哪些技术,你必须要想明这件事。

这是面试官常问的一个题,就是在在高并发负载均衡的时候。负载均衡的时候会牵扯到1个LVS的一个技术。它是基于四层,也就是传输控制层的一个负载均衡器。那么这时候很容易给你下套,就是四层负载均衡器。

是不是可以把我们的数据包随便的给后边的这real server去负载呢?这时候你说可以负载,但是它必须受制于协议约束。什么意思?不能出现这样一个非常诡异的现象,就是你有一个客户端,然后呢。

经过中间的负载均衡服务器。比如说LVS。然后呢,你有两个。这个服务器。你可以做负载,有两个服务器,也可以做负载。但是这时候客户端握手的包发过来之后,LOSS把握手的包假设转转发给这这台了。

它是四层数据包转转过去了。那么他一定会给这个客户端回送一个确认的包acknowledge是三次握手的第一次和第二次。那么客户端如果再发来最后一次的确认的这个握手的包的话,你LOSS一定给他不能给他。

如果不小心把最后这个包。负债均额给到他了的。

系列 2:P65:TCP合集:3,TCP ip 网络层原理 - Java视频学堂 - BV1Hy4y1t7Bo

那这时候你会发现他等不到最后那个握手的包,他没有开始就已经要那啥那啥了,还少少前面那两步。那这时候其实这两者都不会开辟资源,没有开辟资源,就没有我们所谓的连接通信就不行,你就破坏了分割。

这个不可分割性完整性。

到这部分能听懂的来说边一,你看知识都是你需要先学一个体系的知识,才能理解一个高阶的一个知识。好吧,有人立刻就反映出了一个Ddos攻击的呗。Ddos的一个基于这个TCP的S文的一个攻击啊,也就是什么意思?

也就是说你可以在互联网找一堆的肉机,然后呢,你设置他们只对某一台服务器只发,我想给你握手,你给我回确认,我就不给你回。那这时候他其实会计时的说我得等人家回回的确认包啊,你这样肉机多了。

那么别人真正的客户端想跟他链接的时候,已经没有资源了,那存已经满了,那连接连接不进去了,对不对?好吧,这是关于传输控制层的所有的知识点。现在已经梳理清楚了。但是这个梳理清楚之后,我再跟你说一句话。

我再跟你说一句话。软件是工程学啊,软件是工程学,是分层的。我刚才是就这这一层说把下边这一层就已经就带通了。其实应用层是先说内核帮我建立一个连接,然后内核说收到传输控制层开始握手。

传入库能创建了一个握手的包,它就停住了。因为这个包不是它发出去的,它怎么发,怎么发给谁,就得需要另外的层次。就上面都是阻塞的,所以三次握手的它的第一个握手包在这阻塞住就就开始掉网络层了。到这步能听懂来。

上边一就是为什么要讲网络层,就跟就是你的数据包传输控制层,我能做一个包,就是握手SN。但是这包该怎么发发给谁,从主机怎么出去,路由怎么走,互联网怎么才能找到他。对方这事儿不是我传输控制层做的。

是由你网络层来梳理出来的,所以要分层就调网络层了。啊,让我喘口气儿。到网络层的时候。你的数据包应该怎么走呢?从我主机怎么出去呢?网络层说了,每一个层都有协议,每一个层都有一些表。

刚才传输部层inice state可以看sockcket表,网络层其实牵扯到极点,它里面会有一个路由表。告诉你的数数据包应该怎么走怎么怎么走。在这儿我简单的说一下,这个不做太多的网络层的一个扩展。

因为这要聊的话,关于给你讲故事可以讲很多几个维度啊,几个维度你记住清楚记住这个记住了就可以了。网络层要解决什么问题?第一个是寻址。第二个是路由。其实都为了那数据包去走啊。第二个就是路由。

路由的词儿啥意思?一会给你讲就明白了。寻址的话其实就用到了一个东西,叫做IP。寻址里边用了一个东西叫IP路由就会进到一个路由表root。那么寻址的时候,我们拿人来举例啊,我们拿人来举例。

你给别人写信地址寻址,你的地址要怎么写?你的写信的信封的地址里边一定要包含什么呀?哪个国家,哪个城市,哪个街道,哪个小区,哪个门牌号,谁收一个完整的一个路径写的很全,一层层其实缩小查找范围。

最终命确某一个人,对吧?这人的人人的社会当中。那网络当中一样,首先说IP地址在网络层当中啊,网络当中,尤其在互联网当中,每一台机器都有一个自归属于自己表示自己的一个寻址的1个IP地址。

那这时候如果寻址的话,IP地址是代表互联网当中每台机的话,那么如果想某某人快速定位的话,这个IP地址里边应该包含两个东西,一个是网络,一个是。主机号,就是你你是哪个人?如果没有网络号的区分的话。

那这时候就像我们给某一个人写信,就张三周不写哪个国家哪个哪个那个哪个街道。那这个信就是很难很久才能到达那个人手里,可能都到不了。这个思路能不能想明白,就是IP地址里边其实分为两个东西。

一个是描述它在哪个网哪个哪个网络里,哪个局域网里。它的网络是哪一个网络,然后它在这个网络当中,它是这个网络里边的哪个主机主机号。网络号和主机号两部分组成。这是宏观啊,宏观有了之后我们来看一个东西。

VIETCs configure,然后network杠scripts。ETH0。这就是interface congeeternet以太网0号网卡回车。一般我们给主机的网卡配IP的时候。

要写出4个维度来它的IP地址。它的掩码还要给出网关以及给出DNS域名解析。这个域名解析。我不解释,大家应该都知道,就是你只要知道台服务器台地址,把百度那个域名给他,他告诉你百度的IP地址。

因为通信必然使的是IP封装数据包就通信,关键是上面还剩仨,一个是IP地址,一个是掩码,一个是网关网关一会儿再说,先看上面2个IP地址,大家都知道,哎,这个地址就是给我的那别人就不能使用这个地址了。

掩码是干什么用的。为什么你经常看到3个251个0或2个252个0掩码是干什么用的。编码是干什么用的?那这里面其实有一个没错,有一个很简单的一个道理啊。IPV4是点分字节。

就NIPV4里边点一个点与一个点之间是一个字节,一个字节是8个二进制位,8个二进制位。如果表示的是正整数的话,可以表示的区间是0到255。这是一个区间。

所以向下边这个2555代表这个字节就是8个18个全一上边1192的话就是某种零1的组合。那么拿IP地址和你的掩码做二进制的案慰语,就是192的某种01和一堆一做案慰语音算,得到的还是192。

这是这个规律。先跟着我的思路走啊,那这样的话,192和一堆一做是192168和一堆一是1168150和一对一是150。关键看后边12和一堆零就得到了0,所以一个IP地址和一个言码可以得到一个新的地址。

就是网络号,1918150。0,这是网络号,那么剩余这个12就是150。0这个网络里,你是第1112号机器。到这步能听懂来刷波一,就是掩码是。沿你的IP得到网络号的。

你这个你这个主机是归归属于哪个网络的?啊,IP地址是点分字节的一个字有8个20之位,全一是255,全零是0任意的一个数值,一个字节和另外一个全一的字节做202位语的话,得到它自己。

因为有一得一有这个全一为一有零得0嘛。那么得到的网络号就是代表的是这个局域网,后边剩余那个就是你是这个局域网里哪一台机器,这个这个地址是不能冲突的。那么当你知道他之后,我们再来看,注意看。

或一个路由表的概念,root降温。日存日它刚才这个路由表是什么意思?如果没有路由表,首先说上面什么是网络号,什么主机先写明了,然后下边说路由表,在路由表里边,你要给你一个概念,就是第一。

我们可以让互联网里边的每台设备。注意跟着我跟着我搜索啊,互联网当中的每一台设备存储整个互联网所有节点与节点之间的连接关系,就是每个人存向互联网所有的连接关系以及路由通路。那这样的话,你的内存会称报。

明理白我什么意思吧?那怎么可以加快寻址这件事情,怎么可以联通这件事情,这就是为什么我们的网叫做互联网。为什么叫做互联网?互联网其实有很多的。子网这个局域网,你想成局域网。啊,这一个局域王啊。

那边一个局域网。他们网络与网络的网络号不一样。如果这个局域网里边有A机器,有B机器,有C机器。这个局域网里边如果有D机器。然后E机器,然后F机器这两个局网如果不联通,是不是谁都访问不了谁?

那么怎么叫联通?那这里面会有一台机器。X主机这个主机里边有一块网卡接到了这个局域网,那么它就一定会有一个跟这个局域网在同一网段的IP地址。这台主这个设这台主机上面还有一块网卡接的是这个局域网。

也就是这台主机会有局域网,比如局域网一和局域网二的各自的IP地址,能够连,他们就是单单向看都能都能连通。然后这时候如果A想访问DEF只需要让它数据包给到X就可以了。这个数据包给到它,它就可以往这边转。

那么X对于这个局域网就来说,就是它的出路。那这时候其实你就想A还需要记录X之外的世界的所有东西吗?不需要了,它只需这个里边局网里边的所有人只需要知道我给X就可以了。这个东西叫做吓一跳。

你只需要记住下一跳,不需要记住每一跳,就他后边怎么跳都不用管,我只需要知道给了他,他自个儿再去根据自己的链接连接,再去找他后边的吓一跳,就是一跳一跳一跳的去找吓一跳。听懂明来说二波6。所以找到下一跳。

找到下一个出口很重要,那这就是路由表该做的事情。所以你会看到路由表条墨很简单,东西也很少。对吧那这个路由表是怎么回事,注意看第一行有1个111810这一个网络目标的一个网络。

后边一个掩码3-510来自于ETH0这块网卡。那这行条目怎么出来的?其实就是根据我们的配置文件IP加上掩码语文代表通过ET0可以直接连到150这个网络。未来如果访问这个网络里边任何主机。

直接通信不需要任何跳跃。因为你A和B通信还需要X怎不需要,直接他们俩就可以通信了。因为是一个局域网。但是如果想访问外部网的话,是不是找到X找到吓一跳。这时候你看后边还有这么一个条目,1918150。2。

这就是网关。举个例子,你就明白了,下边才是重点3W点百度点com。回车是不是拼通了?百度的IP址是不是61135169点125?这是百度的地址,这个数据包想拼百度应该怎么走呢?假设这个F就是百度。

你在这个局网里怎么拼它,是不是扔给X,怎么找到X的?很快速的1个20制按慰语的计算,拿着IP地址在路由表条目当中的掩码位开始做案慰语。那么61135169125和这个掩码做语算得到啥。

是不是得到了61135169。0和前面目标网络号一样吗?是不是不一样不一样。这个条目被被被淘汰。但是下面条目也不用管,也也也肯定是被淘汰被淘汰的。关键看最后一个条目是4个0掩码。

那也就是百度的IP地址和4个0做云算,得到是4个04个0和目标网络4个0是匹配。那么这个数据包应该交给谁呢?get away网关就是交给19168150。2就不用管了,他就一定能给给到百度去。

这就是所谓的网关的意思,到这步能看懂来刷边一,有是找到你的吓一跳。在你们家里边,其实就是你的路由器的19181。1,这是你家的默认网关。你凭QQ。点comQQ是另外1个IP地址,20。1194。11。

149。你会发现这个条目依然匹配不上,依然要走最后一个。你会发现,其实你只要走到最后一个条目,无论它给出任何的IP地址都能磨成零和相统匹配,也就是默认网关,也就是家里的路由器,想访问互联网。

一定走路由器,别地不用走。这能想明白了吧?哎,这个而且这个计算的过程路由表很小,条部很小,直接记了一个默认网关,所有的计算都是二进制2位语,这是CPU计算最快的方式。

第二条目不用管这个这个这个这个这个条目,这个第二条目不用管它,这个是配置里边少配了一个项,这个可以关掉的。好吧,那这时候人说了,如果在同一局域网怎么通信?比如P192。168。150。1,这个150。

1这个IP址是不是跟我同一网段,同一局域网了?我是12。那你拼1,是不是应该同一局域网回来之后是不是也能拼通平通的时候其实还是一个道理。用这个地址和这个东西做语音算,是不是就得到了150。

0和相对匹配上了,匹配上之后,一看网关没有4个0,就没有网关,不需要给网关,那就直接从网卡上中去走交换机一定能给一。

这就是局域网,不需要网关,剩下的都给扔给网关,我也不知道怎么走了,反正就扔给吓一跳,这叫吓扔给吓一跳就可以了。最终这这个网络层的原理,IP是有网络号主机号,有路由表,有默认网关,吓一跳。

所有东西扔给吓一跳,吓一跳的下一跳其实逻辑是一样的,这互联网当中的每一个节点。中间节点都是有一个路路由表的,就我A里边路由表,知道你的你是我的吓一跳。我如果是运营商联通的第一台路由器,那我后边怎么走。

应该我这里边也有路由表,就是大家都是一跳一跳一跳。只要中间的路由规则计算队,吓一跳,这个能连通,就是有网络工程师能配对数据包里一定能跳到另外你的服务端。是这意思吧?那么这个能听懂之后啊,我考你一个问题。

我考你一个问题,能听懂我就刷波一。我觉得我讲的应该是算是。

普通话的一种水平啊,没有太多的这个专业术语。如果你能把吓一跳想明白了,再来问你一个问题,考你一个问题啊。现在如果想把数据包是发给百度的,是这个IP地址,你也通过路由表。找到了下一跳是191810。2。

这但是注意现在有2个IP地址,一个是下一跳的IP地址,一个是服务端,百度的IP地址。那这时候数据包里边只能写1个IP地址。请问这个IP地址。写哪一个是写2还是写25刷起来。是写2还是写2125?

你看就有人还是有不同的答案。这这个过程我要给你纠正。如果你写二数据包里写的目标IP地址10。2。那这个数据包叭嗒如果扔给他他就是二的话,他一看哎数据包扔给我的,而且里边也看不到百度的那个地址。

那这个数据包他就想收下。但是发现自己又没有这端口号,这个包都被丢弃了。就不能写这个下跳的IP地址,那咱就写百度的呗。如果写百度的125,那你写的是这个IP地址,这个数入包怎么能扔给点2呢?

因为人家路由器不叫125,人家点2,对不对?是不是就冲就就矛盾了。那这个问题怎么解决,注意听这个问题解决,就是路由选择注意听啊,路由选择是靠网络层找到吓一跳了,但是怎么才能正确的扔给吓一跳。

这个这个链路这这个一链链的每一个跳点,我怎么能正确扔给这个吓一跳,其实需要链路层再封一层信发,这个网络层只需要封端点IP的。就是封的是百度的125,但是外边再套一层信封,那个信封套的什么地址。

套的是吓一跳的,它的硬件地址就是mac地址,所以还需要一个链路层。就为什么下面还有一个链路层。

然后再封一个mark地址,这个地址其实一一眼能看出来,就是链路层也有协议,链路层协议就是ARP协议ARP。

系列 2:P66:TCP合集:4,TCPIP 链路层原理 - Java视频学堂 - BV1Hy4y1t7Bo

杠A我听一下ARP杠A。

这时候你会看到了,还有一张表是链络层给出的,他给出了150。2,有另外一个地址,这个地址就是我们常说的max地址,硬网卡的硬件地址。

这个地址如果再套在你刚才百度那个信封的那个I地址外边,那么这个信封只要往外一扔,就通过这个地址一定能交给你的网关路由器。网关路由器一看耶,我是点2,你的地址是你的硬件地址写对了,是我的。

但是再往里一拆哦,你里边写的IP地址不是给我的,是给百度的,是另外一个地址。

那这时候才会触发它路由器的路由表,找它的吓一跳,就大家都开始找吓一跳。

能听回来说波一。我觉得这个不难吧哎。然后我先给你讲通,整个过程当中就牵扯到两个地址,一个是IP地址,一个是mac地址,硬件地址。那这里边又有一个层叫做网络层,一个叫链路层。我给你举个例子啊。

如果你有一个客户端。有一个服务端,这就是它为什么叫链路层啊,就是它词为什么这么起?首先根据刚才我讲的知识点,你起码学会了。如果你的客户端想把数据发出去,有第一个跳点,这个跳点比如路由器。路由器。

然后它路由器是有mac地址的,硬件地址的。然后呢。路由器往后肯定还有S运营商。运营商他也有他的路由器。然后有路由器的markag地址,然后假设我就把中间很多这样的运营商跳转,那一个路由器就缩减了。

就这么两个两步,然后最终就能连通。那么客户端封到数据包里边,注意听IP地址。是C的客户端的I地址发给谁,一定是发给serv端的。IP地址就是IP地址一定是端到端的数据包里封的是客户端到服务端的IP地址。

只不过它的mac地址。肯定是发的封的是自己的ma地址,以及发的什么呀路由器的ma地址。😡,这个数据包一定是这么封的,看懂的朋友原来刷波一。是不是要发这么要封这么一个数据包。

这个数据包里的麦点会驱动这个数据包怎么样?就来到了这台路由器上,来到路由器之后,路由器一看mark地址是我的,把这个mark地址先撕掉,撕毁之后看I址ip地址不是我的是人你的那开始找自己的路由表。

找到了自己的吓一跳。那这时候他的mark地址封谁?ISP的mark地址。那这时候这个数据包封出去之后,一发送就会发送到这台路由器,它就接受了。他接之后一看哎D是我的先撕毁。思鬼州一看IP地址不是自己的。

是人家百度的。如果他俩就在同一个数据中心了,同一机房了,那这时候他会做一件事情,是封一个server的。麦克丽址。那这个数据包就会正确的到达服务端。到这步这个路据包数据包跳转的过程当中。

每一跳每一跳都跳过来的,里边moddy会修改,这个能看懂学同学来刷边一。然后这里面我们把抽象一下,我们来抽象一下,在整个过程当中,谁是一成不变的在数据包里边。IP是一成不变的,也就是端到端的。

但是谁是发生变化的。mar地址在每一跳的时候都会替换,且替换的过程当中,让他们使成为了一个链表式的一个反应,叫做链路层。妈地址是链路层。IP是网络层。IP一直不变,但是骂地址一直在被跳的时候。

你要替换成正确的下一个跳点的骂地址,封住这个外层的这个这个这个这个这个线封。好吧,整体就想明白了吧。哎,先跟着我速度,走,到时候我再给你抓包演示,是不是这么一回事。

先我们先说整体整体的话是这样的一个过程。也就是说你的应用层想发一个请求头,抱歉,停住,别动你应用层的浏览器也好,什么软件也好,先告诉在在这看应用层先告诉内核,说你帮我去建立一个连接。

然后传输工层先创建了一个卧手的包,停住,别动,因为不是你发出去的这个包要先去问网络层,哎,咱那包怎么发呀,从哪个口走下一跳是谁啊,先找网络层网络层说我找着了下一跳是谁是谁,但是这时候别动。

你得知道下一跳的ma个地址就开始问链路层,链路层是不是张表,如果能看到这个映射的关系,这数据包是不是能封上了。因为你连骂地址在IP地址是不是都具备了数据包就完整了,就可以封就可往外发了。

但是如果说链路层说这表是空的,没有下一跳的骂地址,也就是可以AERP。刚D删掉192。168点150。2的mg地址。你再来看这里边是不是没有mark地址。那这时候如果说应用层找他说你别动,我去握手包。

握手包出来之后别动,我找网络层找下一跳,找他下一跳之后别动找链路层找m地址m地址一看没有,那怎么办?它会触发ARP协议去互这个局网当中请求你的下一跳,给我返回mg地址,所以这块一定会把前面都阻塞住。

先走完ARP协议才能知道他的m地址,就是先有ARP才会有三次握手数据传输,四次分手,这么一个整体的顺序,也就是说层一层是垂直调用关系,依赖关系软件是工程学层一层是有依赖的。听懂同学来刷二波一。

那这个过程我可以帮你去演示一下,到底和我说的对不对,我们是不是可以抓包去演示来走。当是这时候你要翻一个现象,ARP杠A唉,他又回来了。退又回来了,你即便可以ARP杠D。删掉1922168。150。2。

你可以删掉它。现在没有了,你再看哎,这又就又又请求回来了,他就自动的会把默认网关,没事就请求一下。或者那边会通告这一件事情,就是这哎,我怎么能保证说我在一会儿cl请求百度的时候,你刚好没有这个骂地址。

我是不是可以杠D给它删掉,删掉完了之后,立刻接一个逻辑语,立刻给我执行另外一个命令prol3W点百度点com立刻请求。那这个过程之间是没有时差的,因为都是计算机一口气先删再请求。

他请求他的时候就可以一个短片的事,没有这个m地址,这个指令,为什么这么去写,能听同学来2边6。都能听懂吧。哎,这个是这么去写,那我抓包的时候就应该能看到它有一个短暂的ARP请求的过程。

抓包的时候注意怎么去写了。现在你要抓的是两类包了,一个是ARP的包,一个是百度请求那个80的多那个包是TCPdump杠NN从接口ETH0接口抓的第一个包是port。

PORT80端口的或者哦这个包要么里边是1个80端口号,要么是1个ARP的一个数据包。ARP协议的一个数据包,就两类数据包通过一次招包都给我抓不出来。这个抓包也能听懂,也能看懂回来刷包一。好,看着来啊。

走,我先监听liston了,开始准备装包了,前边一定会触发什么删,然后有压RP请求以及请求走。

这边ctrl C结束一下,我们来看看它抓的是什么东西。这是刚才说的三次握手的包,晚上倒是不是有两个包,这两个包分别是ARP协议的。request请求 who谁有150。2。

因为他的吓一跳是他请告诉150。1就是我自己这包的啪就发出去了,请求包就发出去了。然后从网络当中接收到了一个数据包replay收到了一个数据包。这个是这个就是人家150。2回送的是在这个漫画地址上。

那ARP表就有了这个这个漫地址了,这个时候才能允许你封一个正确的数据包,开始三自握手私次传输这个这个数据传输,四次分手。这个整个逻辑就是依赖的。看浓西来烧包料。唉。好吧,层一层是那么走的,这么发出去。

那么接收啊,就都这么一个一个概念。这个通信是一个比较。基准的一个知识。都已经梳梳理梳理清楚了吧。网关要怎么。理解。我给你演示一个另外一个职愿,你找到网关的概念,找到网关的概念,找到吓一跳的概念。想听吗?

这什么叫网关,想听想想想想听。网关啊有默认网关和普通的网关,就是网关就是下跳的事儿啊,下一跳,其实就是什么叫路由,怎么去走,我这个给你演示一下。举个小例子,首先这是一台机器,这台机器你先记住了。

二机上面只有1个IP地址是150。12。然后三机器上面我们来看一下啊,有一个地址是150。13,这两台机器,这两台讯机啊,就是这个150。13和15010。12,它们在同一局域网,所以他们能并通。

是不是能拼通?你现在要告诉我他为什么可以拼通。😡,今天听了课之后,不只是常识,你也知道原理。

他为什么可以平通啊?😡,root杠N的时候,当你想拼15。13的时候,无论是本局域网还是出主机的,一定走路由表,拿这个地址和这个掩码一计算,就得到了15。0就和相手匹配上了。网关不需要。

直直接包就发出去了,走交换机就交换给了这台主机,数据包就可以来回交换了,这是同一局域网。

都是依靠的。路由表。这是在网络层,这个能听懂学来shoppper一就是我刚才讲讲讲的知识点啊,他走的协议是IC这个MP协议啊。那么这里面我知道一个知道一个特点,一个什么特点。在这台机器里边。

我if con在环回接口里边,我配了一个子接口,写了一个地址。这个地址比如说192。168点88点88,然后24这个地址。他写错了吗?啊,这个环为这个这个这个这个个这个子接口啊。

比如说3号3号子接口是这个地址,这个地址,然后241个掩码走。IO就是你的local house。录这个还回接口地址127。0。1。这这看那个地址能能明白了吧?

就是你们一般都知道本地有一个local house的loc house地址,你也知道12120127。0。21。那这地址配在哪块网卡上了,有一块虚拟网卡叫IO环回这口网卡。

ET20是你的物理网卡net网卡,以太网网卡啊,这是内核的一个虚拟网卡。这个网卡不插网线的,它是在内核里边的,就跟你的应用层11一下来一回去,没有出主机,我在这个主机里面埋了一个新的地址是88。88。

跟着我的思路走啊,那我这个这个三的主机里边是不是有一个地址,10。13,还有1个88。88,对不对?就是你前面不用管这台主机是不是有俩I地址,一个是150。13,一个是88。88。😡。

这台主机有两个地置,能看懂同学来说边一。

当这个能看懂,刚才我们在二上是不是可以并通这个12,对不对?不是从从二可以拼通13,也就是从二主机可以拼通13。那么请问二上能不能平通88。88,能平通还是不能平通,能还是不能?

去想能评中还是不能。

所有的知识就来自于一个非常非常简单的一个。这个这个原子性的一个知识点就是所有数据包能不能和别人去通信,完全考究你的路由表。那这时候来看,如果你P192。168。88。88。

你现在再看这个界面,你说它能拼动吗?

如果凭它的话,是不是拿着这个IP地址做语音算,跟他之后,是不是1。1888。0跟是不是前面是匹配不上了,匹配上之后,是不是要最后匹配上,要扔给10。2了,扔给10。10。2这里边,他也不知道88。

88在哪了,所以这包都被丢弃了,就往外扔了,就回不到这这到了到到达不了这台主机。所以是平所以是平不通的。

你看所有的知识点,就只要你会,只要你会算路由表,拿着一个地址会算路由表的语音算,你都知道这个数据包能不能通,这是第一这是第一点。

能理了吧?第二点,你就想让它通,对不对?想让它通,那么就是第二个支点吓一跳,你只要给出一个正确的下一跳,能衔接上这包是不是通了。那请问如果在这台主机把目标地址是88。88的这个数据包。

想让这个地址接收到它的吓一跳,那个能通的吓一跳是谁,是不是曾经对15013能通。

是不是先扔给他,这是他的吓一跳,他收到了,是不是就可以交给他了?

对不对?所以你路由表里缺了什么?缺了一个对于这个地址的吓一跳,对不对?能听出来刷个一,所以就是root at。host添加一个主机,这个主机是192。168点88点88,然后GTV网关下一跳是192。

168点150。13,这是它的下一跳,这是主机回车。

少了一个参数啊。atho应该是杠杠吧,杠杠hos哦。

我忘了怎么写了啊,不着急,不慌,命令只需要知道这个功能manu学习这个命令回车,然后在里面一定会有比如root at添加哦,杠house一个杠,我刚才多写了,不慌。

我是翻车了吗?不是翻车了,我就是想告诉你怎么学习,对不对?减掉一个行,是不是路由表添加一个主机,这个主机这个地址下一跳它走。

是不是又多了一个路由条目?看怎回来烧波一。那这时候你注意再家看啊,平。192。168点88点88,那这个地址是不是要和掩码做运算?因为刚刚刚houses就是主机一个主机,主机的话就是一个地址。

就是88万精确这个地址,他用4-25,4-25和它匹完匹完之后,刚好是他这个地址,这个地址跟前面正好能匹配上,所以下一跳是谁,是不是就是他?所以这个时候走是不是就通了?

路由层网络层的协议,基础协议就是这么low这么简单。但是就是这个东西支撑了现在你们疯狂每天刷的互联网。

就是你要告诉一台主机,这台主机你告诉他的路由表里边,如果想仿了一个东西,吓一跳扔给谁,有这个条目就可以了。

那学它有什么意义?你们如果超着要学什么docker啊,学什么ops虚拟化呀。😡,docker容器好学,哪儿不好学,网络IP浮动IPnet及速转换,这些才是特别难学的一个知识点。好吧,VPN是什么?

VPN是数据包,背着数据包,也就是1个IPA。然后呢,这是到你比如这是你客户端。你在香港买了买了一台主机,你在香港买了一台主机。那么这里边IP的地址就是你香港那个IP地址。但是这个数据包是外层的。

在这个数据包里边,它又背着一个数据包。这个数据包是你想访问的谷歌的那个数据包是IPX。那么这个数据包里边,因为这个数据包它的外层的IP地址是到香港,所以这个数据包一定是先到香港。

香港你的VPN服务器把外层删掉之后,看到谷歌的,再把这个数据包通过香港那边,它对互联网的访问,就直接给谷歌了。谷歌回来之后再拼完了之后再给你返回。这就是VPNFQ。就是数据包背着数据包。

听不出来说2波6,这就是IVS什么呀,天到隧道的这这这么一种。通信方式啊,就是你先到先到香港,从香港再出去。或者你在国内出差,你公司内部有一台服务器,你公司里边有一台服务器是一个私有的一个地址。

然后你公司有一台路由器是接了互联网了,并开启了VPN功能。所以你客户端跟路由器之间先走到公网IP地址,数据包呢先扔过去。然后里边其实包了一个数据包的,私网IP地址,是访这台服务器的。

所以你的这个公司路由器的VPN一定把这书包交换给你这个公司内部的ERP的服务器上,他处理完之后给到他他在丰装完再给到你的这个你的出差的这台笔记本里边。

所以你在世界上任何地方都可以访问你公司内部的一台私有的服务器。有人时候把它在跳板也可以。但是中间就是IP背着IP就跟说你们现在所有人想去全全球各地方去旅游。但是我说了,你要想去别的旅游。

你们我背起你先给你背到北京机场。那从你家到北京机场是我背着你去的,到机场,你再坐飞机再走。那你你家和机场之间就是我背着你之间就有一个特的隧道了。好吧,这里边加上加上加密,加上安全,这还是很安全的。

这就是另外一个表层和绘画层里边的那个加密的能力了。体力可挺好啊,老周那还必须的。因为我真的会背你吗?出书没出书,但是这样的课程的视频我讲了好多了。好吧,现在对网络通信这块应该是没问题了啊。

周老师有女朋友了吗?我都结婚了我都结婚了。今天没开摄像头啊,看不那个就不给你们看我长啥样了。好吗?要讲这个东西,呃,最后总结一下。其实我我你看我讲课整堂课穿插了很多的知识点。

有linux操作系统命令的一些个基础的一个知识点,以及一些学习方法。然后呢,有关于TCP协议,就是应用层到内核从划分这个两个层次,以及内核层完成通用的通信,就是无论你上面是什么什么什么软件。

你是QQ也好,你是应用传输也好,你是王者荣耀也好,你是任何的想通信的东西,你们自个完成协议的事,尤戏有有游戏的通信的协议,然后往这个外有 web的协议,然后文件传输文件传输协,你你们这块你们随便玩。

但是你们想想通信哎,找内核,内核一定帮你梳立的清清楚楚的,尤其这么一个主机和一台服务器,有多个页面打开想通信的时候,为什么传输数据还不乱。比如说我一个浏览器可以对着百度打开三个搜索。为什么还不乱?

这里边是因为有一个骚的概念。对吧s有给的概念有之后,然后这里面还有一个三次握手到4次分手,不可分割的一个概念,这是写了一个负载均衡的一个协议的一个面试题。其实这些知识如果从上往下串的话。

其实你会发现知识点是有依赖关系的,是要成体系的。这是个啥?他发了个啥?我看他发了啥。嗯。不用管它不用管它,应该是个。是傅你就想他你就想把它想成是骗子就可以了啊。那接着他这话,我来说一个事儿啊。

就是我以上讲的一些知识点,注意听啊,只是1个TCP连接上的事情。

系列 2:P67:左神算法-KMP算法及其扩展 - Java视频学堂 - BV1Hy4y1t7Bo

大家好啊,下午把kmp算法应用讲讲两个题,然后再把bf p r t算法一收是吧,下周买那车了,不然买那车,我估计一节课也讲不完,再留个小尾巴,怪恶心的是,bf p r t算法是用来干啥的。

你在笔试的时候遇到你不用用bf p r t,因为有一个已经很好的方法替代了,b m p r t是你在面试的时候遇到面试官跟他聊的,算法是给你提身价的,换句话说是某种程度上说你可以认为是装逼的。

笔试的时候不用用啊,飞火同学早上不懂,是因为你十点钟进来是吧,就这我还给你讲懂了,你不得不暗暗敬佩我是吧,嗯哼哼,笔试用什么会给你讲啊。

哈哈哈,你知道你为什么错了吗,你看你这个i是09,你这个g是08,你传进去的时候,x乘0~9,y乘零的,这有错吗,哪错了呢,这八个位置没整理对吗,i加2g减一嗯,i加2g加1a加1g加2a减一。

g加2a减二,g加1a减二,g加1a减1j减二,这个为什么错了呢,这同学是哪里哪里看到有错呀,没觉得他错呀,是哪里有错呀,嗯你是你是用什么方法得到它,错的啊。

你你你传什么位置跑出来是零,我跑出来不是零啊,你你你跑,你传什么位置跑出来是零啊,是哪些位置跑出来是零,你要知道在有限几部内码,有些位置不可能都是零,我给你看看,这不是昨天代码吗。

哎昨天什么test是吧,六个位置八位置跑十步啊,不是零二,为什么是零了,啊这时间好长诶,有些有些步数码是到不了某些位置的,它只能是零,你注意马不是在规定步数内,什么位置都能到的,理解这意思吧。

你给我个步数,我有些有些位置他就是到不了,听听听懂啥意思吧,就这个同学,8月同学,他他有些东西它就是无解的,就是没有办法去到到达的位置,你你我不知道你懂不懂,我说啥啊,位置有,但是v2 就是零。

我看一下你这个这level没有啊,哦对那就这个啊,你看你这个dp i g level,但是你往下传的是k减一哈哈,k可是一个固定值是吧哈哈所以你请你把这个这里面换成level好吧。

理解吗啊但是你要知道是真的不一定他某个位置马能到啊,你你懂啥意思吧,有些位置确实在规定步数,你这个是到不了的,那就是实际情况他就到不了,他就零种方法吗,是啊我说的也没错,但是你写的有错,哈哈啊。

嗯嗯行啊,这个还是可以的啊,当然,哎你说要是暴力方法,你们打算怎么用这个暴力方法呀,就是换一种尝试方式,有可能是什么情况呀,你你换一种尝试方法,你觉得你会怎么试啊,然后现在讲一个别的方法好不好,你不服。

你说哎你操,你光是拿暴力递归自己,在那改动态规划,我怎么知道你两个方法是不是都对,是不是都错,那就换一个方法想想怎么试,正好也时间也没开始,马上跳问题是吧,发现大家很纠结这个问题,那你怎么试呢。

你这么来行不行啊,你写个函数p是吧,当前来到的位置叫行,当前来到的位置叫列行吗,然后当前走了dk不,我把xy也传进去行吗,可以吧,这啥意思呢,就是当前来到肉column位置,当前来到rocm的位置。

还剩就这个k也别搞k了,就rest,还剩rest不可以吧,还剩rise的不问,你走完rest步之后,来到xy位置,方法数方法数多少,你是不是可以这么试啊对吧,你要注意这个xy是个固定值。

这个xy是个固定值,它是永远是你目标位置,你当前行当前列跟剩余多少步是可变参数,那么你主函数应该怎么调啊,比如说我再给你写个方法叫v3 ,你如果有个位置三的话,它让你知道啊。

他让你求走k步之后来到xy的方法输,你就应该怎么调这么调,如果我就想用这个p函数来试的话,那我一开始肯定我来到的是零零位置吗,对吧,我还有我零零,为什么我还剩k不可以走吗,我的目标永远是盯着xy。

你也可以这么试吗,无非就是这个这个这个函数中,它前三个是可变参数,后两个是永远固定的,听到他在打一行吧,可以吧,这么吃是不是也行啊,这个尤其是刚才问的那个8月同学,你你能你你你能能理解这种施法吧。

我现在重新换了一种施法行不行啊,这可能这种施法就更加的自然之灰是吧,我当前来到肉跟column,我还剩rest,不要走完,我问你走完的时候,来到xy的方法数有多少种,如果是这样定义的话。

我一开始当然从零零出发嘛,我要k不要走嘛对吧,我来到方法xy的方法我来了,来到了xy,最终的目标肯定是不会变的,这这可以理解吧,啊这个8月同学你还在吗,好那我们就先试好吧,那么那但这不一样嘛。

如果rise等于零,就没有没有步数走了,那你只有什么,只有你当前行来到x位置对吧,并且你当前列来到y位置,是不是才能够返回一,否则你就返回零吗,就是你走你已经走完所有的步数了。

哎你你停留的位置正好是xy,那你就找到了一个点数,就是有效方法,找到了一种是吧,这种方法叫你之前走过的决定,如果你0度可以走了,你来到x没有来到xy位置,那就零种方法吗,这是不是也对应了。

接下来你怎么加这个函数,你一样一旦有越界了,你就返回零,但是是什么越界了,这个可不是可不是xy越界了,是肉跟column越界了,对不对,因为肉跟column是你现在的位置,xy人家是个目标啊。

所以你怎么改呀,肉行数如果小于零或大于九,然后是列数如果小于零或大于九,列数如果小于零或大于九是吧,但小于零或大于八,你就返回零,接下来你该怎么走,你不是一样吗,你你还剩rise的步可以走。

那你还是八个位置吗,你就看你call了吗,可以蹦到哪个位置上去吗,八个八种可能性吗,对吧,你这跟column可以往八个位置上跳,跳完之后他们的rise要减一步,没错吧,那那那这个那这个逻辑不还是这个吗。

你把这坨拷贝过来,但是里面你要给他换成啥呀,给它换成现在的p函数的描述,是这意思吧,我先把他水听过来,看的比较多是吧,没事我给他列一下,但是这里面呢是我肉要往下蹦的位置,也是八个位置,x全换成肉。

其实没什么区别,跟他刚才,但是他确实是一种别的事法,外墙换成colum,剩余步数全减一,因为我现在蹦出了一步嘛对吧,我有八种泵法,我有八种往外蹦的方法,所以它往下的剩余步数都会减一嘛对吧。

但是你不要忘了我们这可是p函数,所以所有的函数变成p,p函数还要再补一个参数,这个参数就是x y都是固定值,所以后面要补xy永远都不变,因为目标永远是他,是这意思吧,全部补一下,或者逗号拷贝上来。

这恐怕应该也对是吧,我们把它调一下位置,三,对吧,没毛病吧,听懂他还打一啊,你你怎么试都行,对不对,没有变化啊,它它上一种释法依然是三个可变参数,后面两个是固定参数,它依然不影响它状态返回值。

但是你这张动态规划表,你要想做的话,你就返回00k位置的值作为你最终的答案了,没错吧,他这个是法不同,最后决定和动态规划样子是不一样,但是其实是一码事,不懂的话,看一下基础班你就懂了,好吧啊。

这个我们已经过去六分钟了,但是感觉但是同学有点早上有点没听懂啊,或者有的同学可能下午不来了,那我们现在就讲一下k m p算法的应用,下午的课如果你不会开mp算法其实没啥啊,因为你也能听懂啊不行。

第二个题目可能会哦。

没事啊,你还是能听懂的啊,举个例子啥意思啊,就是我比如说我现在做一道题,这也是一个经典题目,哎呀我说一个字符串啊,我先给你叫spring 1,4x1是啥呢,123456这个字符串,那么我说它呢。

它有很多的旋转词,什么叫旋转词,由它可以变出很多旋转词来,他自己是自己的旋转词,这种旋转方式叫我没有旋转,还有就是我把左侧部分的一整体拿到右边去,会形成一个旋转词,234561,这是它的旋转词。

这你怎么旋转的,左侧一个长度的转到右边去了,它还有个旋转词,左侧两个长度的整体转到右边去,345612,三个长度的也可以转到右边去,456123,四个长度的也可以转过去。

5612345个长度也可以转过去,六五啊,612345整体转,那就等同于这个你整体都拿到右边去,那不还是他们吗,好我说一个string,它有这么多旋转词,这都是它的旋转词,那我问你,我给你两个字符串。

string一跟string 2,请你判断这两个字符串是否互为旋转词,如果是返回true,不是返回false,听懂题同学打个一,好那你说你暴力方法怎么解,你暴力方法你就把字符串所有得到的旋转词全部生成。

然后你再比较跟spring 2哪一个string 2,如果它属于任何一个,就属于旋转词,我说一个数,我说12345和454561231定是互为旋转词的对吧,456把他三个部分挪到右边去。

不就得到原来了吗,我把我的三个部分挪到右边去,不就得到这个嘛是吧,所以旋转词一定是相互的,那我们来想一下这个暴力方法,我们要这个暴力方法时间复杂度是啥呢,我们来估算一下,你怎么得到12345。

你你你起码得把这个拷贝一遍,b o n的时间拷贝出来,这个或者你自己不拷贝,你就你自己就当做第一个旋转词,那好我就认为你是b o一的,你得到12345这个代价必购一的没问题吧,那你怎么得到23456呢。

啊234561呢,这个恐怕得拷贝了吧是吧,你你你你想你啊,换换句话说,我们完如果完全如果我们完全不不不去生成这些旋转词,我们怎么判断一个strong是否互为旋转。

比如说我说这个123456和561234,怎么判断它是否互为旋转词,是这样的,我从一出发往后走六个,如果跟你都对上,就认为是旋转词啊,对不上,我从二出发往后走六个,我怎么走六个呢,转到六之后。

我再写一个类似于转回来的代码对吧,我二对你的五一下就没就不对了是吧,所以就不用转了,然后我从三出发便利的时候,我再转回,就有点像循,有点像循环数组那种方式,有点像循环数组那种方式。

我往下咽跟你同样多的字符串,如果每一步都对上,咱俩是旋转词,比如说我练到这儿的时候,我五六转回来1234跟你的561234正好一样,那么我就知道我们两个互为旋转词,这个东西是很复杂的。

为什么你一共有多少个位置啊,n个位置你一共要遍历多少字符串呀,每一次的时候你是不是都要遍历一个n的字符串呀,所以整个复杂都b勾n平方,是不是没毛病啊,那肯定这个暴力解肯定是好理解对吧,也不难写这个代码。

但是这也太差了吧,听到他在打一,好首先你要知道啊,我想判断两个字符串是否互为旋转词,长度都对不上,你就可以直接返回false了对吧,所以最大的过滤器是长度一旦不一样,你就不用判断了,你判断什么呀。

旋转词一定跟自己原来的长度是一样的,能听懂吧,听懂同学打个一,就你你连长度都对不上,他俩不是一个长度,你还判断啥呢对吧,直接返回false了,所以我们讨论的一切都是在两个长度一样的情况下好。

那么我们说这道题怎么样做,相信大家也也见过这个题,见过同学你也不用说见过了,反正我要讲了对吧,怎么做,假设我就判断123456和561234是否互为旋转词,我干嘛,我把123456生成它。

自己拼自己之后的一个大字符串,123456,再接一个123456,我给他增一倍,你长度不是六吗,我就看你这个字符串是否是这个大字符串的子串,我有一个字串叫56123,我就说他俩互为旋转词,就这么简单。

不管你是什么,spring一和spring 2,先判断长度长度不一样,直接返回了,如果长度一样,生成两倍的string,一加string这个字符串。

然后用k mp算法看string 2是不是这个大字符串的子串,这事就解了,流程听明白,同学打个一,那为什么呀,为什么我就可以说就这个结论呢。

123456再接一个,123456,注意看从一开头长度为六的串,是不是它的旋转词是从二开头长度为六的串,是不是它的旋转词也是从三开头长度为六的串,是不是它选的词也是从四开头长度为六的串。

是不是也是旋转词,也是从五开头六长度的,也是从六开头六长度的,也是为什么我的方法是对的,因为一个串加一个串的形式,可以把所有旋转词全部拼出来,那你说现在某一个长度为六的串式子串,它可不就是旋转词吗。

听懂同学打一,就因为一个串拼一个串之后,所有旋转词我们都没举了,只要是长度为六的任何一个子串都是旋转词啊,你觉得有更简单的方法嗯。

那,我们以我们spring一长度为n string 2长度也是n,他拼完之后是个2n的长度,我们k mp算法已经做到b格n了,你觉得还有更好的方法,他能不能在log n内解决,就问你这个问题。

你怎么可能连字符串都没看完,一遍就能确定spring 2是不是它的旋转词呢,那是不可能的,所以没有比这个复杂度更好的方法,听我同学打一,懂懂我说啥意思吧,啊你就要说小常数,那小常数这个事儿。

那就属于是扣的问题了对吧,我们说这个啊小常数这个事那就属于扣的问题了啊,注意啊,给大家提醒一句,你们在这看到那个index of方法,他不是他后台,不是k mp。

不是他后台是一个比k mp继续优化的一个算法,叫什么名字,我忘了他比k m p拥有更小的常数,但它是一个别的算法,但它时间复杂度也是b格温,至于这个index of底层是什么算法,我们就省掉了。

因为k mp已经足够经典了,听我同学打一,in the excel方法,底层不是k mp,它是一个比k m p更加优化的一个解法,但是它的时间复杂度还是b格温,只是比k m p优化的继续小常数啊。

你想要小长寿有是吧,你继续去学吧是吧,当然我跟你说没必要了,因为你们面试难度这都已经线性了,还要怎么样对吧,再有其他的算法,你有精力你就去研究,但是它对于你面试的边际效应其实已经非常小了好吧。

就这么一个东西,我们的课是非常功利的是吧,如果给你培养能力的话,我去讲a s m8 不好吗是吧,那你们这个班为啥想得到什么呢,最快的具备刷题能力嘛是吧,所以必须用非常功利的方式来讲啊,好我们再讲一个题。

什么题呢,我们提到过一个问题,就是这个我给你两棵树,一棵树叫t12 叉树,我们在讲二叉树的时候,需要提过这个问题,但是没有具体展开,基础班的时候,其实提过这个问题的,但是没有,刚刚是没有展开。

我给你t一这棵树它是个二叉树,我怎么给你一棵二叉树呢,我给你头节点,我给你t一这棵树头节点害的一,当然你就可以往下找到所有节点了,是这意思吧,我再给你t2 这棵树它也是一棵二叉树,我怎么给你一棵树呢。

当然就给他的头节点head的二,啊我问的不是head的二,是不是had一的子数,我不是问这个问题,我问的是hd 2所衍生出来的值的结构,它的对应这个关系是不是t一某一棵子树的结构关系,举个例子。

比如说765这边来个四,这边是3t1 ,这棵树是亮的,我这个hd 2有可能它这个节点跟它是不共用的,他俩是独立的数,但是如果我某如果我的结构是五四好,那就返回true,为什么呢。

因为t一这棵子树这个结构对应关系和t2 这个结构是一样的,我就返回tru,如果我这边是五四,我这边是543,返回false,因为我没有任何一颗子树叫五四。

我只有一颗子树叫543指数要求所有东西都要从一个头几点出发,下面全都要的,这叫子数,你不能选择把这个三忽略掉,那不是子数,那叫子拓扑结构,所以这个题就问你,我给你t2 这个这个数的一个结构。

你t一里面是否有一颗完整的子数结构跟它一样,有的话返回tru,没有任何一颗子树的结构跟他完全一样,返回false,这个提议听懂的同学打个一。

好这题怎么做,我们举个例子,这个指数是这样的,上面的值是字符串,可以吧,或者你字符串你理解不了,那我就是一个比较大的值,这可能是20,这个是40,这个是70,这个是30,这棵树假设t2 这棵树40。

30,我们干嘛把整个这棵树先序方式序列化,直接讲啊,我想想怎么给你讲啊,先讲暴力的对吧,我按照按照按照按照按照节奏来是吧,我们按照仪式来是先讲暴力的,暴力怎么办啊,暴力的就你就定义一个函数啊。

直接看吧好吧,在这儿呢不理解,暴力解在这儿,直接就是问你big这棵树头节点是b是吧,以头节点啊b做,头节点的数,其中是否有某科,子树,某棵子树的结构适合small为头的数完全一样的,可以吧。

就问你逼格做头节点的数,它的内部是否有某棵子树的结构和small为头的数是完全一样的,如果你这个定了,那你主函数直接调把head的一传进去,head的二传进去,它不就行了吗,你不就是想求这个问题吗。

我就给你写出这样的递归好不好,那怎么做来看,如果small已经等你空了,是不是任何数都包含空数结构是,所以返回出,如果死猫不等于空,就继续在死small,它不等于空的情况下,开继续,如果死亡不等于空。

如果b格已经等于空了,空数是不是不可能包含一个不空的数false,那如果这个衣服还没有返回传下来的,传下来的语义就是说b也不等于空,small也不等于空对,没错,前两个好懂啊,任何数都包含空数。

出任何空数都不可能包含一个不空的数,false如果b也不等于空,small也不等于空好,这个方法是啥,解释一下,这个方法是说,为了怕你有歧义,我们不妨设啊,就是害的一根head 2吧,好吧。

这是我们b跟small理解这个方法是啥,这个方法是问你head一为头的数是否在结构对应上,完全和had 21样,它不它已经是不探讨子数的问题了,就是问你害的一整棵树是否和had 2整棵树的结构一样。

我们先不管它,假设它就是一个黑盒,所以我先判断以b为头的指数是否它就是等于small的,如果是,那当然是处,啥意思呢,就是我整棵树给你整棵树压根就是一个结构,我就返回处,如果这个没中,我怎么办。

我去讨论b格的左数上是否包含猫,或者b的右数上是否包含调用大过程的,自己看到了吗,我左树上是否如果有包含small,我就返回true,我右数上如果包含small,我也可以返回true。

两个有一个为true,我就可以返回true,这个黑盒你先不用管怎么写的,怎么写的,整个流程听懂他在打一,不同学打二好吧,接下来只剩这个黑盒了,你怎么判断两棵树的结构完全一样呢,head一等于空。

head的二不等于空,不就完全一样,had一等于空,had 2不等于空,那就不一样,force had一不等于空,had 2等于空,也不是完全一样,force hide一等于空,head的二也等于空。

完全一样,都是空出had一的值,如果不等于had 2的值,那结构就不是对应false,到了这一步就等于说我had一跟head 2有值且验证通过了,那我怎么保证两棵树完全结构一样呢。

我的左数得等于你的左树结构,并且我的右数得等于你的右数结构,这才叫完全一样,所以这是一个大递归,套了一个小递归,小递归自己调用去判断两个结构是否完全一样的方法,听完他再打一,这个复杂度是蛮高的。

那我问一下这个复杂度度有多高呢,啊怎么估计呢,有同学知道吗,这复杂度应该这么算。

我给你举个例子,你就懂了,压根就全是1t1 n个节点,t2 m格节点节点,别看刚才写的花里胡哨的,我们刚才的方法实质就是我回头跟你的头诶,咱俩对上了,我这左孩子跟你这左孩子唉,咱俩对上了。

我我这有孩子跟你这幼孩子挨打俩对上了,但我下面还有东西,你下面已经没有了,说明我的这个头匹配失败,这只是否定了这个做头的时候指数匹配不出来,接下来我这个头对你这个头,我这个一对,你这个一,我这个一对。

你这个一,但我下面还有东西,你没有了,匹配失败,我这个一对你这个一我这个一对,你这个一我这个一对,你这个一,但我下面还有东西,你没有了,匹配失败,你一共有n个节点,每个节点都做个头。

最差情况下要路过m个节点,b o n乘m的,别看写的花里胡哨,他就是这个复杂度,听懂同学打一,好啊,所以我们想一下我们在基础班提过的可能是特别微不足道的一句话,我不知道你还记不记得。

我在基础班第一节课的时候,我说了一句话,我叫你分析一个算法流程的复杂度,前提是对这个算法流程足够熟悉,你会代码写代码没用,你哪怕写出来了,你不一定能分析复杂度,需要对这个流程足够熟悉才能分析出来。

听我同学打一就,你只有把整个流程的本质全抓清楚,你才有可能去分析复杂度,理解这意思吧,你看看我们刚才写的花里胡哨的,你敢做,哎呀好暴力啊,以至于我都不想算它复杂度了,实际上没有那么难算。

你要是对流程足够清楚,你可以估算出来的复杂度,不用看代码吗,可以不用看代码,可以作为辅助,但实际上本质是可以不用看代码分析复杂度的,你把伪代码写出来,足以让你分析复杂度了,足矣了啊好。

那我们先来讲一下这个我们想用什么,用k m p对吧,我怎么用k mp,t一这棵树把它序列化成一个数组的形式,先序的方式序列化t2 这棵树把它先序序列化成数组的形式,在数组里面每一个位置的值。

甭管就单独一个位置的值,不管它有多长,我就把它认为是一个字符,那么我就可以把这个数组认为是一个字符串,啥意思,零位置,你这个二叉树的值是1000,我我我就认为1000他就是我的一个阿斯卡码。

他就是一个字符,懂啥意思吧,下面这个这个值可能是17,我就认为这个17它就是一个字符,我去,然后我要补一个空位置,我要认为这个空字符它就是一个字符,懂啥意思吧,我把t一变成一个一个数组。

我就可以认为它是一个字符串,我把t2 也用先序方式编序列化,也认为它是一个字符串,告诉你,如果这个字符串是它的子串,t21 定是t一的子数,听懂的同学打一,来那我们来简单看一下这个代码。

来看,先序方式序列化大的数我就会得到一个由字符组成的a release,这里面是含有空的,因为我们序列化的时候要拿空去站位,不懂的同学翻二叉数序列化的课,基础班讲过了,先用就是用,也要把空算上。

big序列化成一个由string组成的一个字符串,里面可能还有空的小数,也把它转化成一个字符串啊,一个啊一个字符串组成的阿瑞利斯塔对吧,哎呀还是给你举个例子吧。

好吧嗯,他怎么序列化,先序方式,先来个十,它是字符串形式,所以十个字符串,下面我要补空的位置,所以这个数组中下面是空,我要补空的位置,所以这个数组中是空七,52,我要补空的位置,我要补空的位置。

我要补空的位置,这是它序列化的结果,十字不串三字符串空空,七字符串52字符串空空空,它序列化,这是我的t275 52,补空补空补空,我就把它认为是一个大字符串,第一个字符叫十,字符叫三这个字符串。

第三个字符叫空,第四个字符叫空,第五个字符叫七,这个字符串,那个字符单独字符叫52,这个字符串理解吧,我就可以认为一个一个都是字符七,52空空空这个字符串属不属于它的子串,如果属于t2 。

就是t一的子数一定存在这样的关系,不管你这个t2 差在哪都是一样的,插在书上哪个位置都是一样的好就这个改法,为什么,因为先序序列中一个字一个序列化的字符串只代表唯一的结构理解吧,因为先序序列化的时候。

一个子串它只会代表唯一的结构,如果我说我的大串中包含某个子串,就代表原始结构中包含我t2 的结构,听懂同学打一先叙方式,序列化是没有歧义的,好啊,那么呃这个有些同学问我的问题。

其实就是这个coding coding问题啊,coding问题,有没有有问题,我看一眼,别有些问题我错过去了。

先生成b的序列就是这个玩意儿。

再生成small的序列,就这个玩意儿,为了让我们代码看起来比较明显一点,string原来它是一个字符类型的数组,现在string变成一个字符串类型的数组,我就把i位置的字符串认为是一个字符行吧。

生成一个这么一个长度的string,生成一个这么长度的match,接下来k mp去吧,k m p简单做一个改写,这个字符串如果等于这个字符串x加加,y加加,如果next的有东西,如果x那如果没法跳了。

x自己加加,否则y向前跳,不就是改了两个字符,怎么比嘛,现在是字符串来比对吧,next数组的时候,不就是问a减一的字符串和cn位置的字符串是不是一样吗,该怎么做跳转还怎么做,跳转没有区别。

那怎么叫椅子eq呢,如果一个为空,一个不为空不相等,如果两个都为空相等,如果两个都不为空,但值一样相等,不就这么个事儿吗,两个都是向空的处,如果一个为空,另外一个不为空的false,如果两个都不为空的。

问你a是不是一cos b,这不就是椅子eq方法吗,所有方法其实还是k mp,只不过我把字符串延展了一下,听我同学打个一,好有同学会问我,为什么要把改成数组的形式,为了防止一些歧义,我给你举个例子啊。

啥例子呢,我给你举个例子啊,如果不这么干会有什么问题啊,我得想一个例子,如果你就把它序列化成字符串,它是什么,一诶好像不会有问题,等会儿啊不对,一要加下划线的啊,我想想啊,就是有可能会产生歧义啊。

你想个例子啊,首先有一个例子是很好想的,就是如果,想想是什么意思啊,就是如果我把它单独把它序列化成一个字符串,它匹配的时候可能会有问题啊,这个例子我不是很好想想一下啊,一时间想不到了啊。

就是他有可能是有问题的,然后你其实有这种好想的例子,就是万一你这个节点它们里面本身值是带下划线的,你如你不用数组表达的话,你自己下划下划线表达的话,你要给它序列化成一个字符串的形式。

因为你这个假如某个节点值里面是带下划线的,你一切就切断了,这个听懂同学打个一这种例子还是比较明显的,懂啥意思吧,就是节点中如果它这个它这个no的类型是一个字符串类型的,值里面是包含下划线的。

你你其实你这样序列化,你反不反序列化时会出现问题,这就是我们为什么一直强调,我们要用数组的形式来表示一个序列化的结果,但其实如果要是集中没有下划线,其实应该其实也会出错,但这个例子我一时也想不到了啊。

就哪怕你节点值是不包含下划线这个字符的,它它其实也会出错,但一时间我找不到这个返利了,当然就直接记成这样行不行,你你就认为每一个东西它进到数组中的一个位置,甭管它多长,我就认为它是单个字符串。

哦哦我想到了我想到了。

它序列化的结果是11020下划线三,悟空三下划线补空下划线,补空下划线,补空下划线啊,我去的话结果是二零下划线三,下划线补空下划线补空下划线补空下划线,我是你的子串,但我不是你的子数结构,听懂同学打一。

经历了一个贤者时刻是吧,我倒杯水去,有没有有没有完全一头雾水的同学,那估计是我们序列化那节课,你没听到,好有的同学会诶,那你之前补一个呢,之前补一个应该是没有问题的。

之前补一个应该是没有问题的啊,就说这个哪怕就是1020,什么叫之前补跟之后补我都补,那我这个就是下划线,1020下划线我都补,下面是三下划线,三下划线空的时候我都补下划线,空下划线这边也是空,空下划线。

空下划线这边也是空下划线,空下划线,如果你如果你前后都补的话,是不会有问题的,因为你这样就严严严格的区分好了,一个值所在的位置在哪,听我同学打一,啊一定的啊,这个是一定啊,也也啊对一定的。

你比如说刚才那个东西就可以区分了,我这是20,这边是三,那那它其实会区分说我是下划线,20下划线,然后是下划线,三下划线,然后是下划线,空下划线,这边也是下划线,空下划线,最后是下划线空下划线。

这是不会有歧义的对吧,我没有一个子串叫下划线20,我只有是20这套这个,所以它是不会有歧义的,你别搞那么麻烦,你就搞成数组不香吗对吧,为什么非得逼我举那么多返利是吧,为什么要逼我怼你是吧。

听我同学打个一,哈哈哈哈,数组是不会有问题的啊。

嗯好啊,这个我们终于给他绕过去了,那么我们现在讲这个b f p r t算法,他解决的是个什么问题,大家在面试中经常遇到这个问题,简直玩到死,又是一个跟kp一样会玩到死的一个东西,啥呢,在一个无序数组中。

怎么求dk小的数,注意这个k是从一开始的,我的第一只有第一小,第二小,第三小没有第零小,第一小,第二小这回事儿,如果你规定好有d0 小,那他这个k就从零开始,看你怎么规定。

往往它规定的地基小事都一是从一开始的,那么在一个无序数组中找到dk小的数,我们知道排序肯定可以直接拿出来,那就没意思了,我的问题是在无序数组中求dk小的数怎么样,b格on拿下,听到他在打一。

有没有之前有问题啊,我看一眼,翔龙同学为什么要补空,你可以去看一下二叉树序列化的内容,因为你不补空的话,二叉树有可能啊都是相同值,结构不同,但可能得到序列是一个,所以这就是为什么我们我们要补空空。

这就意味着后续没有了,它相当于在结构上我占住一个位置,它代表没有后续的意思,这就是为什么序列化的时候要补空,只有补了空之后,序列化才代表唯一的结构,理解这意思吧。

可以看一下我们基础班的那个序列化的那一节,啊然后,其实这个问题它已经有一个非常好理解的线性时间内拿下的方法,它就是一个b o n乘log n的算法了,对不对,他什么思路呢,我随机选一个数,随机选。

然后利用荷兰国旗问题,比如我随机选这个数是m,那么我们利用荷兰国旗问题,一个b和n的过程,可以在这个数组中把他的小于m的放左边,等于m的,放中间大于m的放右边对吧,然后比如说我的下标是29~31。

这个下标范围上是等于m的区域,这个我们也是也是可以拿到的,没错吧,如果我们要求d,七小的数就说明我们选的这个划分值,它没有命中这个k接下来我们在左侧再随选出一个m撇,再把它小于m撇的放左边,等于m撇的。

放中间大于m撇的放右边,再有他这里面有没有命中k,不过我要求的是第70小呢,那我就在右边继续玩这个partition,一直到命中到了停,听到他在打一,那么这个他是不是快牌,它不是快牌。

我我快拍,我是不用动的,左侧要进一遍递归,左我测进完递归之后,回到这个,我要在右侧去进一遍递归,它的时间复杂度是b o n乘log n的,而我们这个过程是什么,我们这个过程是在数组中随机选一个m。

一旦我划分出小于m的,在左边等于m的,在中间大m的在右边,接下来我要想命中这个k是左右两侧,我只会进一侧的,另外一侧我看都不看了,听懂同学打一,怎么选,怎么选这个m随机选,随机选一个数,就是随机选。

那么这个的时间复杂度它已经是b一个o n了,注意这个是怎么来的,它是根据概率累加来的,什么意思什么意思,就是大家想一下,如果我在一个数组中,我选了一个数m过了一遍荷兰国旗,问题是一个b on的,对不对。

如果这个m选的非常正中间,接下来左右两侧递归,它只进一侧的,没错吧,那么左右两侧规模是多大呢,基本上就是二分之n,这m选的非常靠中间,那它左右两侧的规模基本上是二分之n的数据量。

所以这个表达式就是t n等于t2 分之n一倍的t2 分之n,这左右两侧递归只进一边,没错吧,tn等于t2 分之n加上一个b o n,这个很明显它是一个b o n的方法,为啥八四公式我们在基础班讲过了。

对于这个公式来说,a等于一,b等于二,以b为底,a是小于这个次方一的,所以如果你这个划分值的位置打的非常的正,那么我后面的过程他就会收敛于b格温。

如果我这个划分值打得非常之不正,比如说我这个m算完之后,我是来到整个这个范围上最左边的位置,接下来就要面对的是后面这些所有的数,你继续进递归它就变成tn等于tn减一,是后续的规模,你这个m打到这个位置。

我我我我m已经没没有命中了,我剩下的数据规模是多大呢,是n减一这个规模,那tn等于tn减tn减一,加上一个bn这个什么复杂度,一个n平方嘛,很明显就是你这个位置过了一遍,搞定了一个位置。

你再过一遍搞定了一个位置,再过一遍搞定了一个位置,再过一遍搞定了一个位置,他很明显是个b勾m n平方的,所以我m位置到底打在哪儿就是个关键了,他打在中间位置,它就是收敛于b o n的,打得非常偏。

它就是退化到b勾n平方的,到底以哪个为准呢,因为我是随机选的m,所以好情况跟差情况都是概率事件,这个概率公式用非常麻烦的数学表达式写完之后,一球还是收敛于b o n,听懂同学打一。

如果你是基础班跟下来的,你一定知道我在说什么,对不对,给我点提醒,是不是这样,大家可以发表感慨,是吧哈哈,如果你是基础班跟下来的,你一定知道是啥意思,这种方法他就已经足够优秀了。

这种方法它已经足够优秀了,但是他是用概率累加的方式求最终复杂度的期望,你在笔试上如果遇到了,你就这么写,已经可以说来到b格温了。

我来看一下有没有这个方法,我看一下啊,啊对对对,还想再讲一个方法,这个看一眼这个哎,这就是我们刚才讲的方法,process 21会儿把这两pos一好吧,pos 2啥呢,就是阿瑞,i arrl到l范围上。

找对于index,塞尔瑞l的r范围上,如果排序的话,但不是真的排序理解吧,如果排序的话,而不是真的去进行排序,如果他只只管这个范围上,其他范围不管其他范围也不参与我们的,如果排序也不参与。

连想都不想对吧,如果排序的话,找排完序之后,位于index位置的数,而且我告诉你这个index,我告诉你这个index他一定在l2 范围上,一定在l2 范围上。

就index一定是l到r中的一个位置位置理解吧,不是值,是位置,我们processor的方法,你说你这个方法定了,你主函数怎么调啊,你不是号称要在二位上找d dk小的数吗,那你主函数怎么调呢。

主函数其实你就只能调用这个process 2啥呀,re从零到n减一范围上位于如果排完序之后,位于index是k减一位置的东西,返回就是dk小的数,听懂他打一,是不懂同学就打二啊,我看到会回你好。

那么我们来看这是怎么做的,如果l已经等于二了,我要告诉你,index一定在这个范围上,别考了,你要的就是唯一的这一个数,这可是一个强大的潜台词,就是我一定能够保证index它就是l到r范围上的位置。

你在l等于r的时候,其实就就已经就说明什么,你到这一步就是l等于r等于index,一定是这个关系返回这个l位置的数就行了,这是我的base case,如果你这上面不止一个数,不止一个数,我们干嘛。

这在干嘛呢,l加上一个随机位置,这个随机是怎么随机的,这个蓝色的这个东西啥l加上一个啥,这个蓝色我是怎么做的,这个随机l其实就等同于l加上一个零到r减l,到r减l等概率随机的一个值。

不就是随机选出一个数吗,你l如果加零的话,就把l选出来了,你说l如果加一的话,就把l加一选出来了,你l如果加r减l的话,就把r选出来了,所以这一句就相当于我我等概率随机选了一个值来做他的划分。

听懂他在打一,干嘛荷兰国旗问题,它返回的是什么,返回一个数组,这个数组长度一定是二,我告诉你这个range数组啊,它一定有个range,零和一个range 1,除此之外就没了。

他这个返回一个长度为二的数组,这代表什么呢,这代表l到r这个范围上,我问你划分值在这个范围上的左边界和右边界在哪儿,举个例子,比你l到r范围是0~1000,假设我以某一个划分值,荷兰国旗问题划分完之后。

等于这个划分值的范围是70800的,在01000这个范围上划分值,最终它是坐落在在这个范围上的,70~800这个范围上好禁止零就是70,range一就是800,这个就是利用荷兰国旗问题去做划分。

等于划分值的区域是从哪到哪记录在这个range里,同学打一,都是基础班讲过的啊,那我就看,如果index是大于等于左边界,但小于等于右边界的,哎,命中了吧,不是我选的这个划分值命中了呀。

这个index正好命中了它的范围,返回这个值就行了,没有后续不走任何递归,如果我这个index是比我左边界还要小的,啥意思,那你荷兰国旗问题画完之后,他的这个命中是在划分值,左边的是小于划分值的范围上。

你给我继续去玩儿,继续去考察命中的问题,所以调用自己l这是啥位置,第一个等于的在前一个位置是不是小于区域的最后一个位置,所以这是小于区域上,你再去考察index在哪去打。

index小于睿智零的时候没命中,你既不在它中间,也不小于认知零,那就只剩下index大于认知一的时候,那就是右侧有右侧的范围上,你给我命中去吧,就这么个代码啊。

所有的code包括这个partition都是给你讲过的,听懂他打一,这就是我们说笔试你怎么做,你就怎么做,再打一的同学,我要我,我要对你表达一下敬意,你现在能够很顺利地听懂,绝对我绝对相信你。

基础班掌握得非常牢固,你们下了功夫的啊,正好在边界上呢,注意没有所谓的。

正好在边界上啥意思,我一个数组中,我假设一个数组中,假设我拿70这个东西做划分值的,他给我一个范围,假设17~89这个范围上躺着全是70,就这个意思,你你说你要index,我要位于你处。

你排完序之后处在17位置的数,那不就是命中了吗,说我index想要你排完序之后处在89的位置,那不就是命中了吗,如果你小于17,你左侧给我老老实实递归去,如果你大于89,你右侧过老老实递归去。

他没有碰边界这回事,所谓的等于区域的左边,这个右边界指的是等于区域第一个数坐落在的位置和,等等于去最后一个数坐落在的位置,听筒下打一没有边界这回事儿,就是命中没命中,理解吗,bf p t算法是啥。

这个东西它已经是b格温的了,笔试的时候就用它就行了,绝对快,那么bf p r t算法是啥呢,f p bf p r t算法是说哪怕你不用概率求累加,不用求概率,最后的长期期望。

我也能让你收敛到b o o n用概率的方法正,也不用概率的方法设计,我就让你严格b格温,这就是b f p r d算法,他跟我们刚才刚才介绍,就刚刚介绍这种方法,时间复杂度是一样的,只是人家是用概率。

而我bf p t算法利用严格的流程,我就可以告诉你它概率都不用概率这回事,直接收敛到b格温,这就是bf prt算法,它的意思打一知道bf t2 t算法要干啥了吧,你不理解概率也可以收敛到他。

f p r t算法,它名字就叫bf p t算法,这是mit 5个大牛名字的简写,首字母简写抽出来的算法叫bf p r t,啥意思吧,如果他的全名就把所有五个人的名字都拼出来的算法。

人家正式名字叫bf p r t简写叫五个好朋友算法是吧,叫无有算法,是不是,说起这个给大家吹个蛋啊,跟bf p t算法是非常有感情的,当年啊这个从美国回来之后啊,突然间有1年很想去美国玩一圈儿。

然后旅游一下是吧,也不打算长期生活旅游一下嗯,对我来讲旅游还是挺好的是吧,然后那年是符合历史大潮是吧,这个奥巴马一上台宣布,中美之间旅游护照一下子能搞到10年内不用再签,你要能搞到10年内不用再签。

说大家一看这个我靠时间好长啊是吧,就挺不错的,就是在这之前,美国护照是2年以前的,2年过期之后,你得重新去大使馆重新交一遍钱,重新过一遍面试,但是那个奥巴马那个到那个时候他是完全宣布10年内免签。

你说免签吧,就你只用办了理由签证之后,只要填一个表就可以去了啊,那就那当然申请的人就很多嘛,有些他有些可能他不去美国,但是他觉得哎呀这个办一个签证,想去的时候就能去,而且也不用抢时效的问题。

10年比2年长多了是吧,结果我也去了啊,我正好想到那个时候去美国玩一圈儿去,卧槽我那天看了就感觉不对劲,宣布这个政策没有两个月,已经到冬天了,大使馆门外人山人海,我也想玩了,但通过率肯定非常低。

他是临时在那边,我要去美国有哪些目的,结果眼睁睁地看着我前面五个人,他们是冬季回来再回家打吧,打算着春季开学的时候回去继续上学的人,五个人被拒了三个,我想就完蛋了是吧,这不拿点硬功夫,看样是过不去了。

然等到遇到我的时候,他说你为什么要去美国,我说我去美国波士顿玩儿,他你为什么要去波士顿,我说我是一个在国内算法教学的一个老师,但是当时还在工作,只是一开始已经承担开已经开始教学工作了啊。

就是刚开刚刚开始讲课的时候,还在单位打工的,但是我说我是在国内教算法的一个老师,我非非常崇拜一个算法叫bf p t,他是mit 5个大牛搞的算法,我想去mit的校园,就在波士顿嘛。

想去那里缅怀先贤的足迹,我那个面直接就是计算机科学的,他一听啪盖个章,欢迎你是吧,人才是吧,赶紧他妈过去是吧,这个这个是一个真的蛋啊,这个是这个不是在跟你开玩笑的啊,这是我当年的真实经历是吧啊。

你看这个你你要是会一些算法装逼都是香的是吧,你这是,啊好我们先来扯这个算法是吧啊,再把这个打回事啊,刚才那个流程是说刚才那个流程是说第一步飞机,一个数,假设它叫m,第二步,荷兰国旗问题。

小于m的放左边等于m的,放中间大于m的放右边,而且知道它的左边界和它的呃,知道他自己的左边界和它的右边界等于区域的,第三步是如果命中了k或者说index,返回这个m值,如果没有命中左侧。

右侧只选择一侧走好,我告诉你bf p r t算法后面的过程全一样,他就是怎么选这一个数非常之讲究,可以认为bf prt算法跟我们现在刚才刚搞过那个算法,后面的过程全一样,选出一个m之后。

我也利用荷兰国旗,问题小于它的,放左边等于它放中间带着他的放右边看命中没命中没命重的近左侧,整个重复递归右侧,或者进右侧两边直径一侧为一的区别,就是怎么选一个数,讲究的,这就是bf p t算法。

听懂同学打一,全一样啊,就关键点就是聚焦在怎么选这一个数上,唉我感悟同学感觉很好,可以,但那就不经济了,为因为快牌是你选出来一个数之后,你左侧跟右侧你死活要进递归的bp算法,为什么精心挑选这个数递归。

如果只走一侧的话,我可以让这唯一的后续过程变得尽可能淘汰掉比较多的数字,可以像bf p t这样算法这样选择精确,要精挑细选一个数,但是没有必要,反正你都得去搞,无聊的很,增加了常数项的优势,但没有必要。

因为它两侧都要去走的,而我们这个题是只走一侧的同学打个一,bf p r t算法用它是有实际意义的,所以就随便选一个得了是吧,别平白无故的增加了一些东西了啊,好那他怎么挑这个数来了三两步我们就省掉了。

因为都一样,关键就是第一步如何挑数,如何选出一个精挑细选的m来,怎么样搞出这个精挑细选的m来听我讲,先写一下这个bf p r t算法的过程,这个函数是啥,bf p r t对吧,给我一个arr。

给我一个二位,这个二位长度是n在上面求dk小的数,是这意思吧,那你就给我传一个,传一个参数列表是啥呢,二位dk小的数,你给我返回这个数字是吧,这就是b假设bf pr的算法就这么个玩意儿好,我们来看了。

同样精挑细选出m来,第一步数组中,零范围,04范围上,这个数算一组,59这个范围上的数算一组十,直到14,这个范围上的数算一组,最后一组如果不够五个,那单独一组,第一步咱就是脑袋想了一下。

什么也没干,就是在逻辑概念上,我让041组,下一个五个数,591组在下面五个数,十到14是一组,依次往下,如果后面的数不足五个数,那就后面的数单独这些剩下的数一组只是脑海中过了一下,什么也没干好。

第二步啊,04这个范围上,就只是这五个数的内部排个序,这一组有序,59这个五个数的内部有到14,这五个数的内部有个序,每一个小组请你都排好一个序,但是跨组与组之间是无序的,只是五个数一组的内部。

这五个数之间你们分出一个顺序,第二部好,讲到这儿,听懂同学打一,啊看一下大家有多有多集中,有我问你,如果整个二位是n个数,我做完122步之后,时间复杂度是多少,b o n,为啥呀。

我第一组就五个数之间排序,毫无疑问是b o一的事儿,我第二组就五个数之间排个序,毫无疑问是b o一的事儿,我组五个数之间排个序,毫无疑问是b高一的事,一共有几组呢,当然是n除以五组了。

所以122部一起算起来还是在b o n内的,听懂同学打一,就有意思了,我不是排完序了之后嘛,好第三步五个数里,我把位于排完序之后中间位置的那个中位数出来,我管它叫m一下m01 组。

这五个数不是排好序了吗,我把位于中间位置的数拿出来,我管它叫m2 m1 ,这第一第第零组,第一组在下一组,我把这五个数中位于中间位置的那个数拿出来,不管它叫m2 ,每一组都把他们中位数拿出来。

如果最后这一组是五个,比如说它它是a bcd,它只有四个数,那你最后拿上中位数或者拿下中位数都行,不要不要拿b加c除二,这个数不别拿,就拿一个具体的数,不要拿上两个中位数相加除二。

这个结果如果最后四个数a b c d那就拿上中位数,拿这个b如果只剩下a b这两个数单独一组,那就拿a,我就把所有每个组中的中位数所成了一个由中位数所组成的数组,我管它叫m数组,没有问题,同学打个一。

我干嘛,在这样一个弄出来的新数组中,找到它的中位数,怎么找,递归调用bf p r t这个新数组叫m我给你塞进去,这长度是多少,基本上是五分之n规模对吧,因为你一共有五分之n组吗,临出来之后。

它就是这些数组成的,基本上是五分之n规模,我在这样一个总长度为五分之n的数组中,我找到他第十分之n小的数就是m这个中位数的中位数吗,我把它返回,是我选出来的天选之子,那个m听众同学打一。

讲的非常的清楚是吧,当然你不懂的话,没关系,你告诉我,我给你重新再讲,啊都懂是吧,每一组里面选一个中位数,你是不是组成了一个由每一组的中位数组成的数组,叫m数组,下目标其实是场求在这个m数组中。

它这个数组里面谁是排完序之后位于中间的数,问题不就等同于是我们在问这个m数组中第十分之n小的数吗,什么是d 10分之小的数,因为m数组它自己的长度是五分之n,自己的长度是1/5,你怎么找啊。

它上中位数的位置是不是就是d 10分之n小的数,你去问你的递归过程啊,你d调用bf p r t,但里面传的东西是m数组,它的长度一半的位置的d那个小的数,之后就是我大过程中选出来的那个m返回之后是m好。

你再拿这个m去干嘛呢,在这原数组中,荷兰国旗问题小于m的放左边,等m放中间,大m的放右边,然后看命中没命中,k不流畅,听懂能再打一,挑细选吧好,那怎么样有什么好处呢,对n是原数组的长度对吧。

颁布数组的排序吗,不是如果是数组排序的话,不是又变成了n乘log n的问题了吗,哈fp t解决的是啥问题,我们想象一下它的递归含义,在一个数组中拿到dk小的数,是不是是这样一个递归含义。

我们现在有了一个由mi所有中位数组成的数组m,我们想知道在在它的这个整体中,位于中间位置的数是啥啊的含义,我们就继续往下接着玩儿嘛,所他怎么得到这个数的,它不是排序,它是递归调。

用自己利用它已经固定好的含义玩下去,达成从我在这样一个中位数组成的数组中,把中位数再选出来的过程里面,理解整个过程除了122步,有小组排序的时候,其他地方就没排序了,就122步。

每个小组内部五个数排序之外就没排序了,听懂同学打一,感悟同学,你理没理解,我们没排序,第三步不是排序,第三步就是想在在一个无序数组中找到它的中位数吗,这bf p t算法的定义啊,那我就重复玩这个定义吗。

啊,这个感悟同学有没有懂,是把排序中随机选出那个数变成寻找中位数组成的数组中的中位数,这个过程了没错,你别急,我就先问问你这个流程听懂没听懂,我会给你证明时间复杂度的流程,打个一。

我给你举个例子行吧,哎呀真是好来吧,我们现在举个例子,假设数组中,写一些数,怎么选出m来,范围上我怎么选出这个m来,第一步36214,我就认为这个小组,50219,下个小组,最后一个小组三四。

你的小组内部我排个序,变成123461259,三四,不只是逻辑概念,画组了,啥也没干,第二每个小组内部排个序,跨组之间不排序,第三步把每一个小组位于中间位置数拿出来,三位数拿出来,二如果是偶数个。

拿上中位数,三成了m数组,它是不是是无序的,是无序的,干嘛呢,我想知道在这三个柱数中,第二小的数是谁,bf p t请你把bf p t什么传进去,m传进去,把二传进去吗,怎么排序呢,没有排序啊。

我我问你这个数组中位于第二小的数是谁,是不是这三好三出来之后再带回原数组中,拿三座划分值小于三的放左边等于三的,放中间大于三的放右边,你命中去呗对吧,听懂再打一,打二同学现在有没有懂,还没懂。

同学再给我例子,再给我个二,他们是五个流程,搞明白,我就想让他五个行不行,你可以去发明,三有方法跟七有方法是吧,好朋友,方法跟七个没有方法随你的便,但我们这个流程它就是五个。

我会告诉你它为什么是五个行不行,流程能听明白的同学给我一个提醒,有没有懂,第二小的数不是假设的,是你这个m数组,你发现它长度是三,就知道它的中位数是第几个了吗,这个这个第二个不是假设。

是是直接通过它的长度算出来,我要拿哪个,后续拿哪个东西做k感悟,你理解了吗,理解了吗,第三步是继续求中位数啊,没错啊,所以递归调用bf p t回来,你返回多少回了三第三步是调用个子过程。

b m p r t这个子过程是不是有完事的时候,子过程完事了,你拿到这个三,你再去原数组中拿这个三去做划分理解吧,他他总有跑完的时候吧,跑完之后会给你一个值,你就他就是你选出来那个天选之子。

接下来你在原数组上继续partition,听没听懂,跑到第三步没了,是跑到第三步的返回值,接着第四步做partition,然后看命中没命中,我知道他确实很难,知道他确实很难,我声音大。

只是因为我要提醒我自己,要保持激情,啊好那么这么做的意义是啥呢。

啊我们现在把整个所有流程我们先梳理一下,fpr t一开始面对的是一个数据量为n的东西,叫tn,五个数划分组其实啥也没干,想象中的一个概念,bo一的每一个组内排个序,跨组之间是不排序的,只是组内排个序。

一共有五分之n个,差不多这个数据量的小组没小组内排序就只有五个数之间排,所以是bo一的,那么第二步它就是一个b o o n的过程,干部我们是第一调用bf p t把什么传进去,我是五分之n的一个数组。

就是我们的m数组传到了我们下一步的bf p t里面去,没错他用怎么样用表达式代替它,是一个t5 分之n的复杂度,没毛病吧,为什么呢,因为你这个m数组它的规模由原来的n会减成五分之n。

所以第三步是一个t5 分之间的表达式,没毛病吧,当我考完这个过程之后,我就选出了这个m,那么第四步是在整个数组上小于m的,放左边等于m的,放中间大于m的,放右边玩荷兰国旗问题,这又是这个bgn的第五步。

做右两侧,我选一侧去递归t问号,因为我不知道,我现在不知道左右两侧的规模是什么,所以我用t问号来代替,那既然总的表达式它就是t5 分之n加t问号加上b on的这个表达式,再打一,认为这是m2 好吧。

所有组内的中位数组成的叫m2 ,把m2 求完之后会出来一个数,叫m拿这个m再回原数组做划分行吗,这就没有歧义了吧,啊是吧,这是好吧,另外一个变量叫m,哎为什么要精确又细选一个数。

因为这个b t t问号这个规模在精挑细选之后,它居然是可以确定的啊,重点聚焦,第五步,前的过程都确定了,tm第一步b勾一直接忽略b勾,m在这儿呢有了对吧,t5 分之一在这呢有了就是b格温,在这呢也有了。

都是b格温的,都画在一起了,唯一不确定就是第五步。

你左右两侧规模到底后续是多大,那我现在就开始估算,我们要想一下,你现在有一个划分值m你假设你要进小于m的区域,你先要估计左侧的大小,但如果不是bf plt算法是我们介绍的第一个算法,我们说无法估计大小。

因为随机你选一个数,我根本不知道我左侧有多大对吧,现在是精挑细选的m我们就要估算小于m这个左侧的范围最大是多少,小于m这个左侧的范围最大是多少,它是不是就等同于在问你在原数组中最多有多少个数是小于m的。

有几个数它是小于m的,如果你能够回答这个问题,我就知道左侧递归的规模有多大了,不好求,但是有一个东西是可以等同的去做出来的,啥呢,我想问小于m的,最多有几个就是在问大于等于m的,至少有几个,对吧。

我估算了大于等于m的,至少是几个,我总共的数字,一共才是n,我拿这个n减去大于等于m,至少有几个我们就反推出,最多有几个是小于m的了吗,我要打一,怎么回答,大于等于m的,至少有几个。

它n在一减就是我左侧最大的规模那个量,那然后我们的t的问号不就出来了吗,对吧,或者说在在在进入左侧递归的时候,它这个问号的量就出来了,对不对,那我们现在看m是个什么。

m非常特殊,你不要忘了给你画个图,你就理解了所有数组,这是第一组的数,第二组的数,第三组的数我们不是五个数一组吗,第四组的数,第五组的数,这每一组都由小到大排好序了啊,每一组都由小到大排好序了。

这一组这一组所有的组都排好序了,可以吧,每一组都从小到大排好序了,m2 其实是哪些数组成的,这五个数组成的叫m2 ,r,没有问题,同学打个一,一定要进入左边,是如果进入左边的话,我们这样估计就有意义了。

对不对,不是一要进入左边,是如果进入左边的话,那我们来看我们给它编个号a cd好,我们是什么过程,我们是把abcd组成一个数组,去求这五个数中第三小的数,abcd这五个数中求整体第三小的数,没错吧。

不妨设第三小的数是e这个数,你也可以假设第三小的数是a这个数,你也可以假设第三小的数是c这个数你怎么假设都行,总之它这五个数里面会有一个数是第三小的数,没错吧,看一下。

假设一是这个第三小的数e是在左边的,a c在右边的,当然你也可以假设中间位置是b,这边是这边是b啊,这边是dc,你啊这边是ec,你怎么假设都行,无所谓,是不是我选出来第三小的数理。

在整个数组中有两个是大于等于我的,两个是小于等于我的,没问题吧,所以我们不妨设e就是这个第三小的数,ac是大于等于这个e的,可以好,我们看发生了什么,可就是我的m了,我选出来这个中位数中的中位数。

我就拿这个e其实就做划分了,没错,我们这个东西它特殊在哪儿,六几组,五分之n组,五分之n组的这些数组中有一半是大于等于你的,这个数组中有一半是大于等于你的,有多少个数大于等于你十分之n个数。

你要把整个数想象成n数组有多长,五分之n在这个数组中位于第三小的位置,假设是个e大于等于他的,那是不是说明这个量是多少,差不多是1/10的规模。

看看a看看c你看一眼a在自己的组里面可是有两个比它大于等于的,在自己的组里面可是有两个比它大于等于的,你在这个数组中如果有十分之n个数是大于等于你的对应归元数组,就至少有3/10 n是大于等于你的一。

每一个代表在自己的组里能额外找到两个比你大于等于的数,所以是3/10人,大的数至少是3/10的规模,那比你小的数最多是多少个,7/10 n吗,知道左侧最大规模是多少了,7/10 n了,看到了吗。

为什么精挑细选这个数,因为可以固定的甩掉3/10的规模,听懂他在打一,二没懂我就再来一遍,好吧,没懂我就再来一遍。

来再来一遍,好,这个注意听,想估算我们精挑细选了一个m出来,精挑细选了一个m出来,这样的过程数据规模我们都估算了,唯独最后一步我们拿不准对吧,也就是说最后一步如果我没有命中,我没有命中。

我等于我等于m的区域,没有命中那个k我的选择就是要么进左侧去走递归,要么进右侧去走递归好,我们先看左侧的,我们先看左侧的,那么进左侧的递归实际上就是估算什么,你要雇你要用最差情况来估计,这是复杂度的。

它的定义对不对,你要知最差情况估计,除非你是概率事件,你去求概率累加去,如果你是确定性的算法,那你就你如果你没有概率这个因素,那你就你你在左侧估计什么小于m的数最多有几个,我们不去正面挑战。

小于m的数最多有几个,我们先干嘛,如果我知大于大于等于m的数至少有多少,拿n减去这个量,我们就估计出左侧最大的规模了,二位同学现在听懂讲到这儿听懂同学打一,他讲到这儿听同学打一。

现在我们就在估计大于等于m,至少几个这个问题,等于m至少几个问题,如果你是随机选的m,你是没有办法回答这个问题的,因为它至少有几个情况都有可能发生对吧,但我们的f不是随机选的,我们的m是精挑细选的。

他怎么精挑细选的画那张图,假设整个array它被分成五个组,就假设这个第一组啊,m来自哪,如果每一个数组中,每一组内部都由小到大排好序了,是谁,就是每一组的中位数所组成的数组,火树会组成m2 位。

那么是什么地位呢,是在这个mv中的中位数是什,么,叫m同学打个一,这不就是我们的流程吗,那怎么分析来看,编个号a b c d e这个m,是由abcd,它可能是一个无序数组中第三小的数。

如果整个二位是n个数,我问你m2 位是多大,五个五个数,一组每组里面选一个数,m2 位的规模就是五分之n的规模,换句话a b c d e它的规模它就是五分之n的,m又是在这五个数中正好位于中间位置的数。

这说明啥,大于等于m的数规模是多少,一半吗,基本上一半的比例,所以你不管这个m是什么,这个m有可能是a这个m有可能是b,这个m有可能c根据具体的状况来决定它是什么都无所谓,但我问你。

如果m真的是这个数组中第三小的数,是不是相当于在这五分之n个数中,有十分之n个数是大于等于m的,我指的是在这个数组中听的一,来打二同学,哈哈那么在这个数组中,有十分之n的规模是大于等于m的。

如果是e选出来是e大于等于m在自己的组里可又多增了两个,是大等于一的,为什么这个组里人家是中位数,每一比m大的,在这个数组中,每一个比m大于等于的数,回到自己的组里会多来两个大于等于m的数。

因为这些数是大于等于e的,e就是大于等于m等,任何一个在这个数组中大于等于m的数,回到自己的组里又多来了两个,那你说全数组至少有多少个数大于等于m,十分之n的代表,每一个代表回到自己的组里又多加了两个。

是不是十分之n乘以三啊,数组中有3/10 n的规模至少是大于等于m的,那你说最多有多少个数是小于m的,n减去他们十分是7n吗,我们不就估计出来左侧的规模了吗,听,三打二的同学有没有懂。

异化的东西来给你讲是吧,有没有懂懂了吧。

好估计了,左侧的最大范围,的最大范围,右侧是不是同理,右怎么去估计,我们问最多的是大于m的,不好求的话,我们就问至少有多少是小于等于m的,一旦按了,至少推理方法不是一样。

你m中至少好有十分之n的规模是小于等于m的,所以在每一个组里至少有3/10 n的规模小于等于m,那最多有多少7/10 n它估算的方是跟右侧,跟右跟左侧一样,都是分至多的问题。

也就是这个结论就是左侧最多7/10 n,右侧最多也是十分之七一,经过一个比例一次甩掉30%,再甩掉30%,这样甩下去,所以大师是什么。

不学上不用概率证明它是b格on证明略听懂,数学问题,想看证明的同学,算法导论第九章第三节有三页纸来证明它好吧,就行了,他没有办法用master公式来注意,没有办法用master公式的,在你们面试中。

就这一个bf p t算法需要记这个结论,在面试中,其他的递归行为都是master公式能解的,就这一个,问一下,咱们休息两分钟,然后讲一下bf p t算法的代码,有任何同学弹幕,我没有的。

没懂的同学打二弹幕,我我给你搞懂,因为这个算法非常重要,你听不懂还怎么跟面试官装逼是吧,笔试过你根本用不了bf p r t,直接用我们第一种方法就行了,你一定要确保自己懂了好,我们休息两分钟,然后继续。

意思是如果排序的话,排dk个吧,对对,相同的吗,不合并掉,不合并掉,下标是从一开始的,也就是dk个就等于零位置,排完序之后,零位置的数,第二个就排完序之后,一位置的数合并掉吗,不合并掉。

是直接取m2 a的中位数吗,没错,就是把概率问题搞成了确定确定流程的问题,没错,没有概率了啊,行吧,注意啊,你好听懂我讲的,因为你自己去翻论文的话,你看不懂,他为什么看不懂呢,他估算非常麻烦。

他估算的非常的精确,什么呢,它充分更估计了唉,如果最后一组的数不够五个怎么办,这个问题,所以他想它的表达式,它这个它这个7/10可能会加一个小常数,它你估算那个方法算得麻烦死了。

我直接按比例让你来理解理解吧,因为它后面不管是减一个小常数也好,还是加一个小常数也好,都不会影响最后的结论的,听懂同学打一你,就是你你最好,理解我在说什么,因为他对他自己在论文里或在帖子里估计的时候。

他是给你把最后一组如果不够五个怎么办,给你算得非常的麻烦,他这个最后的表达式它可能是要加一些或减一些小常数的,但是在让你理解方面,其实是没有必要引入这些小常数的。

大家懂不懂我啥一次我给你估算的就是按比例给你估算,最好理解的样子了,已经是,更大的组还是吗,那不是一样吗,来如果是更大的组,如果更多的刀,你说如果是更大的组,比如说七个数的组是吧。

比如说七个数一组是吧啊为什么选五个数一组呢,五个数一组呢,选七个数一组行不行也行,保证最后的表达式收敛到b格就都行,一你选七个数一组去搞,选中位数,如果最终写出来的表达式能证明它收敛于bn那也行。

ppt算法在算法界的地位非常的高,为什么,设计一个我随便定的一个常数的分组,或者是一种什么方法能搞出来一个表达式,只要他能收敛到我想要的这算法就那过,也就是说他能不去严格想这个算法的流程。

他最终弄完之后,他只要估计出比例,我就可以确定这个办法流程有没有必要继续研究了,放了一大套的去找各种复杂度的方法,搞搞这种优秀流程的一个筛查器,听懂同学打,一开始试的时候可能就是三个数一组。

如果收到我再试五个数一组,还收敛不到,我在17个数一组,或者说我已经明确地描述出我是几个能够让性能最优,唉,我就看看最后能不能收敛到这个程度,我就给它定成五个数一组的李梅里。

在这个为什么人人都爱问bf p t算法,为什么你能够装这个逼,一方面是因因为在无序数组中求dk角度数,这个问题很常考,另外他们就是在算法上,它其实开创了一个时代,什么时代呢,我利用我先把流程设计出来。

我直接写出最后的tn的表达式,它给发现他有搞头,我才继续去分析它,我一直先写出后续的表达式,发现他已经不不能收敛到b了,我想都不想他听我同学打,三个数一组行不行,七个数字一步行不行,九个数一组行不行。

五六个数据组行不行都行,你自己去试,如果你发现能够收敛到b o n,那就是你的算法,但是长建的是五个数一组,听懂啥意思了吧,代码好,rt,啥呢,他跟下标统一起来,k从一开始下标从零开始,好恶心。

所以我们就这么来,那是在二位上,到r范围上,如果排序的话,index位置的数是什么,嗯排序的话位于index未知数是什么返回,所以这又有个潜台词,index一定是位于l到r范围上的,好如果这么规定。

你主函数怎么调零到n减一范围上,位于k减一位置的就是我要的,有什么区别,一点区别都没有,它递归含义完全是一样的,这个名字叫bf p t,它的含义及主函数为什么这么掉,同学打个一。

唉你看这个算主流程是多么的简单,精挑细选一个数做划分值,哼具有精挑细选一个数,请你做划分值啊,国旗中用荷兰国旗问题,根据这个划分值小于化划分值的,在左边等于划分值的,在中间大于划分值。

在在在右边等于的区区域,左边界和右边界range告诉我,如果命中了,直接返回,而瑞没命中,左侧你给我bf p t去,否则右侧你给我bf p t去,看懂主流程,同学打一要细选一个数嘛。

我给你变成一行主流程,你懂不懂,跟刚才有什么区别,告诉你了,没区别,就是精挑细选,而一个数而已啊,那么我怎么精挑细选这个数呢,就是底下的方法了,含义就丰富了,阿瑞到r范围上,请你五个数一组是吧。

然后每各小组内部排序,嗯嗯各小组中位数拎出来,成头部是吧,不是组成m瑞是吧,组成mv,然后再求,瑞中的中位数,嗯迷恋上的meeting of meeting的方法,中位数组成的数组中,它的中位数是谁。

返回这么一个方法,代替了所有的含义啊,代替了所有的含义,它怎么做呢,你一共有多少个数,r减l加一个数size,这个offset指的是你要不要补最后一组,举个例子,你说你如果size是十,有两组。

但如果你的size是啧啧,单组啊,为什么最后单独一个数要单独一组吗对吧,如果你的size在是12,你是不是也是三组啊对吧,最后两个数单独一组吗,意识到如果你的size,如果你的size是14。

你还是三组吗,因为你最后四个数一组嘛,但如果你的size到了15呢,三组,数一组正好三组,所以这个offset是什么,看size模五等不等于零,如果袋子摩5=0,你的组数就是size除五向下取整。

如果你这个模五不等于零,那你要单独补一个offset这一组,这就是的含义来看m2 多大,size,五五加offset,听我同学打一,范围大小对不对,我说了,我们只是忽略的,估计它是五分之n规模。

但他后面有可能带一个小常数,这重要吗,重要啊对吧,我你永远是最好理解的,你不用管这个小常数,它最多加一或者不加,有什么区别,对不对,他最后的时间复杂度的肯定不会显得太小了,空间就出来了,接下来干嘛啊。

一个m2 位组长,就是每一个组的中位数,你给我一次扔到这个m2 位里去里来,所以啥意思,再而瑞的从这个范围到这个范围上选出,如果排排完序之后,位于中间位置的树放到此时组里,做他的组长,做他的代表。

啥意思,你说是谁,l一直到哪,l加四,对不对,那第二组是谁,l加五到哪,九对不对,那下一组是哪,l加十,l加14,对不对,所以每一组的组长是谁,第一个组长l加上0x5,正好是l,l加上1x5,l加五。

第二组的组长l加上2x5,正好是l加十,每一个for循环进来第几组,他的手部的手的位置就是tm的,我是可以这么确定的,他的最后一个位置是谁呢,加四,但如果到了最后一组,他不够五个,那好了,看到同学打一。

在阿瑞在阿瑞的这个范围上,你给我玩个排序,排完序之后,就这五个数排序哦,最多五个数哟,这个方面是不是最多只有五个数啊,排序排完序之后,把你组长拎出来。

接下来bf pr t什么在m2 位中零到m2 位减一的范围上,位置的书,meeting of meetings,你接下来剩什么工作了,m2 a中找到中位数,你的范围是啥,m2 位从零。

m2 a点蓝减一这个范围啊没错,那你要在这个范围上哪哪个下标呢,m2 瑞自己长度除以二这个下标,m2 为零到n减自己的这个范围上的位于中间位置的数吗,你怎么拿最快bf rt。

也就是说这个方法它难理解的地方就在于负掉了一个子函数,但子函数里面调用了大函数的递归,但规模可是减小到五分之n的,听懂它在大一,哎呀这个所有中位数都拿出来变成m2 了。

不就是在这个mv中找到它的中位数吗,接个电话,嗯,啊看一下啊,五分之n这些中位数组成的数组中的第十分之n个,我想n这件事情了,我现在都都不都变成m2 v的表达了嘛,对吧,你现在问题是不是在m2 位中。

如果排完序之后,位于中间位置的数返回,那不就这一句吗,原问题了嘛,对不对,啊这个,流程跟证明已经扯过第三遍了呀,但原理的证明已经来第三遍了,再来一遍就是,就交给视频吧,好吧好好啊,啊好啊。

那么多一步就是这个返回中位数组成的中位数,就中位数组成的数组中位于中间位置的数,这就是我们要的那个划分值嘛,我们可以设计它的对吧,然后选取一个啊,这下面就是在一个范围上,你五个数排序。

并且把它的中间位置拿出来,你五个这个l到r上,这1l到r上最多五个数,玩隐私salt还是玩什么salt,是不是随便,为什么要推荐insert呢,你本来就五个数之间排序,你就选一个常数项最低的呗对吧。

你不就五个数最里面l到l最多五个数嘛是吧,你看在在这样一个范围上拿到,排完序之后,拿到位于中间位置的数,那不就是l r最多五个数,你去排吗,insertion sort就够了,拿到中间位置返回。

就所有的代码都结束了。

啊这这这个应用就很简单了,你已经解决这个源问题了。

这应,常见的还有这样一种问法,在array中,去的我怎么拿到他生成一个长度为十的数组,它这个诺维斯代表在这个二位中,前十小的数我都要,第一前一小,前二小一到前十小,这个问题很简单,上咋做呀。

你先求d 10小的数,假设十小的数,它的值是17,一个结果数组它长度是十,你再遍历一下所有比17小的数填在这里,唉你第十小的数值是17,你在二位中只找到了六个比17小的数,那我问你最后四个是谁。

都是17吗,听到同学打一,我怎么前十小的数我先找d 10小的数,我看看有多少个数比这个找出来这个值小,它们都是答案,如果不够话,那毫无疑问剩下的那四个或者剩下的还没确定的,就都是我找的这个第十小的数。

说明他有很多个重复值,没没毛病吧,你同样道理,你是不是可以解决前十大的问题,你你会找dk小,你不就会找dk大吗,所以kd算法真的在面试中是经常出现的,非常常见。

我们在公开课的第二节还是第三节还讲过一个bf p r t算法,一道非常难的题,我准备把道题再拿到我们训练营里,在接下来的就是可能不是这一期训练营了,可能来到第三期或第四期的训练营。

再给你讲一个b f p2 t算法的一个应用,但是它他的他他它的用法其实也不需要找什么敏感度,他也没有什么敏感度好找,就是一个数字无序的,你想找dk小或dk大都可以这么去弄。

提醒一下笔试时候不要写bf p2 t算法,常数项有点高,而且也没要就做那种最简单的就够了,如果在面试时候讲完了那个最经典的之后,跟面试官聊,bf p t算法会极大的提升身价,就整个这套嗑儿啊,满分十分。

你可以用装逼的用处是吧,可以做它把它做装逼的用处,但它常见的呢,他是一套很大的一个启发思路,对不对,啊啊啊啊平和我们不精挑细选的那个数,就拿快牌直接改方法,时间复杂度是一样的,都是b n。

那么我们下周希望大家到场,我们下周一上来就会讲马拉车算法是吧,你想在网上现有的帖子里面看懂马拉车算法,我告诉你几乎不可能,因为啊讲得非常之细好吧,大家到场如果没明白的同学可以了解这个我们的视频是吧。

因为我们这个流程已经扯到第三遍了,再说第四遍就祥林嫂了是吧,啊就买nh算法啊,马拉车算法好,那么欢迎希望大家下一周继续来好吗,嗯拜拜拜拜,这需要复习什么吗,不用复习什么,完全不需要啊,不用管啊。

直接带着脑子来就行了是吧,好我们下课啊。

系列 2:P68:左神算法-Morris遍历及其相关扩展 - Java视频学堂 - BV1Hy4y1t7Bo

哎我就看了,今天最近看了一下啊,这个买大车的讲法唉,蛮有意思的,你知道,第一个帖子,然后你看他讲的方式和他提供的代码,最后来了,有个同学来了一句,是吧,哈哈哈哈好吧,这个,行啊,这可能是我某一个。

未曾谋面的朋友吧,能听到不说话了呀,明天明天讲现代数和ak自动机了,下午班,下午是莫斯便利,诶有有有,有有多少同学这个最近参加一些笔试,面试比较频繁的啊,我还有几分钟是吗,估计要到2。05开始讲。

可以聊聊对吧。

你怎么刷。

这是cn,咱去的不是cn啊,你们怎么刷啊,这个是这不有这些吗,top 100,like the questions,这个还有这个top interview questions,说句实话。

这个top 100块的比较有意思,但是这个是最高频最功利的,你这样的,你这种这种这种列表,你点进去,你比如说你你就是最功利的方式,你点进去他这个最最高频的这些题,你都一个一个刷就行了。

他肯定对你来说是最对你来说,对你来说面试压力最大最大的啊,然后还有就是你你知道他你们点进去啊,如果你们有精力有限,你在100在100这个top question里面,这不有一个点赞跟一个点踩吗。

看到了吧,你点你选这种点赞多的题,刷这种题,就说明是他那个他这个这道题你搞会之后有一些有一些技巧或用法,以后切别的题可以借鉴到啊,他就就很多人会点点赞,虽然你你感觉这个赞只是用户说刷爽了就点个赞。

没刷爽就点个踩,但实际上它达成的效果就是这个意思啊,也很奇妙是吧,这个我这些都是我的经验啊,我观察要发现哪些提示,它可能会比较提炼出技巧的题,就这种有有些题目他真的很烦的是吧。

它每道题它那个优化技巧是属于那道题的,你刷完之后就没什么帮助吗,有有些题他点点点赞很多,就意味着就是他能学到一些东西,你比如这种题,我公开给我讲过这双指针问题来解决的,那双指针统一的技巧,他能借鉴的。

那这个点点赞的就非常多啊,高频题里面也有点赞很少的,我记得这没错,这个题吧应该是点赞蛮少的啊,点点点赞蛮少的,你看这个虽然他很高频,但是点赞那么少,点踩这么多,为啥呢,因为这道题本身它的业绩。

他自己的业务优化太多了,用户刷完之后觉得我搞了半天弄了个啥是吧,这这什么玩意儿是吧,我刷完题之后有有有有啥球用吗,感觉没啥,就是这道题那就点大家都点踩听懂,他打个一,啊。

啊这个有的同学问我就是奇数都放在奇数,偶数都放在偶数,这个题我都已经不讲了,只要你问的话,我就可以给你讲一下,正好我们还有几分钟要开始了,就是有同学问我说一个数组中,一个数组中都不用。

都不用限制2n个元素,就是就是就是一个数组,请你把基数放在奇数为奇数的下标上,偶数放在偶数的下标上,你总能达成一个就是你如果基数过多的话,你也能做到基数放在奇数的下标上对吧,你如果偶数过多的话。

你就可以做到一个效果,就偶数放在偶数的下标上对吧,如果你奇偶一样多,那你就可以做到基数放在奇数下标上,偶数放到偶数下标上对吧,所以这个题可以不不一定它非得是2n个元素,我们现在解决这道题吧,因为。

因为这个这个这个现在还有些时间好吧,大家听懂这个提议,同学打个一就是倒数第一,这个不是这个名,这个同学名字叫倒数第一啊,我们就管它叫第一同学是吧,第一同学问了个问题是吧,你不让我想现场解吗。

那我就解完之后,正好这个题我一开始是讲的,后来我觉得他太简单,然后就给他删掉了,你们的班上现在我都没安排这个题啊,但是他这个题是一个很简单的道一个问题,你是考到了吗,这个其实是个coding技巧啊。

他是怎么做呢,这样啊,我有一个数组吗,这个数组你要么做到奇数放在奇数下标,要么做到偶数放到偶数下标,所有奇数都要这么做,所有偶数都要这么做,如果你奇偶一样多,那就可以奇数放奇数下标,偶数方偶数下标。

或者你基数有点,比如说你基础有两个,我说有一个你也可以做到,对吧,哦不行,偶数有两个奇数,有一个也可以做到,你比如说你有两个偶数是四二,另外一个奇数是九,那你其实可以做到零位置上放二,一位上放九。

二位上放四这种是吧,反正呢他就是嗯就是也就是说你尽量让所有的基数放在基数上,如果做不到,你基数不够,那就算了,你尽量让所有偶数放在偶数上,如果你实在是个数不够,那就算了,就这么一种一个题。

理解啥意思吧啊那怎么做呢,你有个数组,我有一个,我就看最后一个数n减一未知数,我就看他我设置两个指针,一个指针在指指它只去指偶数的下标的指针,比如这个指针我管它叫aa指针,还有一个指针。

它一开始是b它就就指奇数位的指针,比如说我给你举个例子,76294237651,这个速度我怎么做到的,调整是啥样的呢,一开始看n减一位置的数,a指针指向零,b针指向一哎,这个数是奇数对吧。

你把它跟b位置上的数字交换,那么你就一就来到了这个位置,六就来到这儿了,然后你的b已经指到一了,你跳到下一个奇数位置上,三位置就是bb一下,它会跳隔一个格子,跳a也是隔一个格子跳,b永远是隔一个格子跳。

a也是隔一个格子跳,他俩不会跳到一个位置上,a跳的都是02468这种位置,b跳都是13579这种位置,那你这个位置就搞定了吗,我再看这个六,它是一个偶数对吧,我给他发货到偶数位置上,你的七就来这儿了。

然后我的a就往下跳,跳一个格子,大家懂啥意思了吧,你永远看最后一个位置的数发货,你发货到哪儿,那个数拿过来,然后指针相应的跳一个格子,a或b有一个越界了停,你做到了,听众同学打一,对吧。

你这种为什么说它简单,我都我都不想讲了,因为啥呢,他就是一个口径技巧对吧,就是后面最后一个数你就发货吗,你扔到哪个货,那个货位置的数就来到这儿是吧,你就这两个指针,它有一个月界了,说明有一组做到了。

那就停了呗,是吧嗯,好啊,我不知道他是不是离得扣的原题了,因为我刷的题太多了,我其实你跟你们讲到lead cos上或者是居多,我自己刷什么平台都刷了,所以我也我也不去区分他到底哪儿的题,他重要吗。

他也不重要,对不对,可能有吧是吧,可能有吧,你可以看一下奇数的奇数位,偶数在偶数位,就拿这个东西搜,也许他会提给你跳出某一个ledcoat的提吧。

好吧,那再等两分钟,就这种这种小题,好多东西都不讲了。

因为,我总觉得有点水,对不起观众啊,所以我也陆续的很多,我原来好多压箱子踢我都不讲了,因为没必要啊,既然我们这个班会一直开,有可能所有之前没讲的题可能会复活是吧啊,a cm体哪能刷top cod。

top coder上是是那个a c m的人拿着来做打比赛的,拿着做比赛平台的啊,当然你你自己是图中图片式的话,你不用刷了,top coder,因为上面的题都不知道哪,你不知道他突然间就拿到哪去了是吧。

他不够功利,嗯嗯面试的同学刷绿的code,如果就是想学好算法,对这个都有瘾,跟我一样是吧,你就去刷top code好吧,然后,我出的书有没有推荐购买的,嗯这个我自己吹,我自己不太好吧是吧,你爱买就买。

不买就来听课是吧,就一样了啊,书上只是一个总结啊,真正本体现在你不就正在听吗是吧嗯,啊,啊不是脑子笨,是你还不熟啊,没有脑子笨的,你能跟他说句实话,就现在课堂上,甭管是在参加正在参加直播的,还是看录播。

看到这里的,你要知道你你脑子不笨,你一定能够把这个事情攻克,为什么攻克真正攻克不了的人,基础班都看不完就退课了,听我同学打一,啊,就练就行了,你这不会他有雷德cod,还要我教吗,你比如说这个某一个题吧。

你不会对吧,讨论区里面最多投票的方案看懂八九不离十,理解啥意思吧,当然你这个lead code里面讨论区最大的投票你未必看得懂,但是代码你得有点抠,你自己把它翻译过来啊。

还有一点就是投票最高的题未必是最优解,这个还是挺多,有不是最优解的,我跟你讲,我肯定讲最优解吗,就是筛选的过程你可能做不到了,但我跟你讲,如果你想现在就是刷题,那你就这么干嘛对吧。

你一个题起码要想个想个三四十分钟啊,你实在想不出来了,你就就就这么干净,就是题目描述实在想不出来了,边讨论区最高投票,你就你能懂得理解吧,听懂啥意思吧,超过一小时就不要再不要再重复,再再再再再憋他了啊。

就保证自己一小时一小时这么弄啊,如果你小时解不出来,完全没思路,那这道题本身你也应该去学的是吧,给你不要一道题扣一天,我这是我当年的干法啊,真的没用啊,这个非常费时间的,就一道题最多给自己一小时时间。

但要保证这一小时心无旁骛对吧,如果如果你觉得你自己有印,如果你觉得你自己有思路了,那可以超过一小时来用来扣顶,但是一小时都没思路的话,你就赶紧看看答案是吧,嗯,好啊,这时间也差不多了好吧。

我们现在讲摩尔斯便利啊,好这个p p t大家都有吧,没有也没关系啊,这个,我们来先把莫瑞斯便利是四个哎呦,不是公开课,哎呀算了,不不不不不开ppt是吧,不开ppt显得很心虚一样啊。

这个已经熟到不用开是吧,好我们现在讲一下啊,这个我们知道在我们之前讲的基础班里,我们介绍过两种二叉树的遍历,都可以实现先序中序和后续便利是吧,那么我们说当时讲的时候是不管你用的是递归的方法去搞啊。

二叉树的三种遍历,还是你用非递归的方法去搞二叉树的三种遍历,其实你都是需要额外空间的,如果是递归方法的话,你其实需要调用递归栈来帮你去做压榨,是那个空间复杂度,时间复杂度当然就是节点个数b o n。

但是空间复杂度其实它也是要占用的,就是占用你整棵树的高度对吧,这一棵树我想便利完全把它遍历完,我是通过一层一层的压榨的方式到底层去的,这个东西搞完了之后,回到上层的站调用这个函数再往下走对吧。

那你的这个占空间,你不断的使用,不断的释放对吧,这个使用了,然后又释放掉,然后用来搞这边就是递归战里面,他开的空间其实是跟高度相关的地沟h这是递归方法,非递归方法也一样,非递归方法就是你自己去压战。

你也要最最最差的时候,你要要压整个一个高度的,所以不管是递归非递归,我们之前讲的方法都是时间复杂度b勾温,额外空间复杂度b勾h这么一个指标都听明白,同学打个一就是我们前置的内容,如果不会的话。

嗯这节课你也能听懂,但是会麻烦一点,基础班都讲过了,啊好,那么,我们morris遍历是做什么的呢,morris遍历是我遍历完一科二叉树,可以实现中序先驱跟后续便利。

我能够时间复杂度b g o n空间复杂度优化成b o1 ,这就是摩尔斯便利,摩尔斯电力可以实现树的先序中序和后续便利,而且它的空间能够从高度这么多变成差有限,几个变量就能做到,为什么它重要。

因为数有很多题目都是跟便利有关的,你掌握好一个非常优良的便利,就意味着你有可能关于数遍历的某一个问题,morris遍历的流程,它就是最优解,听懂同学打一,对吧,因为我们输的很多题目都是跟便利有关系的。

我们掌握了一个优秀的便利,其实就意味着很多题目它是以morris遍历本身作为最优解的,因为它空间很好,时间复杂度又没有什么变化,但是这里面这个地位大家要记清楚,不要在笔试的时候得瑟,笔试我们讲过了。

在基础班的时候也给你提过了,笔试的时候什么以什么为准,以最快ac accept通过这道题为准,面试的时候,你可以跟面试官好好聊一聊,理解这意思吧啊对,怎么简单怎么写,怎么尽快过,怎么写。

在保证时间复杂度更正好,卡中让它过的情况下不用再优化了,这就是笔试特别功利的玩法,因为没有人会看你的笔试写的扣的,他就看那个分,但是在面试的时候,你想一下,如果面试官出了一个很简单的题。

比如说判断一棵树是不是搜索二叉树,判断一棵树是不是搜索二叉树,1万个人都会给你告诉你递归的方法或者是非递归的方法,给你那么做,你来个猫便利,你跟面试官讲清楚了,你觉得会要谁,听我同学打一。

对吧好啊哎大帅同学啊,看样子你是下午功课的km p中的mais和猫变重不变,猫2s便利中的猫是死是同一个人,这是我早年的算法和数据结构的偶像是吧,大家觉得他很厉害的,请把厉害打在公屏上,哈哈哈哈。

这个k mp中的morris跟我们今天要讲的morris遍历的morris是一个人啊,好啊,那么我们先来看一下啊,先把流程给你列好,大家准备好截屏键是吧,我边讲,你看我这个流程。

我我是不会掉入任何ppt的,因为对我来说太熟了,这个流程是当前节点,叫current,一开始,current就来到整棵树的头,好第一种情况,如果current无所述,current直接向右移动。

那怎么向右移动呢,就是current,它等于current dirt,这就向右移动了吗,就car t变量是不是跑到右边去了呀,对吧,这是我们第一个分支,第二分支,如果current有所述。

找到他左数最右的节点,我们把它记为most right,如果他有左数,就找到他左左上最右的节点,啥意思,你这是current,它有左数对吧,这是current,它有左数。

它左数假设就是一个节点或者是这个样子的,那你说他这个他左数上最后的节点是谁呢,就是他对吧,卡尔的左数最后进点就是他,但如果他这边还有节点呢,那左数最右节点就是它,如果它右边还有节点呢。

那左数最后节点就是他,总而言之就是看人的左数最右的节点,你给我找到怎么找,就是从左孩子开始点right。right。right点,right下去点right到最后一个最右的啊,这就是这个意思好。

如果car的有左数,就找到它左数上的最右节点,most right,接下来就要分情况了,第一种情况,如果most right,他的右孩子,他的右指针,是指向空的,这个时候你让most right。

右指针让它指向当前节点,然后current向左移动,现在你听了一头雾水,不要紧,把流程记一下,或者准备截屏,我们会给你例子,把这个流程彻底过明白,那么第二点就是如果这是如果啊他的右指针指向空的啊。

就把他的右指针指向当前的节点,然后让当前节点向左移动,也就是说我们会人为地改,我也就是说我们会人为地改他左指身,它它左树上最右节点,右指针的走向,懂啥意思吧,我们会人为地改的。

那么那么假设most的right,他的右指针,它是指向当前节点的哎为什么会有这种情况呢,你如果不改整棵树的话,你找到它右左树上最右节点这个most right,那肯定它的右指针指向空的。

但因为有了第一个操作,我们会我们有可能会把某些节点的右指针改成指向某个值例对吧,所以它会出现第二种情况,第二种情况是因为我们第一步操作的时候所产生的这么一个效果对吧。

所以有可能这个当前貌似right的右指针是指向当前节点的,如果它是指向当前节点的,怎么做呢,让most right它的右指针指回空,然后current向右移动。

那你说除了第一种情况跟第二种情况还会有别的情况吗,我告诉你不会了,也就是说不存在更多的情况,我们也其实在整个过的流程中,你也能够体会到这一点好,什么时候停,current来到零的时候,停current。

current来到空的时候停,整个流程停,大家先把这张图截了,放在你视频,我给你讲课的旁边,我们我们现在开始设计例子,给你过一遍,这个东西说什么,截完的同学打个一,好啊,好行。

那么现在我们就来设计例子了,这个屏幕这个东西我就给擦掉了,这么一个数,大家现在忘掉谦虚,中序后序遍历,我们只纠结一个东西,就是current依次会以什么样的顺序到达各个节点。

这个序我们管它叫morris序,就是你现在没有所谓的中序先序后续的概念没有,只有cn的节点依次到达某个节点的顺序,那么我们知道一开始我们规定好carry的是指向当头节点的。

所以mors去的第一个就是一好,你现在听你现在旁边那个规则里面,我们写了,如果当前节点是没有左数的,怎么怎么样好,第一个条件,第一个大条件没中对吧,我们看第二个条件,那就那就中了。

中了我们就找到这个current左数上的最右节点是谁,五,看二楼的左数是二维投的这棵树,它最后节点是五,那他五的右指针是指向谁的呢,他一开始什么都没动,他他当然是指向空的。

所以中了大大二条件里面的小一对吧,我们是怎么说的,我们把这个节点它的右指针人为改成它指向当前节点,然后我们说current向左移动对吧,所以现在它会从一跳到二,到二的时候会怎么样呢,还是判断它有左数吗。

他有左数,所以条件大一没中,他中的是第二个,既然有左数,就找到他左树上的最右节点,那就是这个思自己吗,那他左树上最右节点找到了,他的右指针是指向谁的呢,他又指针是指向空的,所以根据我们的说法。

我们就中了大条件二里面的小一,就把他的右指针指向当前节点,然后看着它我们怎么说的,往左移动对吧,刚现在是二,它会来到四,给我来个四,来到四的时候中了什么条件,因为这个四他是没有左数的。

所以它会直接向右移动,你看到了这个四,它的右指针已经设置成了二了,所以卡尔往右移动会往上蹿回二,讲到目前为止,理解没有问题,同学打个一,诶这个磊同学有什么问题就发弹幕,好吧好,那我们就看我们回到二之后。

继续判断当前节点有没有左数,有,所以中了没有中条件一,中条件二,有左数的时候,找到他最后的节点是谁,注意我们一定要想一种机制,不要让这个四穿回二,就是客观上来讲,它左树上最右的节点,我们要找到他。

那你怎么加这个判断啊,你比如说我我我当前节点是current,如果我告诉你他有左数哎,你你得写一个while,你这个while里面得是一些移动y要出来的时候,你要找到真实的数中我左树上的最右节点。

所以你你不能够只是让这个让这个most他傻穿对吧,你这个你这个most他呀他不能够单纯的我永远是most。right往下蹿,为什么不能这样一直这样做呢,因为你这个四会穿回二的对吧,我们得想个办法。

要让这个四就是找它每个每个左数上最右节点的时候,还要保证它不要往上走,这个过程假设我们做到了啊,里面会有写,但是我们现在就认为,假设我们真的能找到他左数上客观的那个最右的节点,那么他就能找到四。

找到四之后,你就会发现他中了哪个条件,就是我们先假设我们能找到是吧,虽然我的右指针改完之后,它这个过程肯定不是单纯的往右窜,但是他我我我是可以通过一些技巧找到的,这个你不用担心,肯定会跟你讲。

现在我找到这个四,他是中了哪个条件,他大条件里面的小二,我们会发现这个四的右孩子就是他的右指针是指向当前节点的,我们是怎么说的,我们让它的右指针指回空,然后current往右移动,没错吧。

所以这个current就从二来到了五,a5 它没有左数,直接往右移动,来到一,要这样指上去了对啊,网易又来到一那ka来到了一了,ka来到一,他有没有左数呢,有找到它,客观上左数的最右节点五,对吧。

那这个五节点它的右指针指向谁的呢,它指向当前节点的,根据我们的说法,我们怎么干的,我们把它恢复成让它指向空,然后卡尔向右移动,来到三,对吧,又是这个三是有左数的,他左数的最后节点是谁,是六六的。

右指针是指向空的,所以让他指挥三,然后看着它向左移动来到六六是没有左数的,所以往右移动来到三三是有左数的,找到最右节点六,这个六它,最右的节点是吧,它就是它三左数上最后的节点就是六。

这个指针词是指向三的,我们把它恢复成空,然后向右移动来到七,七是没有左数的卡尔会来到空的位置停,整个这个序列我们就把刚才的那个东西给过了一遍,理解没有问题,同学打个一,我看有同学有什么问题。

那谁的最优节点不是七啊,三左数上的最右节点是六自己啊,你看七是他又数上的节点啊,三左数上的最右节点就是六自己啊,没有七啊,设置五的右节点是一之后为什么四变成u了,四没有变成u啊,来我们再来一遍好吧。

看着有点乱是吧,这个树本身画的比较猥琐是吧,来再来个大脸好不好,重新来一遍,这个流程是啥意思,我给你解释,但是先让先让你对我们刚才刚才那个写的那套文字有所感觉,然后我们再继续讲啊。

那套文字你拿到旁边好吧,这是我们的猫儿续,一上来current在一,没错吧,cart来到一,他左数上的最右节点是谁,他左数这是他左数,二为投的数,它左数最后节点是谁,是不是五是五对吧,怎么说的。

他这个右指针指向空的呀,所以指向当前节点之后,改人为改走向之后,看着它向左移动,来到二,他有没有左数呢,有它左数上的最右节点是谁啊,他左数上只有一个节点,你说是谁,当然是他自己吗。

就是他二左数上的最后节点就是四,对不对,就是他左孩子嘛,他右指针指向空的,所以指向二人为改动,它的指针就中了我们大二条件里面的小一嘛,然后我们看它往左移动就到四,四的左孩子是空啊。

四的左还是我们刚才改的是人为改的右指针啊,所以四的左还是空啊,就是没有左数,对不对,那他直接就中了我们那个流程中第一个大条件current直接往右移动诶,我之前改过他幼稚的走走向。

所以这个时候看着他如果往右移动,它会回到二的,你每一次一个节点进来,你都过那一套的,都是那一套逻辑,懂啥意思吧,所以二现在进来有没有左数,有他左数上,客观上它最右节点是谁,是四,你会说唉我要往右推你。

你假设你可以有一种机制判断出它在是在往上蹿,理解啥意思吧,假设你可以有一种机制判判断出他在往上蹿,往上蹿了,你就停,那那我左上最右节点就是四,我左上最右节点就是四,它的指针是指向当前节点的。

所以根据我们的说法,中了大条件里面的小二把它人为改成他又重新指挥空,然后看着它往右移动,来到五,那么五是没有左数的,所以他直接往右移动就回到一了,一又是有左数的,它最右节点是谁,是五。

假设我们能够知道它是五,不用再五,再继续往上蹿,假设我们能知道对吧,所以这个五他就指针它的右指针指向当前节点的,根据我们的说法,请你把它改成指向空,然后看着它向右移动,就是你一步一步的。

我们都是根据我们刚才定的原则来的,现在还有没有问题,有问题,同学打个一,啊不这个没有问题,听懂同学打个一,有问题,同学打个二,尤其是刚才磊同学,我我我我我你现在有没有理解,刚才打二同学我都记着呢。

你们要懂,然后我们再继续好吧,好给你换一个奇奇怪怪的数也一样的,比如说这个奇奇怪怪的数,这棵树,他怎么便利呢,current来到current,来到一,找到它左树上最右的节点,它左数二不断往右走。

五就是他左数的最优解点,听懂同学打一,就是你不断往右往右往右往右的,不能往右了停,客观上它就是最优节点,它不是七七,不是在左数的最优节点是这个五理解吧,所以干嘛把五的右指针指向一看,二上向左移动。

来到二,二是没有左数的,所以直接往右移动,来到五,五的有左数,左数最右节点是七,所以指向它成这个鬼样子了,看到了吗,然后往左移动来到六六,没有左数,往右移动来到七七,没有左数,往右移动来到五五。

有左数找到它,客观上的最右节点是指向自己的,好改成它指向空,然后往右移动回到一对吧,然后往右移动回到一一,有左数找到它,最后节点就是个五指向自己的,改成它指向空之后往右移动来到八把。

没有左树一窜窜到空上去了,整个东西停了,看到了吗,什么样的书都可以编辑完,听懂他在打一奇奇怪怪的也一样,有没有看出一点门道呢,比如说我们刚才那棵树,猫二次训练啥先来到一往左移动,来到二,再往左移动。

来到四四,又通过右指针回去回到二,二,又来到五五,通过右指针回去回到一对吧,一一改完你补的指针之后会来到三三,往右左移动来到六六,通过右指针回去回到三,然后再回到七,这就是我们刚才做的二次序。

你不用去纠结是啥,它就是猫旭,你看到这个序有什么意思,你会发现有一个规律,任何一个节点只要有左孩子,只要他有左数都能来到两次,一有组孩子b来到两次,二有组孩子肯定来两次了,三有左孩子肯定来两次。

对于没有左孩子的点只会来一次,这就是某次序,包括奇奇怪怪的数也一样,刚才怎么说的,先来到一节点,人为改动指针之后走向二二,没有左数,直接来到五五,有左数啊,就是刚才这样画的是吧,还是这样画的,五有左数。

七,改完之后就走向六六,没有左数转向七七,通过右指针回到五,回到五的时候会把它的指针改回来,然后往右移动,来到一,来到一的时候会来找到它,右指数,把它找到它,左数上最右节点把它改回来啊,来到八。

然后就结束了,哪些书有左数呢,一有左数,所以b来到两次,二没有左数,所以只会来到一次五,有左数必来两次,剩下节点都没有左数就都会到一次,所以mors便利它的顺序是我先来到一个节点一次,他左书都弄完之后。

我会回来的,然后再去我的右边便利,由左数的节点必回到两次,没有左数的节点必来到一次,听我同学打一,我为什么要改动,我为什么要人为的改动它左数最右节点的右指针走向。

因为我想用这件事情知道你是第一次来到你自己,还是第二次来到你自己,啥意思,你说我一上来孤零零的一个一节点,你说唉我我们写那个大流程是不是只有current及其他结构关系的讨论。

我们是没有除此之外不记任何状态的,对不对,只有一个孤零零的current空降空降到我这个刚才你给你们那套逻辑里,只讨论它的结构关系,除此之外我们什么信息都没有,没错吧,那他怎么知道能是卡住的。

是第几次来到自己呢,就利用我就看我发现我左树上最右孩子右指针指向空,我知道是第一次来到我,那我第一次来到我,我就把他改了,然后我来到二,我没有左数,我就只到一次,也就不用区分是第一次还是第二次。

然后来到五,我来到五,怎么知道我是第第几次来到五呢,因为我有左数,右指针就指向空,所以我知道我是第一次来到我,人为改个走向,然后我就来到六六,没有左数,他只有一次来到他,也就不用纠结他有几次来到他了。

来到七也是这样,他没有左数,就只有一次回到五的时候,你怎么知道是第二次来到五呢,我发现我右数左树上最右孩子的幼稚人指向我的,说明啥,说明我在第一次时候改过它,现在我再改一遍,他说明我是第二次回到我。

对不对,改完之后我就往右蹿了,我往右窜来到一,是不是这样的,也是这样的,我我怎么知道我往右窜回一周,是第二次来到一呢,因为我发现我左树上最右孩子的右指针指向我的,只可能是我第一次改过它。

现在轮到我把它恢复回去,所以恢复回去之后往右走一个节点,如果一旦他往右走,再也不会回来了一个节点,如果他往右走,要么就是往右孩子方向走,要么就是往上走,他再也不会回来了,听懂的同学打一。

好这个东西你要想深刻理解,哎我操,等会儿我重新开一下。

这个我为什么不提前驱节点,我就怕有些同有些同学他没上过基础课,你给他扯前驱节点,他也不会理解吧,你知道他是找前驱就行了,你哪怕没有没有上过基础班同学,你也能听懂的,你看我们。

所以你知道为了让所有人都懂自己下了多少功夫吗,是我我就给你来个找前驱节点,你知道说啥嘛对吧,这是我们都见过的猫,就是一个二叉树的遍历,如果你把打印行为放在这儿,就是先序遍历对吧。

如果你把打印行为放在这儿,就是中序遍历,如果你把打印行为放在这,就是后续便利,那你说这个递归人家凭啥这么牛逼呢,因为递归站里面给你记录了,这是你第一次来到你,我自己流程控制,我知道你跑函数跑的状态。

所以我告诉你,你是第一次,你跑完这一句之后,你来到这儿,虽然你什么也没干,但程序能告诉你是第二次回到你对吧,然后你就要去你右数遍历,然后你会来到这儿,发现结束你的整个过程才能结束,程序会告诉你。

这是第三次来到你,mars遍历就是在向递归函数致敬,但是他无论如何做不到三次检查自己,他可以做到前两次听到同学打一,懂吗好,那么我们来看一下这个morris遍历的代码。

现在还没有先序中序后序的概念理解吧,只有morris序把这个就擦掉了,来看我们的猫去,你不用看这些代码,我给你重新来一个,就叫猫is,这底下都是在用mos去实现先去中序,后续啊。

这个这个这个这个逻辑它就叫moa,什么打印行为都没有,都去掉,什么打印行为都去掉,刚才说的那整套流程就是这个扣的改几个变量名,不然你可能看不懂,看着他一改成current这个卡。

二就是我们的most right,所以我们看啊这个代码是怎么跑的,你看这里面是没有任何打印行为的,你只要能够根据我们刚才那个逻辑把它过下来,这个代码写的就那么回事儿就行了,他怎么跳。

如果你每一步都打印的话,它就是猫is序对吧,一开始我们都说了,根据我们的流程,current是来到头节点的,没错吧,most right现在还没用准备好一个变量而已。

貌似变量貌似right现在还没用准备好一个变量而已,在这个while中,你看这个while中,我们其他什么都不管,这个while,你看看在这个while里面。

你看啊这个分支会让left就是current往左移动,如果这个就没中,他一定会来到这一句往右移动,所以你不用管这个逻辑,咱现在一个形成的一个印象,就是在while里面,current要么往左。

要么往右动,它不可能在原地,那么我一旦current到空了,我就停,没空就继续主逻辑,就像我们刚才讲的一样嘛,你carry了,先来到头节点,然后每一步要么往左,要么往右动,一按空你就停,如果没空。

你就继续转,所以这个代码整个的结构啊,咱不说这一坨东西是啥,就形成一个印象,就是卡的不断,往往左或往右跳,一旦没空就出来听,打一,好那它到底是怎么动的呢,来看,我的第一步过程就是判断它有没有左数。

对不对,那你看我第一个判断就是请你告诉我有没有左数,怎么判断的,你看他让他先把自己的左孩子给貌似right,如果most right不为空,就是有左数,所以这一大坨都是有左数的代码,我们跳过。

如果卡尔特没有左数,整个这一大坨逻辑会跳过卡尔特往右移动,这是不是我们刚才说的流程,一听打一条件一没错吧,我一上来把卡特的左数给貌似right,如果它为空,就直接跳到最后一行,看着它往右移动。

又重复进这个外号了,是这意思吧,好那么他那么也就是说这个代码它很明显写的是他没有左数,设它是对,它是对的,假设它有左数呢,那就要跑中间这套代码了,这就是有左数的代码,那有左数是啥意思,有左数就意味着。

首先我左孩子它不等于空,对不对,我左孩子不等于空,就说明有左数一项,在有左数的情况下,在由在有左数的情况下,我一上来我是干嘛的,先找到他左数上的最右节点,而且应该这么说,找到,真实的最右节点对吧。

你不能因为你人为改动,它又只能走向,让你无从蹿下去了,是这意思吧,那我怎么找到我卡的左数上真实的最右呢,我们来想一下,如果你这个如果你这个节点你是压根儿是第一次来到你自己。

那么毫无疑问你左树上的最右节点,它的右指针会指向空对吧,如果你是第二次来到你自己,如第二次carry,他是第二次来到这个节点,毫无疑问他左数最后的节点是指向他的,所以你怎么找到这个真实的左数的最右节点。

它不断往右的过程中,右指针为空停,或者右指针指向当前节点停,第一个条件就如果你完全没有动过这棵树啊,从这个节点出发,往右往右往右往右到空就可以停了,但如果你动过这棵树。

你你人为地改过它左树上最右节点的指针的走向,那就你用判断,如果它的右指针指向我了就停,你你还是可以抓到非常非常好的抓到他左树上真实的最右节点,就是这个代码,你看的right的右指针不等于空。

也不等于current的时候,我才往右不断的走,他什么时候会从这个while里面出来,两个条件,有一个违反他就会出来,如果我most right等于空了,我从这里面出来合不合理合理啊。

如果你从这里你是空的出来,说明你是第一次来到当前的current,如果我呢我最右结点的右孩子是等于current的时候,我出来合不合理也合理,那只是说明你是第二次来到current,你再找他的最优。

如果这两个条件都没有违反,那你就继续往右窜好了,所以这个while就是找到卡尔的左数上真实最右的代码,看的同学打一,懂了是吧,那么你从这个while里面出来的时候,我就可以宣告,外耳中。

出来就意味着most right,一定是左数上的最右节点,他一定是,那我们说了,那你此时most right的右指针,你说有哪两种可能性呢,就两种嘛对吧,第一种可能性就是它是指向空的,第一次来到我自己。

如果中的else,虽然他写的是else else,其实你直观理解这个else应该是most right,它的指向不等于空,但是但是这个其实你也没有必要去这么理解,他不是不等于空这么简单。

它是一定等于current,懂啥意思吧,这个else它不仅仅是说我不等于空的问题,它是一定会等于current的,他是一定会等于current的,就这么两个条件来我们看,如果它是只向空的。

根据我们的说法,你人为改动它右指针的走向,让它指向当前节点,然后current往左移动,continue continue的可不是这个well,这continue的是这最大的这个while合不合理。

这不就是我右孩子最右的节点啊,右右左树上最右节点的右指针,如果指向空,改成我之后,我往左回大歪了,没错吧,如果我发现我右孩子的幼指针是指向我的,我们怎么说的,你把它恢复成指向空。

他会从这个else里面出来,他也会从这个if里面出来,它往右移动,你也可以这么写,看着他往右移动,然后去continue,你也可以这么写,但是为了省代码,我们把它去掉,因为他一步一步往外跳。

他也能碰到这行代码,让他往右,整个代码梳理完毕,我们怎么讲的流程,这个代码怎么写的,听众同学打一,好啊,这就是我们整个猫编辑的代码,那我们不妨把它打印一下,不用打印了是吧,何必呢,你知道他对就行了是吧。

这就是我们的morris去,有点复杂度,你不关心吗,你关心关心的点在于哪,老师你这是空间很少,就两个变量对吧,就两个变量,然后走完了,你利用的是底层空弦的指针来标记的是第一次回到我,这是第二次回答。

我实质就是这么回事儿对吧,我大量利用这棵树的本身自己的空闲指针来帮我做的这个空间嘛,也就是我没有单独的使用额外的空间了,我都是用他自己提供的,那你那些指针你浪费也就浪费了,对不对,还不如给我来用呢。

是不是,所以就是我利用底本底层的这个空闲指针来让我回到上级去,一回到从下往上的目的好,但是你这里面太对吧,我们每一个节点我都要去趟一下我左树上的右边界,每一个节点我都要去趟一下我左树上的右边界。

你一共有n个节点,你如果每一次都去便利,你左手上的右边界,他还是b o n吗,下面我们就来证明他还是b格温,怎么正最直观的方式给你画一棵树,看看辩论在哪些节点来估算它的规模吗,这是整棵树对吧。

后面这个花圈的,我就算画什么,来我们看一下,首先你current跳动的代价是多少,一共能跳到几个点,反正是n规模对吧,你这个一会到两次,那也就两次而已,有些节点只到一次,二本身来到节点的次数是n次啊。

b o n次,这个理解吧,卡尔的本身它来到节点的个数是b勾n次,所以下面我只要估计一件事就够了,我我现在不纠结你每一个单独一个节点,你要过几个节点,我就看看所有过程里。

所有节点去遍历所有节点的左数的右边界代价是多少,同学打一,那我们不去纠结单独一个节点的时候走了多少步,然后乘以n那个东西我们算不准,我们也不知道这个数是啥样对吧,我们也不知道我们现在算的一个东西是啥。

把所有节点遍历它们左数右边界的代价都算上,我们看要过几个节点干这件事好,那怎么算来看,我说你我问你,你第一次来到一跟第二次来到一,你过哪个节点二五十一,对不对,是你过了几次呢,你过了两次为是不是两次。

你第一次到一的时候,你要把这个11的右指针,把把这个11找到,把右指针改成指向它,第二次到这个一的时候,你要找到这个11,把他右指针改回来两次吧,你编辑到这个二的时候,你变了哪些节点。

通过它左数的右边界,19也是两次,病人到三的时候,你贪过哪些键的右边界,63也是两次,你到四的时候,你通过哪几点右边界就八自己五的时候就十几,六的时候就12,自己七的时候就14自己。

你没发现所有的右边界最多过两遍吗,所有通过右边界的总代价是多少,这一共有几个节点呀,不就b勾n规模的嘛,所以每一个节点把任何一个节点所有汤这个行为便利,这个左数右边界的行为全算上就是整个数的规模。

节点数量乘二也就了不得了啊,所以即便一个节点有趟过他左数右边界这件事,总代价也不会突破b格温打一,新新人类同学哪哪个地方没太懂,一个节点左数右边,这这件事情我已经都给你列出来了是吧,好再讲一下。

我们再讲一下啊,嗯,这咋讲,来到一的时候,第一次二五十一,你注意我来到这个二五十一,我要遍历,就是从二到11就两次,这两次是谁带给我的,是这个带给我的,我问你,你有没有单独探二的时候。

有没有单独二五的时候有没有单独二五十一的时候没有,如果你说你一个你一个右边界单独编列二,下回可能单独变成二五,下回可能单独变成二五十一,那还有可能出现一个等差数列,这个东西就很难算了,但没有啊。

来到一节点的时候,我要便利就是一整条,而且只有来到一节点的时候,这三个节点在我变绿右边界的时候会碰到我一节点不就是二五十一,三个点,过了两次吗,你发现你每一个节点,比如二也有左数。

这个四九永远是因为二遍历到的时候走的,走过的四九就没有拆分的时候,每一个节点自己左树的右边界你都画一下,你会发现都是不重的,你发现了吗,每一个节点的左数的右边界都不会跟其他节点的左数右边界重在一起。

都连共同的部分都没有,那你整个所有节点左数的右边界都是独立的,你一共几个节点呢,还没有算137 15来对吧,我就算这个画差的,他最大规模不也就是b o n吗,而我任何一个节点如果要过这个边界。

最多过两次,哎所以所有节点通过它左数右边界的代价不会突破它,听懂了吗,对吧,就是没有就是没有任何一个左树,没有任何一棵子树的左树右边界是跟另外一棵树重的对吧。

换句话说你整棵树其实是可以被所有的右边界分解掉的对吧,都是不重的,那不就那代价很低嘛啊,我们来想一下,我们现在已经搞清楚莫is序了,开始做一件事情,那怎么加工出鲜血来呢。

同学在听过基础班的已经知道了是吧,第一次来到一个节点的时候就打印他,你就是谦虚,你第二次来到一个节点的时候打印它,你就是中旭,那如果对于没有一次,只有一次到达节点,你就认为就打印。

因为他第一次跟第二次是合并的,举个例子,啥意思,还是这棵树,它moris序是什么,12251363,这是他more is序,我第一次来到一个节点,我就打印它,它就是先序遍历,这是我第一次来到一。

我打印第一次来到二,我打印,这是我第一次来到四,我打印他也只能到达自己一次,对于这种节点,你说我们是可以去判断的,怎么判断他没有左数不就知道了吗,一个节点如果没有左数,你死混就直接打印它就行了。

你根本就不用去问,那第一次还是第二,第二次对吧,这个二我们能知道他他会在第二次回到自己的时候,我们是能知道的,不打印,第一四次来到五打印,第二次来到一不打印,第一次来到三打印,第一次来到六打印。

第二次回到三不打印,第一次来到七打印,这是啥,这个顺序它就是先去便利啊,打一,哦,那中序呢一个道理,就能回到自己两次的节点,我们就让他第二次手打印,对能来到自己一次的节点,直接打印。

怎么这个一我们能不能知道他回到自己两次,能知道为啥,因为他有左数,也有左数,而且第一次我能知道不打印这个四没有左数,他只能回到自己一次,直接打二,是第二次回到自己的时候,我们能知道打印五只有一次一。

第二次回到自己,所以打印三他能回到自己两次,所以不打印六只有一次三,第二次回来的时候打印七打,因为只有一次,这个顺序45425137不是中序吗,啊,这个时候我们要想一下了。

你还记得我在基础班里给你费了将近十分钟,给你讲递归怎么实现二叉树遍历,当时有忍不了了,说这他妈克胎他妈水了,你现在再想想你那课有没有意义啊,好好听,我跟你讲,我跟你讲的没有废话。

这么多年来我才懒得说废话呢是吧好,我们先看代码,然后再搞后续后续有点复杂的,morris in,还是改变量名,它是current,most right,啊啊啊,不好意思,他是most right。

是看着他,中序遍那时候咋说的,一个节点一个节点,如果,没有左数,直接打印该怎么移动,怎么移动,它往哪移动呢,如果一个节点它没如果如果当前看着节点没有左数,它会往右移动对吧,打印完之后往右移动。

如果开着节点,它有左数,说第一次来到自己的时候是改完指针之后往左移动,第二这次轮到自己的时候是改完指针改成空之后,就他右孩子,他左树上最右节点的右孩子改成空之后往右移动的,这个时候我也打印。

总结为只要一个节点要往右移动了,你就打印就自然规避了,能回到自己一次节点的时候不打印嘛对吧,他规避了这个时候打印的时机嘛,所以我们二次病例怎么改的,我什么都不用管,只要一个节点要往右移动了,我就打印。

他是说不打印,能回到自己两次的节点会continue不打印,刚才打一,便利对吧,如果你压根儿如果你压根儿就没有左树,整个这一大坨衣服跳过,你会打印当前节点并往右,你说合不合理,将合理,对不对。

如果你有左数,完了之后,中的是第一次来到你的时候,你continue是不是没有碰到这行,打印逻辑也合理,对不对,只有是你第二次来到自己的时候,你改了指针之后往外跳,再往外跳,你在一往右移动之前打印才对。

所以就加这么一行打印它就是中序遍历,打一没能打二,你打过同学就算了,好吧嗯,我们再看先序遍历怎么改,他改动了一点点,一开始是没有这个的啊,是没有这个else的,把这个去掉的,没有这行打印的。

除此之外就是源代码,好我们来看一下,哎呀不想改,就这样吧啊好吧,如果就是most right,如果我没有左数,我这个衣服会跳过没有左输的节点,我第一次跟第二次是不分家的,我应该遇到他就打印。

所以你怎么写,蓝色代码既然是有左数的时候。

你就给它加一个,没有左数的时候就打印完了吗,对不对,看如果有左数,你就给我跑蓝色代码的东西啊,之后你不会再进到这个里面来,只会卡着它往右移动,是这意思吧,如果没有左数五就会中这个else,然后往右移动。

所以在加了个else没毛病,这个else就只是为了给能够只能够到达自己一次的节点,它会跑这行扣的在哪,对于能回到自己两次的节点,这是第一次回到自己的时候,我再把这个打印行为加在这一行。

不就代表的是能回到自己两次的节点,第一次到的时候打印不能够到达自己两次的节点,死活就直接打印就行了,看同学打一,这就是先去便利,本来搞后续了是吧,下面就剩后续了,这是啥呀,好难弄。

对后续感觉怎么都弄不出来啊,我告诉你这么弄,把毛意思序搞清楚,去注意打印时机,放在能回到自己两次,第二次回到自己的时候,就这么三个打印时机,但是不是打他自己打,他左树的右边界逆序打印啥意思。

我第二次回到二的时候,左数的右边界是四,逆序也是四,我第二次回到一的时候,左数的右边界是二五,请你逆序打印,当我第二次回到三的时候,我左数右边界是六,请你逆序打印,这个过程完成之后。

单独打印一下整棵树的右边界,逆序137,打印逆序731,后续便利,听到他在打一,得得得自己再弄一下,我再给你写一个奇怪怪的书吧,有有有没有同学打二打二的,没听懂的同学就打二嘛,大方一点是吧,再来一下啊。

今天我们说你是不是可以便利遇到每一个节点,你也知道这个节点是来一次还是来两次,还是只有122次是合并的对吧,你是第一次来到你,还是第二次来到你,还是你只会来到自己一次,我们都知道。

势必能够找到现在这个底下这个序列中画三角的这三个时刻,这个这个没有问题吧,这三个时刻我们能找到的同学能懂的,打个一,人家能找到这样的时刻,对不对,在找到这样的时刻的时候,我们打印什么。

不是打印它这个节点自身,打印它左竖的右边界,而且是逆序的形式,你当我们来到二的时候,我们就找到它左数的右边界是四,就逆序打印它只有自己,当第二次来到一的时候,我们就逆序打印它左侧的右边界就是五二。

来到三的时候就打印它左树的右边界就只有六自己,但是这样的一种方式呢,我们会错过整棵树的右边界啊,最后731要自己单独弄一下,为什么想到的证明还记得吗啊,你咋想到的呢,你说我咋想到的,我刚跟你说过。

整棵左树啊,只用一只用子书的右边界就可以把整棵树分解掉,我刚我跟你讲过这个事儿,你来到他的时候就逆序打印你的右边界,来到他的时候就逆序打印你的右边界,你每个都这么干,不就是后续吗,刚讲过证明的时候。

棵树可以被子树的右边界分解掉啊,就到一个节点的时候,我逆序打印它,左右边界就依次出来了嘛,但是最后一个整棵树的右边界是没人搞的,所以我要单独搞一下才打一,大家可能还没有注意一个问题。

老师你说的流程我懂了,但是,怎么逆序打印我左树的右边界,你现在给我一颗子树,有东西我不知道是啥,你现在给我一颗子树,这玩意是a,它底下是b,它底下是c,它底下是d,然后他就没了,假设让我逆序打印。

我得想个办法,按照dcba的顺序打印,怎么弄,我放到站里去吗,你千万不能放到站里去,为什么我我们就要求莫尔斯便利,额外空间复杂度比个o一能用战,你怎么逆序打印你某一棵树的右边界呢,继续想一下。

对反转链表我们两分钟之后继续,我觉得最疯狂的就是最后一步翻转,代表了,啥叫你举个例子,这是current诶,你现在已经两次了啊,已经来到你两次了,你左侧的右边界,这是a他左边可能有东西,我不管他。

他右边指向的是个b节点,b节点,它左边可能有东西,我不管它那右边指向的是c这个节点,c这个阶右边可能有东西,我不管,但它这个节点肯定是指向d节点,d节点它就只回current了,是这种情况吧对吧。

我第第二次来到ka的时候,必然是这种样子,当然你也可以假设更多的边界节点,我这里就假设四个好吧,把他调过来,d的右指针它肯定是指向空的,他左边可能还有是啥,我不管干嘛,你用你假设a的左孩子,b的左孩子。

c的左链条,d的左链条,这些左链条你都不管他是不是一个单链表啊,电表的话,你让a的右指针指向一个空,让b的右指针指向a,让c的右指针指向b,让d的右指针指向c,这个你会不会调,不就单链表的反转吗。

完之后你就可以从d走到c,从c走到b,从c走到从b走到a,从a走到空了,你就打印了,听完之后你得把你再把数调回来搞定,听懂他说打一,复杂度会不会因此增加,当然不会,你原来是左树的右边界,过两次。

现在变成了过四次,都不都是常数次嘛,所以时间复杂度继续闭个听我同学打一,过两次,过四次,只要是有限几次不都是b格温吗,对不对,所以后续代码怎么写的没那么难。

后续整个行为其实跟morris遍历没有什么区别,改个名,它叫current,它叫哎呀,操,整个代码其实没有什么区别。

就在这儿,还是这个well,只只是把这个操作行为放在哪一行了。

这一行能够回到自己两次,且真的第二次回到自己的时候,你逆序打印我整左数的右边界,你就把它当做是一个黑盒,打印某棵树的右边界,逆序的形式逆序打印某棵树的右边界,你左数传进去,他就打印了。

打印完之后你再给它调回来,这都是黑盒,你跟while就加这么一句,但你不要忘了在while结束的时候,整一棵树的右边界,你再来这么一下,就是后续接下来不就是怎么实现怎么逆序打印一棵树的右边界吗,21下。

每一步打印在reverse回来没了,要打一,你说这有什么难的呢,对吧,不是线段数,这叫线索二叉树,理解吧,什么叫线索二叉树,就是利用这种类似于摩尔便利的形式,我下去一节点,利用我的空闲指针能串上去。

这叫线索二叉树,这不是线段数,完全两个概念,好啥用有啥用,我现在让你判断,你告诉我这棵树是不是搜索二叉树,我问你,你怎么做,但是你要写一个递归,你去判断你或者用那个二叉树的递归套路。

你去判断24便利还需要吗,我给你随便改来,就这个,改一把我就叫我判断is就是布尔类型的一个返回值,is bs对吧,binary search tree是吧,你整棵树是不是搜索二叉树。

搜索大树不懂同学去看基础班吧是吧,这个讲没法讲是吧,这都不懂没法讲,你问一下吧,大家都知道啥叫搜索二叉树吧,知道同学点一,哎任何一个节点左数的值都比它小,右数值都比他大对吧。

常来讲判断搜索二叉树就是你中序遍历一下,如果你发现你的值一直在递增,是搜索二叉树,是这意思吧,啊听懂他在打一便利一下,如果你发现你中序遍历的序列中直一直在递增,你就搜索二叉树,实现这个就行了。

那我怎么实现来看啊,树为空,我就认为它是搜索二叉树,接下来这样弄啊,返回的过程中校验他没有违规的,我也认为他是搜索二叉树判断出违规来,注意看,设计一个之前的值,等于系统最小,这个这个也不太保险。

空白表示吧,之前的值认为是空好没有,可以吧,那我就认为它是个空好,中序遍,原来是中序变的代码,在这个地方是打印时机啊,你把打印时机变成比对时机不就完了吗,如果,它不等于空。

而且你发现pre的值大于等于当前节点的值的,啊你上一个便利的值如果是空,你不用判断你另一个值,如果变量的值不是空,这个只有大于等于你,你肯定不是搜索二叉树,因为我们说在中序遍历中,你一定要递增才行好。

如果这个没有违规,你把普瑞设成当前的value,就完了嘛对吧,这你就判断了整个搜索二叉树,而且额外空间复杂度b o一的面试场上你就吹去吧,听我同学打一,讲一下这种题目都很常考啊,吹这个别人没吹。

多提身价啊对吧,当然你也别说唉老师这题我会莫尔斯便利来搞啊,咱说唉咱时间不够了,你赶紧写下个题,老师不贼好是吧,你别是吧,那呵呵呵,你不要这样来好吧,嗯他他已经明显感觉到不想听了,那算了是吧。

你做下个题,如果他很有兴趣,你吹完之后,那身价杠杠的是吧,嗯意思吧,嗯好好,我们再做一个题,你讲完之后,我们讲一下什么题可以用编译,什么题,只能用二叉树的递归套路,啥样的呢,说起来很简单,一棵树。

一棵二叉树,知道上面的最小高度,最小高度只有我到了夜节点,我才有一个高度啊,在所有夜节点中,哪一个是距离头部最短的,把那个距离返回,特殊最小高度就是三啊,这个我知道这一个节点最高高度不是一吗,不好意思。

他不是叶节点,你不能以他收尾,夜节点才是产生高度的时候,以这这个是夜节点,所以它高度是三,这个是夜节点,它高度是五,这个是夜间点,它高度也是五,这个夜间点高度更大,返回按克数的最小高度,听懂这个题。

打个一啊嗯,那这个你就可以去搞最大高度的,同理的好吧,二叉树的递归套路怎么做,很简单,写一下,做题,来看这二叉树的递归套路,它只返回一个值啊,先说这个啥意思,以节点为头的时候,我的最小高度是。

如果我左树不为空,我求我左数的最小高度再加个一,右数不为空,我求我右数的最小高度,再加个一,两个比对两个两个两个相比谁更小,谁就是我的最小高度,如果我压根就没有左数,不好意思。

那我只能拿我右数的最小高度再加个一,没有右数,能拿我左数的最小高度再加个一,如果左右两数都没有,我的最小高度,就是一听懂的同学打一,这个题就就你看如果我左数也为空,我右数也为空。

我就一潜台词是这个x一定不为空,放心x一定不能让你为空,一定不会让你为空的,如果左我数为空,就数也为空,返回一,如果左数不等于空去求一个我左数的最小高度,如果右不等于空去求一个我右数的最小高度。

怎么加工出来,左数最小高度跟右手最小高度叫最小的那个,再加一好,毫无疑问有空间,额外空间很高对吧,高度就是你的额外空间是对的,但是太简单啊是吧,所以怎么根据摩尔便利来改写。

我们想通过morris遍历来改写它的难度是什么呢,难度就是我们整个过程中只能用有限几个变量,是意思吧,我们在整个过程中用有限的变量,有限几个,我的第一个问题是你current来到任何一个位置的时候。

你能不能知道他所在的高度,来到任何一个节点的时候,你如何知道他所在的高度是多少啊,问题第二个问题是,如果我能够知道current,此时他确实是叶节点,记录一下它的高度。

我用一个全局最小值mean来抓一下他,我我说这个这个如果它是业界点,我就把它的高度跟全局最小值比一下,如果它更低,就刷新这个全局最小值,如能够做到这两个机制就能改出来,听懂同学打一。

啊啊今天我要知道我当我来到任何一个current的时候,我能不能知道它的高度是什么,这第一个问题,第二就我能不能用一种机制知道current是否真实的,它是夜节点,如果都能知道这两件事儿。

那么我就在它叶节点的时候把它的高度去更新一个变量,那个变量就叫mean,他它更小了,我就更新它,它没有变更小,我就不更新它,整个过程跑完之后,我就得到了这个最小高度了对吧,我们先看第一个机制。

你能不能做到可以,可以是我现在的current高度,一开始是head对吧,他一定在第一层对吧,他一定在第一层,没错啊,所以坎儿呢一开始如果有一个高度的话,看着大等于had的时候。

这个这个这个这个它所在的它或者说它的层数,我在的这个level数,它是一开始有个默认值为一的,这个是肯定对的好,我们看你curren他无所述,下一步的current是往右移的。

往右移之前把这个level加加,一定去第二层,那我们如果我们发现卡尔的五左数看的我往右一式去更新,看着它它的高度也可以更新,对我当我下一回遇到的他往右移的那个看着他的时候,他的level它就是二。

它不可能是别的,所以我们可以由前一个current,它所在的结构如尤其如果他中的是第一种结构关系的话,可以直接由level加加就得到下一步看着它的高度,听我同学打一,啊,你们看第二种情况。

如果current啊有所述,他们的有所述,我们能区分出他到底是第一次来到自己还是第二次来到自己,他是第一次来到自己,我问你,他是怎么来的,为什么会第一次来到自己,这不是从底下这个层蹿上来的。

我现在讨论的是car呢,如果有左数,我永远是用下一步怎么做对吧,如果他有左数,说明他来到他自己一次,接下来这个current他是肯定会往左走,对不对,往左走,那level加加有没有正确,正不正确。

想怎么说呢,啊就这样啊,讲有点飘了啊,这样的啊,就是你,就这么一件事儿啊,就是你出初始的时候,你出的时候current它是它是一嘛对吧,我们看我们是不是永远能够推出便利到的下一个节点,它的高度是什么啊。

就想就想说这个问题,我们能不能又便利出下一个阶段,它的高度是什么,就是如果嗯如果你发现你自己无所树,你下一步的高度你是知道的,如果你发现你有左数,但是你是第一次来到你自己。

那你那你毫无疑问你是从你父节点或者往左走或者往右走到你的,确定的是第二种小情况,就如果你发现你curren他左既有左数,又是第二次到达你,你,那么便利的上一个节点是谁呢,右书上的是你左树上的最右节点。

高度是什么,这个节点减去它左树上最右节点的高度,就更新出你的了,直接举例子吧,太麻烦,来,我一开始就是呃画箭头的,就来到了点,他唯一对吧,往左走啊,我我我干了一件啥事,一指向了a,往左走。

我知道我即将往左走,我知道,往左走了,我来到b这个点,它高度是二,能更新出来,更新出来,你可以利用这样来判断一个变异的节点,它的左孩子如等于,此时你辨认到的卡润,它高度就是上面的高度加加得到。

听说同学打一我上一个便利到节点啊,我上一个变量就是pray,是我pray,其实就是a我上一个变量节点,如果我发现我是他的左孩子,我高度就是上面的高度加加理解吧,好我们继续你你做了什么。

你把d的右指针指向了它,你就来到了d,是这个逻辑,你发现上一个变量的节点是b,我是他的左孩子,我可以把我的高度顺利更新成三,接下来你这个d没有左数了,你是通过右数回到的b。

不能知道这个b是第二次回到自己的,你能知道一问上一个便利到的节点是谁,是d都已经到三了,我怎么办,我数一下我左树上最右节点有几个点减掉,我就从三能更新到二,都不回去,接下来我必往右移动,来到一。

你是不能这样判断的,你是不能p。right,如果与你当前节点,你不能用这个来判断为啥跟我们刚才,那你看你刚才你来到b的时候,你这么判断就瞎了,对不对,我这个b确实上一个阶段的幼孩子,他就是我呀。

那是窜上来的理解吧,所以你怎么办,你就看e如果有左数右节点,它指不指向你,如你这个右左孩子最右的节点是指向你的,你就去减高度,否你就加高度,我上一个节点是二,我现在一定是三,得到高度是三。

然后e就穿回a了,a他不这个条件它不成立,它没法加加二,拿什么判断,不能用,它用完了,因为我上一个辩论节点是e,我确实是他的幼孩子,难道我的高度改成四吗,不行怎么判断,我就看看,就我左树上最右节点。

这个右指针是不是指向我的,如果我知道它是指向我的,我就知道他是我上一个节点是通过蹿上来的方式到我的,我怎么得到我的高度,我数一下我左数右边界有几个节点,我给它减掉3-2,回到一听不懂同学打一。

哪一步我怎么判断,我就看看他是不是从上上一回蹿到我这上面来的,如果他是我左树上,如果我发现我左树上最右节点的右指针是指向我的,我就一定要跟把上一个上一个高度减掉一个值。

如果我发发现我左树上最右节点指针不是指向我的,哪怕或者说我压根就没有左数,我就知道我的高度加加一定对听再打一就麻烦在我们这个结构关系,它变了,我们人为改动了它的指针,所以他麻烦能够得到这个高度。

但是还是是可以实现的,懂这意思吧,是啊,那我们现在就搞搞定了,第一个机制就是我们在每一步的时候,我们每一步的时候是可以知道自己所在哪一层的啊,一直,能不能知道current它到底真实情况下是不是夜节点。

为什么真的到你到一个叶节点的时候判断不出来的,你为什么判断不出来,因为他的右指针一定是改过的,来的时候把五的已经改过了,二来的时候四已经改过了,等你真的到四的时候,你不知道他是不是真实的业绩,点一。

current到哪个点到不了这个东西是不是夜节点,那我们怎么把所有叶节点拿到呢,叶节点都会在能回到自己两次的节点的时候,重新发现一遍,啥意思啊,我让五指向他,二,四指向他,来到四的时候,我什么也不管。

来到四的时候,我什么也不管,错过了没错,从四回到二的时候,我能够知道这个二,我底层上来的,我给他恢复完了之后,我看看我左树的右孩子是不是业界点,也就是说你是来到二的时候去抓四的高度更新全局命的。

到一的时候把恢复过来之后去抓,看看五是不是叶节点,去抓五的高度去更新命的美节点都在你两次那个节点的时候,就是他上级某个节点的时候再重新发现一遍啊,一,不要忘了整棵树的右。

整棵树最右的节点是没有人去发现的,所以你在整个流程跑完之后,你要单独自己去找他啊,跳我再给你换一个,换一个比较奇怪的树,让你感受一下,一指完,指来到三三,这么指来到十十,这么指来了10,一回到十。

回到十的时候啊,过来检查它是不是叶节点,并且把它高度重新算一遍,更,就往右走,来到12,回到三的时候恢复过来,重新找到这个12,看它是不是叶节点,如果是把它的高度重新算出来,这里面是不用不用更新。

因为它跟11在同一层上对吧,然后三往上跑,来到一,来到一的时候,把这个阶回复回来,看看它是不是夜节点,它不是,那就不参与,四直接走,来到五九,这么指,八这么指同再回到六恢复过来的时候。

重新计算这个八的高度更新密啊,九九回到五,回到五的时候,7。9的高度更新灭,整个过程来到七,来到七,再往右结束了,整个过程没有七的参与,所以整个过程完成之后,单独看看整棵树的右节点是不是叶节点。

如果是更新密,这里你特殊的就是这个三,我再把它恢复过来之后,它不是业界点,要不参与更新,听打一,代码说起来很花里胡哨,其实没有那么难,还是感冒一次便利,哦,首先你看level怎么更新。

打一次的节点level直接加加,啊,这个我看一下啊,有对数器吧啊对有对数器,所以这个代码肯定是对的,哦嘶,一次节点level加加,如果是第一次到达自己level也加加,如果是达到自己。

那么毫无疑问上一次变调了节点,应该是减掉,我接下来就是,我们现在这个counter level还没更新,我能够到达了自己两次,我们是一定会把它这个most right右指针改空的,在改蓝空之前。

我看如果他左孩子也是空,表示我重新发现了那个节点,事业节点,我把先把先把它抓出来,在最小值更新完了之后再更新成我自己正确,再更新出我自己正确的level,就是,如果你如果你没有左数。

你就直接下一步来我加加就行了,如果你一次到达一个节点,你下面也会往左穿,你也会往下走,所以你level加就行了,如果到达了自己两次,如果我到达了自己两次,说明我一定是从底层那个节点窜上来的啊。

把捕获它层数去更新最小高度,这个时机和自己更新出正确level的时机放在了一起,没错吧,啊我如果发现我们我我左树上最右节点的左孩子是空在这里面,我要把它右孩子也调空的,说明他一定是业界点。

所以这个时候我就去记录,的那个当时没有发现,现在被我重新发现的那个叶节点的高度记录成全局最小值来,然后我成功地更新出我自己的高度,周而复始,整个代码跑完之后,整棵树最右的节点是没有人管的。

所以你要单独跑到整棵树最右的节点,如果它是叶节点,不要忘了它跟总的最小值,再更新一下,看看同学打,一啊,过粒子同学打个二,需要过粒子同学打个二没关系,那我就过一下啊,我就过一下啊啊最后这点不用管吧。

我问啊,最后我找到整棵树的右节点,如果这你可以看不断往右穿,不断往右穿,不断往右窜,看到了吗,发现从一开始不断往右窜,不断往右窜,往右窜的过程中,往右窜的过程中找到最优的节点。

如果这个最右节点它碰巧它又是夜节点,再去参与更新一下,最后这点不用管吧,最后这看懂同学打个一哦,不用是吧,那就是整,那就这个过程呗,好那就尽量给你搞一点多的例子好吧,弄多一点例子。

咱也别完全是完全二叉树是吧,或者是马二叉树,这没进,为了跟数值区分开来,我们把a b c d来表示这个数好吧,质数里面有的只有左数,有的只有右数,有的左右两竖都有,有的是夜节点,没问题吧。

好我们看这个代码会怎么跑,几个变量,首先当前节点所在的层数,你那么根据我们的代码,它是零,没问题吧,零全局最小值我一开始让它等于一个巨大的值,500吧,唉500就够了,只要在更新的时候。

我就要去想办法去更新这个最小值是吧,这它是我全局的一个值,这是一个整形,没错吧,好嗯嗯,到了current跟most right,我们都知道怎么怎么弄来看啊,这个函数一进来,他中的是哪个分支呢。

有左数的,所以它是直接进到这个while里面来了解这,你来了之后,他会去找自己左树的右边界,会找到这个e,这是我的,这是我,我用r表示来表示right,好吧,我用当前节点表示c啊。

当然他那是c找到的最左数,最右节点是r错了,你看我找到的过程中,其实我去统计了左树的高度,这不是高度,是我左,是我左数右边界的几个节点,他左他右边是不是不等于空,是的,加加变成二,一开始加加变成二。

来到e e在while里面就不用再继续跑了,e在这里面就没有继续跑了对吧,所以来到这个e的时候,我这个我这个变量就变成什么呢,left就左树上右边界的这样一个点的个数,左树上后边界的点的个数啊。

改个名吧,免得你歧义好吧,我们叫右边界,好吧右边记size可以吧啊那么左左数上右边界点的个数变成了二,还有没有要求呢,其实没必要,为什么,因为我e的右指针是指向空的,我e的右指针是指向空的。

所以但我明显地知道我下一个节点是往下走的对吧,我明显的知道我下一个节点是往下走的,所以我当前层加加,加加其实是更新才只是更新出了我自己的高度,这个一是什么,这是我的高度啊,就是这个卡尔呢所在的高度。

这才能更新出来,好下一层的它是我自己这一层的好吧,然后我们都知道貌似右指针指向当前的current,这都没有变化,然后current往左移动好,那就改嘛,然后car t往左移动,他就来到了b。

待定的一个东西了,那我们来看你,你依然是有左数的,你依然是有左数的,你有左数的情况下,补一下你有几个点到d就停了,r就是所以r r直接的右边界就是空指向空。

所以这个这个well其实这个well其实没有进去没有进去,没有里面加加也没有往右移动就直接出来了,它还是右边界数量是一个节点,一个节点是吧,右边顺序是这节点求得有用也没有用啊,也没有用。

因为我右指针是指向空的,我可以更新出我自己的level来了,就是加加啊,就是加加,所以加加变成啥,我现在两个二层上对吧,我现在二层上,然后我们根据我们的说法,他他的这个右右右指针是指向我的,我往左移动。

就是这样,那就这样就继续嘛,他往左移动,它就会来到d这个位置,来到d这个位置就变成啥了,来到d这个位置,它就是左树为空的了。

这一大坨衣服跳过,但他会中这个else,直接更新了我的高度加加。

那合理啊,我这个d d确实我在第三层啊。

我这个d我这个d我确实在第三层啊。

所以我加加完了之后就往右移动了,往右移动他就回到了b,到了b你可别忘了这个三是在是哪个节点的层数,你上一个边界的节点是你上一个变化的节点,我现在回到b了,好那么可能大家最关心的就来了。

毙了之后我有左数啊,我有左数,我左数就是d,我这个右边左输右边界先有一个节点,它依然是进不到这个while里面去,就停了,为什么,因为这个b这个b它的右指针是指向我的,他进不去。

你看因为这个我的我我我我整个左数最右节点的右指针它是指向我的,所以这个well它进不去,他就跳出来看了,那么一来的话,我其实我我此时我左数一右边界有几个点,一个是不是啊。

这就是我右边界的这个数量就一个就跳出来了,跳出来我看你看我是第几次到达我的第二次,因为,我我左数右边界的最后最右节点的右指针不是空对吧,我就走到这个else里面来了,他确实就像我,他没有指向空。

所以我知道我是第二次到达我自己来看,我在第二次到达我自己的时候,我先看看我书上最右极的左孩子是不是空,树上最右键的左孩子是空,说明什么,说明在我把他右指针恢复完成之后,他是个夜,它是个叶节点。

这时候干嘛,g我发现了这个夜,我看看他跟全局收集到的高度去pk一下,能更新更新能更新,我是500,你找到这个d它是夜节点,而且它高度是三,在这呢,所以就更新,这变成三,变成三之后,数出它的节点。

右边界节点数是一个了,你怎么更清楚你的呢,人家才是三,你又数出这有一个点,你减掉这个一,你不就是你的吗,所以就看到这一句,我当前的怎么怎么决定,当前怎么决定。

就是我现在的值减去我左数右边界点的个数就更新,我就层数了,然后不要忘了把他的右指针给恢复成空,这是肯定的,周而复始,没懂同学继续打二,我再给你过好吧,这里面每一句代码都是必要的,因为你找到的那个时机。

它未必是叶节点,比如说这个比如说当某这个时机我们来到a的时候,我们会发现它左数最右节点的右指针指向我,但是他的左孩子是不是空的,虽然我要把它右指针恢复成空的状态,但是它不能够参与我的更新。

因为他他不是e理解吧,那你看这棵树的最后一个最后时候是干啥,是单独找到整棵树的右节点h但是它事业也不要去更新这个密,如果他没有这个i那你就把它的高度求一下。

去更新这个面理解的意思吧啊所以这里面的人后招很多,就是你发现了你左树上最那个时机的时候,你还得判断你左树上最右节点,在你恢复完它右指针之后,它到底是不是e主要是这个点叫难嘛,是吧啊。

也就是说啊这种这种难题呢,实际上你在平时的练其中不太容易遇到,但是如果你面试中遇到了,他就很难给你涨身价好吧,这也是啊也是很不错的一个一个便利嘛,它确实省空间,它不需要什么额外空间。

它就有限几个变量是吧,好我们来讲一下它的总结,总结是什么呢,什么时候可以,什么时候你知道这个题的最优解是猫便利,什么时候可能不是,当你的算法求解过程,你接点x的时候,你去你左数给你信息。

需要你右数给你信息,你要做整合,如果你的解题方法定成这个流程,你就变成这个流程,你没有办法用莫尔斯便利一明显,你既需要你左数给你个答案,又需要又输给你个答案,一定不是bo一的。

你的空间一定不是b o e的,我左述这个答案,我得缓着我去右数收答案之后,收上来我才能用,都用二叉树的递归套路,但是如果你的求解流程,你发现我并不需要另有一,比如说我并不需要右侧数的答案。

我这个答案是递推的,我左数收完了答案之后,我用完它,我再也不需要了啊,就莫瑞斯便利改,比如说我们刚才那个搜索查数问题,如果你的流程我就想定成,我把我所述的最大值和我右数的最小值拿出来。

看看我他自己是不是做到二数,他是不是受到二数,我自己看看能不能连起来,你如果流程从定程,我就是需要很强的左右两侧收信息,这个流程你就用不了摩尔斯便利,但如果我们换一种思路说。

x只要在中序遍历的一个序列中,我保证它一直递增,你看这就属于我用完我所述的信息了,我并不需要往下,我并不需要继续了,我必须要留着它了,或者我只我用单独的一个变量,可以把这种递推关系给成给那个继承下去。

你就可以用吗,四便利,听我同学打一你,你定你把流程定成什么样有关,能定成什么样,有关有些题目是你必须收集完全信息才能解的,这种题目你就用不了莫斯便利,有些不是你通过你往下分析。

你发现你这个你这个信息是可以往下推的,并不需要我所有信息都留着,那你就那你就可以用莫尔斯便利很很空的一句话,但是啊就是说当你想出比较容易理解的解之后,你动一个心眼,你就拿莫瑞斯便利的流程去套这道题。

你看看你的信息能不能传递,如果你能像莫尔斯便利这样传递,你就能改,如果你觉得传递不了,它就改不了,听懂他打,而且在网上帖子里面,他很难有这些全部的证明啊,各方面的啊,有问题啊,这些了啊。

莫瑞斯病例有别的题目再给你讲,他其实其实讲一个也就够了是吧,这也差不多了啊是吧,因为它实际让你理解完这个便利之后,他真的是不难的,加工信息这件事吗,你把几个过程在代码里面都给你分的那么好是吧。

你看哪个阶段干什么事了就完了,是不是啊,会不会长相会不会很大,是有点大,但是你要知道大家说一个啊,我们调一个函数,它它它其实是比较常数项比较大的啊,函数要运行它的环境,在系统里面准备好它。

它常数是比较大的,比我no no等于note点,right,要要卖,你感觉有那么大常数,你怎么知道你调递归的常数不大啊,常数很大的啊,听我同学打一,嗯因为你你准备递归函数,那个递归函数跑的时候。

每个函数要组织起来,要只要给它准备运行环境,它它其实是很大的,所以你这样看起来我我就每一次接连点right。left真的是不大的,好吧,你找右数的最左有啊,那肯定有啊。

你这我们刚才讲了前其实类似于前驱节点,你可以用后期节点来搞也一样是吧,嗯我你要是聊算法,这个常数级别真的真的可以是可以聊很久啊,还有嗯,为什么呢,就是,嗯哦对啊,关于常数这个事得说一下。

就是你的数据它明显给你范围了,比如二位,我给你这里面的这个数都不会超过15个零,对于你对于这个题,你可能需要一张哈希表,注意啊,范围的话,你一定要拿数组结构来替代哈,希表啥。

你每个值你想知道它出现跟没出现,你一共就这么大,你这是一个help数组,哈希表零下标就代表零这个值出现在哪,一下标就代表一这个值出现在哪,你就把它认为是哈希表,你数据范围的值。

请你用这个数组结构来做哈希表,你别傻乎乎写一个哈希map,为什么哈希map里面我们在训练营第二节课会给你讲哈希map的实现,他的它的那个常数项是很大的,哈希map拿到任何一个值要做离散化。

掉一个离散化函数,这个函数它常数项是很高的,它绝对没有,因为他要不数组自己去贴哈希表要快听,我同学打一,一,这也是这也是比赛的同学经常用到的技巧,他你你会看到他很少去用哈哈希set这样的纯粹的结构。

它都是拿自己的数组去t的,你说你这个数组,你这里面它就是一个字符串,那你就用哈希表吧,那没办法,你不知道这个字符串它能它它怎么我们要用数组来代替,对不对啊,这个时候你就用哈希表,放心用是吧。

有些我说这个是什么意思,一般来讲刷题的时候不会因为你常数项过大就让你不过,代码不会因你常数项过大就让你卡住,它往往就是你时间复杂度没达标,它会设计良好的测试,用力的大小。

让你时间复杂度不达标的时候才不过你时间复杂度是要达标,哪怕你常数项大一点,它也会让你过,但是总有一些一些公司他在准备这个数据量的时候,他没准备好,这就要求你平时写的时候,你看你发现它是一个整数。

而且它的数据范围不是很大,你就直接用你我们数组结构做出来的来替代哈希表的功能,因为常数项呢这个问题在哈希表里真的是挺大的,虽然你可以认为增删改查都是b o1 ,但它常数项其实挺大的,理解吧啊,运气唉呀。

这同学你看哈训练你不觉得少了一节课代码吗,第四节课代码啊不对,第四节课代码是讲资源限制的面试题,第一节课的代码诶,怎么不对了,不再多占用大家时间了,我跟大家说,我训练营的。

下下一期就把哈希函数及其哈希函数相关的结构都给你讲了,哈希表布隆过滤器一致性,哈希底层算法原理都会讲,就是下一个训练营就是下啊,唉悟空同学是我老同学吗,好,啊我带过一个徒弟啊,这他是用了四个月进头条的。

他之前没摸过算法啊,名字叫悟空啊啊,满分十分啊,明天见,明天讲,明天讲这个,以及相应的题目,还有ac自动机,好吧嗯,同学是个二本啊,对四个月四个月的时间,但是二本啊,所以这个拿自己脑子说事啊。

真的你脑子绝对够用,好吧真的嗯,原来我原来带过一个国外的培训班,把一个卡车司机八个月给他送进facebook,这司机怎么样哈,哈哈所以你你不用不用怀疑自己给你讲的东西,给你讲东西,你好,课下好好看。

把所有扣的都练过,提高非常的快啊,提高非常的快,如果你懒得去敲过课上讲的代码,那就咱就不谈了,好吧嗯,那就啊好啊,行,那明天见好吧,嗯满意的跟我们工作人员聊,在qq上跟我说,我会改进好吗。

系列 2:P69:左神算法-暴力递归 - Java视频学堂 - BV1Hy4y1t7Bo

来了啊,能听到吧,稍微再等两分钟啊,今天我们讲图的算法,这个肯定是要拖了,下节课,下一刻能够把课结了就不错了,也就是说我们原本12节我要讲到,16节是吧,嗯基础课,然后开完,下周开完基础课之后。

直接就给大家开这个训练营的课程,或者说这个进阶版的课程啊,各位今天休息啊,五一没有祠堂直播课,五一我们没有上直播课,所以中原同学是你上一回是听到二叉树的递归套路吗。

那么我们就接那么二叉树递归套路的下一节就是昨天讲的,五一没有直播课啊,五一我没有看,没有没有直播课,休息了,啊,今天今天的课呢我们要想顺利讲完,你首先得理解两个东西,第一个东西就是并查集昨天讲过的。

第二个呢是一个之前给你们细致讲过的一个东西,就是自己手动改写堆结构,大家有印象的同学打个一啊,什么样的题需要我手动改写堆结构才能够实现,什么样的题可以用系统实现的堆结构我就能实现。

这个我是在我的之前的课,用了将近一个小时的时间给你讲过这个内容的是吧,就说你上了堆的东西,如果你又想改变它某些字段来影响他在堆上的位置的话,那么你就要手动改写堆结构,如果你给他的东西,他给你吐出一个。

你给他东西,你不再改动了,或者说不再改动他参与排序的那些字段了,那么你就不用重新自己手写一个堆结构对吧,这个还给大家在课上现场实现过吗,那么我们今天要用这个结构啊。

这个结构是在dj特斯拉算法里面的改进里面需要用到的一个内容,再说多少分钟啊,因为还有些同学要进来。

今天今天的内容其实还是不少的嗯很多人写图的算法,觉得写的不顺利是吧,你一次每次遇到图的题就挂是吧,刚来的同学可以看一下这道题,我们想做什么啊,在这儿,昨天讲了一道题啊,只是今天想现场实现一下嗯。

也不难啊,这说一下啥意思,就是昨天我们留了一道题,昨天我们留了一道题,说这个你看有每一个user,他有a b c3 个字段都是string类型的,当然你也可以是别的类型啊,这个无所谓了。

我们就假设他都是死string类型,那么这个user就是如果两个user a字段的值一样,我们就认为它是一个用户,可能人家多建了几个账号是吧,但是只要a字段一样,就认为是一个用户,那同样道理。

只要任何一个用户b字段一样,它也是一个用户,只要任何一个字两个字,用户c字段一样,它也是一个用户,那就有可能会就说你比如说我这两个用户,它它俩a字段一样,他算一个用户对吧。

然后这其中一个用户呢又和另外一个用户b字段一样,那其实三个用户是一个用户对吧,就是你尽量合并,最终我问你,如果两两个用户a字段一样就能合并或者b字段一样就能合并,或者c字段一样就能合并的话。

请你返回合并之后的用户数量,这很明显用并查集做的,这很明显用冰卡奇做的,昨天我们提了这个题,但是没有实现,这个有多少同学昨天没来,或者是不知道并查集的,打个二听来过,然后听了我讲的打个一,我天哪哎呀。

那不可能重复讲了是吧,能不能粗略的说一下这个是啥意思啊,你寄几不要紧,你今天即便不懂并查集的具体实现,你也能听懂今天的内容,你只要接受这么一种黑盒就行了,什么黑盒呢,给大家多啰嗦两句啊,这个并查集啊。

来看一下啊,不要慌啊,你这个不会并杀机不要紧,你最多就是不会实现嘛,但是你知道冰沙机它干啥用的,你直接今天这节课,你先默认你这个黑,这这是一个黑盒,我把想用的功能给他托管,它不就完了嘛对吧。

托管给他不就完了嘛是吧,不影响你今天听课啊,什么叫并查集呢,简单提两下啊,就说有你有若干个样本,abcd一开始认为这几个样本各自都在自己的集合里,就是每一个样本他都在自己的集合里面。

这个集合里面只有他自己,每个样本都是这样的,那么我就可以我我就可以提供一种结构,一开始先把所有的样本各自做成小的集合对吧,各自做成小的集合,然后那个用户可以调用这些方法,就是查询x和y是否属于一个集合。

这是第一个方法,第二个方法注意第二个方法很有意思,第二个方法是x跟谁合过的,全部都算上它背后的所有的东西,只要跟他合在,就跟我一起的东西,把y背后所有的东西彻底两大集团合成一个集合。

就是我们的unit方法好,并查集就是就是做这两个用的,你可以认为并查集就是做这两个功能用的,但是而且is the same set的方法跟用on方法可以做到单次调用的时候,时间复杂度bo 1。

这就是冰沙机的功能,就啥意思呢,我一开始把一坨样本全部搞成各自的小集合,然后我可以我可以调用,你查询is same set,x样本和y样本是否属于一个集合,就是他俩连其实或者换换换,换一个意思理解。

就是他俩联袂连通在一起,布尔类型返回,如果连通在一起了,它是一个集合,就是true,如果不是一个集合就返回false,这是第一个功能,第二功能就是unit方法是吧。

就是我们的unit方法就是呃联合那个方法,联合那个方法,如果x跟y你要想要和的话,他不是说xy单独合在一起,是x背后所有的东西和y背后所有的东西,你们彻底合成一个大集合。

这两个东西想要实现这两个方法想要实现的都高效,其实就是我们的并查集设计,但是他你现在现在你现在你你能够通过学习之前课的视频学会,所以我又不想在新的班去再重复讲一遍,你现在就接受一种设定。

就是我现在理解这两个方法,同时这两个方法单次调用的代价是b o e就能做到这么逆天,我看他能做什么,听懂同学打一,这就是并查集,刚才打扰同学,现在理没理解,理解了,给我一个,给我个提。

给给给给我个提醒是吧,你理解啥意思了吧,嗯理解了好啊,这个并差集可以删除特定的指定链接嘛,其实通过改写是可以的,但是要注意啊,你这个改可以删掉某些东西吗,其实可以,但是他不是最经典的冰沙机。

这里面还要抬再抬十线是吧,这个并查集,如果你就是要做落路径压缩或者是小集合去挂大集合,这两个优化始终坚持的话,你没有办法做删掉有某些东西,但如果你从来就不做过路径压缩,你也从来不小集合就挂大集合。

谁挂谁无所谓,这像这种就可以做这个某些特定的删除,但是并查集的这个优化后的性能优势就荡然无存了是吧,这个我不知道你听没听懂我说啥是吧,嗯已知的bo一除了哈希表并杀鸡,还有其他的吗,呀这个。

其实可以设计很多这个结构,你就你为什么这大帅同学这个b g o e这件事情要这么总结是吧,这个有点奇怪,但是现在目前为止提到的确实只有哈希表跟并查集,增删改查b o e的好吧嗯。

但是我确实也没有想过以这个时间复杂度b勾一来分类是吧,呵呵我一个没有没有没有没有这么总结过是吧,可以可能还有别的吧,嗯他我是根据基本上根据功能来分的是吧,他有些东西适用于哪些不适用于哪些来分的。

现在目前讲的确实只有并查集和这个哈希表啊,好那我们来看一下这道题,我们来看一下这道题,昨天昨天提到的一道题,怎么用并查集来解,我先把冰渣机贴在这儿是吧,你不用管实线,你就管功能吗。

具体时间大家可以看上节课视频啊,因为听过的同学不想重复讲了,浪费时间是已经有视频了吧,这个病查体你不用管它怎么实现,你只用知道我有一个这个对吧,我有一个以same set的方法。

有个unit方法行了是吧,而且都很高效,他可以把两个样本查两个样本是否所在一个集合,以及两个样本背后所在的集合彻底合成一个大集合,是这意思吧,好我们来看这道题,昨天讲过了,现在先来写一下。

这道题是说如果两个user a字段一样,这是一个user,两个user如果a字段一样,就认为要合并在一起,他是认为是一个用户,如果或者两个用户b字段一样,它也要合在一起,认为是一个用户。

如果两个字用户c字段一样,它也要合在一起,认为是一个用户,那你会那你会可能会有,我举个例子,比如说你第一个用户是10,这都是字符串啊,假设13,第二个用户呢是二,37,而第三个用户呢是400 537。

这意思就是说这三个用户只是一个用户,因为你看这个用户跟这个用户因为算一个对吧,而这个用户跟这个用户又算一个,所以他们三个其实是一个用户,就让你这道题其实让你就是a字段一样的用户,就认为是一个该b字段。

c字段也一样,你该合并合并,问你在这个user里面到底有多少,合并之后合并之后的用户数量有多少,听我同学打一,好啊,那么注意我们现在我们要开始玩这道题了,刚开始怎么玩这道题呢。

我们要先把所有的user给它变成各自的小集合对吧,每一个user就自己的是是自己各自的小集合,然后看看怎么合并吧,所以我怎么做呢,常见做法是这样的哦,我申请一个并查集是吧,这个去掉,申请一个并查集啊。

这个冰沙机里面放的样本类型是什么,注意你可以放user,也可以放这个整形,哎你为什么可以放整形,是这样的,就是说比如说我们user 0 users里面的零用户,按道理来说他就是实力对吧。

按道理来说他是个实力对吧,哎我们能不能用下标零来代表他呢,可以吧,同样道理,你说你user user一它里面是个实力对吧,你能不能用下标一来代表他呢,可以对吧,所以你在并查集里面。

你未必要放这个user,你可以里面都放下标,都是整形不就完了吗,听懂同学打一,就是你你可以把一个一个的user放进去,没有问题,但是你还是你还可以把下标放进去,零下标一下标,单独成一个集合,可以吧对吧。

完全可以这么做嘛,所以我们怎么做呢,这样来啊,我们把这个并查集改一下,初始化的时候改一下怎么改,就这,一共有多少个size,你告诉我,然后我怎么初始化,i从零开始,i小于s,i加加,然后。

i小于size,然后i加加,然后这node是什么啊,这个这个没没没有,我我一会儿再说,没有学过,昨天没有学过的同学,怎么怎么理解啊,这每一个node呀,这每一个node哦,这个冰沙机里具体的去。

如果要这么改的话,就这样来吧,好吧不这么麻烦了,就不用咱们,咱别别用下标来代替了是吧,这个因为他这个改动比较大,我就写成泛型了啊,写成泛型,那就用原来的user吧,那就这样来。

每一个每一个每一个东西自己去初始化去是吧,但是他这里面又是数组,我靠还是得改得这样来啊,这个v类型的数组是吧,v类型的数组每一个去初始化学,这个这个这个大家现在所有的没有没有昨天没有听过并查集的同学呢。

你就这么理解,就是说我们要初始化一个并查集,初始化一个并查集,我们现在是我们说的是这个user里面所有的user不是单独成一个小集合吗,那么你在这个并杀机初始化的时候。

要先一股脑地把这些user都给这个结构以后,你就可以直接用了,理解这意思吧,啊我们不拿下格来代替了是吧,没必要就拿这个原始的这个就叫uni fn的结构是吧,冰沙机,他来一个初始化,这里边我把u都传给他。

那那那就哎呀好烦是吧,然后我们把这个刚才给恢复过来,他就是一个list的类型啊,好吧,那么你看这个诶这个为什么,哎呀无所谓吧,他们报警报警报吧。

这个这个这里面一开始就把所有的user啊放到这个病查体里去了是吧,他是初始化好了,然后我们怎么合并呢,这么想先进,那先建立一张哈希表哈,希map string对应一个user,此人对应一个user。

我们管它叫map a啥字段就是a字段a字段的map是吧,这里面都放着key,就是这个string是放着某某一个user a字段的值,然后这个user就是哪个user有这个值。

哪个user的a字段是它对吧,有个map a同样道理,你再建一个map b,再建一个map c,再建个map b,再建个map c,先把它写完啊,先把它写完,然后把这个把这个哈希表都建上啊。

然后我们开始便利user了,那么现在就拿到每一个user了吧,拿到每个user了,怎么怎么,我们这算法是什么样的,算法是这样的,就是这个map a里面放着某这边map b对吧,这个是mac。

假设某一个user,它它这里面第一个字段,比如说是第一个字段,假设是字符串类型是吧,是个a b c,这是他的a字段,下面字段可能是k s t d字段,在下面可能是t e f c字段对吧。

你对于第一个user来说,你就把这个a abc它是属于哪个user呢,当前的user对吧,假设它的内存地址,他是他他他这个实例的内存壁纸是a是吧,那就a b c它属于a的k s t。

k s t它也属于a的c e f它也属于a的,然后下面一个字段如果是b它第一个字段假设是b c,它下一个字段讲的是k s t,它再下一个字段可能是e f那么对于这个bc来说。

你就看一下之前那个map a中有没有bc的字段,没有没有,他没有,就说明b不用通过bc和任何user要合并在一起对吧,我原来的map中没有bc吗,我这是新出现的bc嘛。

所以b的这个user不会因为bc这个字段连在一起,那我直接把b c登记上b就行了,然后你看这个b的第二个字段叫k s t,之前谁有这个k s t啊,a用户有这个k s t。

所以我在后台把a和b所在的集合连在一起,是不是等同于他俩合并了,他俩现在属于一个集合了,对不对,我就通过k s t这条这这这座桥让a和b连在一起了,连在一起之后并查集里面他俩永远就是一个集合了。

所以你这个k s t属于谁,你可以让它还属于a,因为反正后台a跟b是连在一起的,再看e f e f之前的mac里面没有ef这个字段,所以也就是说b不用通过ef跟任何东西桥连在一起,直接ef等于b好。

你就用这种策略,每次一个新的用户到来的时候,你都看看他的a字段之前有没有人出现过,有的话就通过这个条桥连在一起,第二个字b字段跟c字段也一样,如果有,如果有过这个字段,就跟之前某个用户联合在合在一起。

如果没是新字段,就建上在这个表三个表中建上它的值,表示你是新出现的这个字段,因为并查集会把所有该连的东西全合在一块儿,所以能够实现你的要求,听懂同学打一。

刚才是忘了加这个是吧,这个早上起来有点懵是吧,好了行了,这就对了啊,然后呢我们就想就想这么做,那怎么做呢,这样,这么写啊,这样不是,如果,user。a啊,这个map a点,content,user。a。

啥意思,map a map a里面之前还有过user。a的这个字段对吧,那你合并吗,当前的user和之前map a里,user a字段的拥有者合在一起对吧。

user背后的集团和原本有user a这个字段的那个之前的那个,user这个背后的集团彻底合在一起,是这意思吧,否则否则你这是个新字段,是这意思吧,同样道理,bc你也这么干,map b。

这也是map b,这也是map b是吧,这是c,这是c,这也是c,要改一下字段名,啊最后干嘛呀,其实你要干这样的步骤,就是,像并查集,像并查集询问,合并之后还剩多少个集合对吧,是这意思吧。

你你你之前一开始所有的user在这个并杀集里面都是独立的,你们现在通过,要么通过你每个user的a这条这个桥该合的合,b这个桥该合的合,c这个桥该合的合,是不是有相当多相当多的集合被合成了一个集合呀。

他一按道理来说是你在这个并查集里面还有多少个集合,就是有多少user,对不对,所以怎么改这个呢,那我就改一下并查集,就是你给我返回u的数量加个方法是吧,get size,get size版本是吧。

在冰沙机里面这个表可以直接告诉你啊,没关系,不会的同学你你你你回去看视频你能懂,你现在就知道说我可以向并查集要他还有多少个集合这个数量,昨天你看完视频你就懂了。

你现在只能接受说我可以用它的这个用你方法是吧,该合的合在一起就可以理解是吧,最后你就返回你这个并查集他的,get set member嘛,这就这就搞定了是吧。

好这个方法有没有不懂同学不懂的同学打二听懂他打一,一个集合代表唯一的用户吗,不是只要是该合的合的一个连通区域代表一个用户啊,有没有不懂同学不懂同学打个二,或者说发个行号,哪个不懂。

我看有一个同学打了二是吧,昨天昨这是我们昨天的课,在最后的时候给了一道题,然后我们说上,但是那是我临时加的一道题,现场给你,现在实现一下,那刚才打扰同学你你你就先发一下这个你的困惑点是吧。

或者这个哪一行不懂,我再给你讲好吧,我们先先开今天的课行吗,一个联通区就代表合完之后的一坨那一坨,用户认为是一个人,好那么我们现在来开图的内容啊,这个图啊,其实这个图的问题在这个代码中。

它是可能算是鄙视中比较难以去比较难以难去写的一个类型是吧,但实际上你要知道它的难点并不在于它算法难,他并不在于它算法难,今天我们讲如果要是往后讲图的算法的话,你会发现算法都还行,没有特别难。

它难就难在它这个数据结构比较复杂,数据结构比较复杂呢,有有些同学可能哎呀理解了这个图算法每一次新遇到的一道题目,如果你临时在它那个结构上去写算法的话,你会发现你每一次面对的图的结构如果不一样。

你的算法都得重新来一遍,这个是啥意思,啥意思呢,就是说对于图来讲,你可以认为是先解释下什么叫图图嘛,就是一些点和一些边连接起来的对吧,这个点这这这有若干个点,我可以在任何两个之间来一条边对吧。

这这其实就算一个图了,虽然说他没有整体连通在一起,它只有两个连通区域是吧,但实际上你知道就是这是一个森林而已,什么叫森林呢,就是它不是一张图,它是多张图,它就是一个森林,那如果这个这个东西是连在一起的。

他就是一个图的样子,就是它它不是一个森林,它是一棵树木是吧,所以就是任何一个任何一个点,几个点,每两个点之间都可以都可以出现一条边的话,它就构成了一个图,它跟我们的二叉树不一样,我们二叉树是一个点。

要往下左右两个孩子,左右两个指针指的特别严格,对不对,而且没有二叉树中,也没有某没有某一个指针,它是往上指挥还的,对不对,所以我们不用在二叉树,它是比较简单的一种形。

形式图呢就是你任意的点中间可以任意划线,但是他就分一些什么有向图和无向图,就有向图就是每条边带方向的,就是有向图,如果我认为这个两个两个点之间只有一条边,它是没有方向的,代表两个点都能够到达。

我可以从这条从这个点通过这条边到达它,我也可以从这个点通过这条边到达它,这叫无相图,事实上无向图和有向图你都可以理解成有向图,为什么你说你无向图,你不就是它指向这边有一个有向,这边只回来再加个有像。

他不就是无相图了吗,对吧,两个点之间我到他有个有向,他道我有个有效,这不就等同于他是个无相图吗,对吧,所以我们理解图你就可以理解为one,每一张图万图都是有向图。

只不过无相图的时候就是两个点彼此之间有两条有相边,那你就可以随便连嘛,你这这这这这都是图,对不对,这都是图,这样一来就有问题了,我日常是怎么表达图的,他就有个讲究了,对吧,他说白了图很简单。

如果我如果我说有个东西有图的话,那无非就是你的典籍有哪些东西,有哪些点构成,然后有编辑有哪些东西对吧,这个编辑呢就是哪两个点之间有边都记录在编辑里,点击,就是你到底有哪些点记住在典籍里。

这个就是我们日常理解的图吗,他可以随便连他也可以有,还要随你随你随你随你的便,你甚至于可以这个这个这分子向指向自己也行是吧,无所谓,但是你怎么表达一张图,它就是个问题了是吧,你自己画出来的图你肯定知道。

那你怎么表达他呢,常见的方法有两种,第一种方法叫邻接表法,第二种方法叫临接矩阵法,我们分别来说一下,比如说我们这张图,假设他是个无向图,那么无向图实际上就是a到c。

a到c有路有个有项c到a结果有像b到c有向c到b结果有效是吧,d到b有项b到d a果有像d到a有相a到d a果有像,这不就是无向图吗对吧,所以你无论什么图,你都可以理解为有向土是吧。

好那么怎么表达这张图呢,邻接表法咋做的,临近标法是你以点为单位,你有哪些点,a b c d是吧,好,我写在这a b c d,然后他后面写什么,后面写的是和这个a点。

直接就从从a点出发能到的直接邻居写在冒号后面,那你看一下从a点出发能够到的直接邻居有谁,c和d吗对吧,所以它有一个c,有个d,同样到了下面,从b出发能够到达的直接邻居有谁,c和d。

从c能够出发到达直接邻居有谁,a和b,从b出发到达直接邻居b和a,临街表法,如果你每条边是带权重的,如果你每条边是带权重的,比如说,比如说我a到c的权重是三,c到a的权重是四,就是边上是有代价的话。

如果边上是有代价的话,那么你就可以在这个封装一个结构吗,a到c这条边的代价是三对吧,而c到a这条边的代价是四嘛,就随你去封装,对不对,这个无所谓,你边上加值还是边上不加值,对于临界表的表达来说。

这个结构是一样的,无非就是多半多有一些伴随数据而已,连接表法理解没有任何问题,同学打个一,好那么还有第二种方法呢,就是临接矩阵法,连接矩阵法就更好理解了啊,临接矩阵法就更好理解了。

这个邻接矩阵法就是说你你有你有几个点吧,你用a b c d4 个点对吧,好a b c d4 个点,a b c d44 这四个列你给我填这个格子,这个格子代表a到a的距离零,现在往a到b的距离该是啥是啥。

a到c的距离该是啥是啥,a到d的距离该是啥是啥,如果比如说a到b是没有直接距离的,如果a到b是没有直接距离的,认为正无穷,认为他没有直接的路,就是正无穷,你比如说你这里面a到c的距离是三,你这个前三。

然后你说你比如说a到d的距离,你是七,那就就就就就填七,这不一样嘛,对吧,你看你b b到a有直接路吗,没有正无穷,b到b的距离是零,b到c的距离,你给它一个值,比如说这是六,那就六,那b到d的距离。

你给他个指甲是一,那就是一,然后c到a的距离,4c到b的距离,给那个值假设是五好吧,5c到c的距离0c到d没有直接的路,正无穷,啊所以这张表你就认为是个绝对是个正方形表,那你那你当然可以把所有的边。

你你我我们为什么可以用一个邻接矩阵就可以表达一张图呢,因为你这个表是不是可以做出一个全连接呀,没错吧,你a到aa到b a到c,a到b b到a b到b b到c,b到b c到ac到b,你回复键它是全连接。

而你的图肯定比全连接或者小于或者就是全连接吗,边数一般来说这边数不可能在大于全连接了,对不对,所以你在这张表里,如果你有直接的路,你就写上他的全职是什么,如果你没有直接的路,你就正无穷吗。

所以这张表依然是用这种方法也可以表达整张图,听懂我同学打一,好这就在下面我再跟你说图的题目最难点的地方,它就在于图本身没什么难理解的对吧,我们小时候都画图是吧。

但计算机里面的图呢就是点跟点有点各个两个点之间利用边连接起来,这种东西就叫图,难点就在于你不要把什么算法在各种表达图的结构上都来一遍,我用邻接表法去实现一个算法,那我底层的数据结构。

那个图的结构是连接表,我要在临接表上玩一遍所有的算法吗,你玩完一遍之后,你又在邻接矩阵这种结构上要玩一遍所有的算法吗,那下回换一个图结构的算法,你是不是还要来一遍,难就难,在这能表达图的结构很多。

可远远不止邻接表法跟邻接矩阵法,比如说我们刷题中,或者说你们在比试过程中最特别常见的一种表达图的方法,是这样的,啥样的呢,我看一下啊,啊对啊,他是这样的,他给你一个矩阵,第一组数据704。

第二组数据41415,第三组数据323啊,444413吧,第三个数据323,第四组数据,四,啥意思,每一个小数组都是三个数,第一位数据代表一个边的权重,第二位数据代表from点是什么编号。

第三位数字代表to点是什么编号,这个可以表达一张图啊对吧,你比如说从04,相当于就是它权重是七,然后从13啊,那权重是四,从23呢,全中是三,从24呢群众是八,就这么一张图。

你会发现这这这个结构也可以表达一张图,你难道把每一次这个图的底层结构变了,你都重新写一遍算法吗,而且如果在笔试过程中,你要现场去守撸,你大概率是要出错的,因为图的结构比较复杂啊,不管用哪一种去表达。

写的代码都会比较多,哪怕算法在算法理解层次上并不难,他也会很容易出错,因为它表达图的结构,写的本身这个篇幅比较大,听懂我的说法,上来打个一,好所以怎么办呢,所以这个这个这个课就给你推荐一些私货了是吧。

对所以这个有个同学很聪明对吧,知道我要干嘛了,就是这个这个志豪志豪同学是吧,就是说你你自己平时练图的题目啊,你你你你你不管是什么样图的题,你都转成一种你熟悉的结构,你都转成一种你熟悉的结构。

然后算法a玩一遍,在这个结构上,在把算法b玩一遍,在这个结构上把算法c玩一遍,把你以后想实现的算法都在这个结构上玩一遍,那么你以后去面试的时候,他可能会给你一个陌生的图结构结构结构一个撇儿对吧。

这时候你干嘛,你只要把结构皮儿写一个转化成你自己的结构,然后你再调用你现成的模板,你不就行了嘛对吧,用户输入是一个新的结构,你你根本不需要在这个结构上再去实现算法。

a算法必须和算法c或临时的那个什么该什么算法,什么算法不用,你只要写一个接口转化类不就完了吗,然你这些东西你保证正确,直接调个模板给他答案不就行了嘛,对不对,这不是,这不很快听懂,他在打一。

所以我这节课就给你推荐了一个我的写的方法对吧,他他这个他这个就是属属于我自己在刷题过程中,这种结构很好用对吧,然后你你未必完全按照我的结构来,但是我告诉你这个我这个我写这个结构,它兼容很多东西。

然后我们来看一下我我给你推荐的结构是啥样的,这个no的结构,这就是点的描述,点结构的描述,点结构的描述啊,这个点上它有自己的value值,这个是你可以是string类型,比如说a这个点a这个点。

那你这个value可以变成string类型的a编号为零的点,那你这个value就是零,理解吧,这个这个note上面这个value就是它的编号,它的编号你也可以把它改名叫d都行啊。

那么这个这个点上它的in是什么意思呢,入do什么叫速度,就是有多少个点通过走路是连向它的这个out的,就是初度,就是他自己直接出去的边有多少,这个就是他直接接收的边有多少,这个是他直接出去的边有多少。

入都跟初度,你们都学过吧对吧,然后这个note里面它有自己的邻居,直接邻居,注意啊,这里面我们来讲一下这啥意思啊,我给你举个例子,比如说有个点,这个点的编号是零啊。

这个点这个点这个点是指向直接指向它的啊,这个这个点是指向他的,这这这你看这个就不算他的入度了,他的入度就是三,它的热度就是三,理解吧,如果他往外有弱的干条边,比如说它有四条边,初度就是四。

只算直接出去跟直接进来入都是三,它出的就是四,他的他的在这个点里面,它往下,比如说它往下的点是a,这是b这是c这个是d d往下,如果还有fc往下还有e等等等等,那么我只记录他的这个点。

这个点的直接邻居a b c d,只记直接邻居a b c d,所以这就是这个点中耐克词的含义,它是一个release,下面是no的类型,它指的是直接邻居的意思。

而且你不要把之前的这这三个点算作它的直接邻居,我们所说的直接邻居指的是这个点由自己出发的边能到谁,叫他的直接邻居理解吧,这就是我们这个next,那这个那那你现在虽然不理解。

我现在还没有讲编这个数据结构对吧,那但实际上它也就是说我我如果把这四条边都做成实力的话,那这个点他下集所有的边就是四条,就从他出发的,会放在它这个边所组成的,而release里node的描述都听明白。

同学打一,这个,有的同学我看见有个弹幕啊,弹幕说,小的同学说这个不是更简单吗,行吧,你觉得更简单的,你就写嘛是吧,你的模板就是那个行吧,我这里面用这种方式是比较容易让人理解的一种方式。

就是跟你脑脑海中想的图差不多的方式,无向图的速度跟速度一样的吗,对一定是一样的,然后还有什么问题,哦没啥了,in in in是next的size吗,不是,应该说out是next的size。

这个印是有多少东西连向我,这个in是有多少东西连向我out是我出去的,我的下面的邻居都是以我直接触发的触发的得到的邻居为主,边也是我出房,我从我出发的边,这个是out的指出度啊,in是这边。

这是入读理解吧,好大家都明白就行了,这就是这就是所谓的点描述,这就是所谓的,点描述,然后我们再看边描述啊,边的描述就很简单了,你你一条边一条边,它上面有权重,没错吧,这个边上面有权重,可能代表距离。

可能代表什么别的别的事情,那不管,反正我上面是有权重的,至于你怎么解释这个权重根据不同的题目来,对不对,那么一条边有一个from,有一个to就行了,注意这里面的边这边肯定是有向边。

因为我们说任何图都可以理解为有向图,无向图只是任何两个点之间既有两个方向上都有一个都有有向图,不就完不就是无向图了嘛,对不对,所以我只用管有向图的结构描述,因为无向图它可以用有线图拼对吧。

也可以用像素表达,所以这个边啊他就是有一个自己的权重,有个from,有一个to,这就是我的边任何一条边,它的描述我们再看图图就更简单了是吧,图就是典籍和编辑嘛,你看这个这个典籍是啥。

为什么这个哈希map就是0号点,编号为零的点,那个点是什么,编号为一的点,那个点是什么,编号为二的点点是什么等等等等,你看这个点的描述,它后面不有个不,里面不是有个y6 吗,它就代表他自己的编号。

我在这我在这个整个点击里面,我希望通过某个点找到具体的实例呢,我就给写一个哈希map结构的典籍,key就是我的编号value就是我实际的点,那么这个编辑就是个哈希赛的结构,所有的边都在我这个编辑里。

一开始这张图是空的,所以点击也啥也没有,编辑也啥也没有,这就是我一个一张图的结构描述对吧,好,我们来看转化,就是你对于所有的东西来说,你只要转化成我的我的图结构不就完了吗。

我们来看一下转化怎么转化的假设啊,这里面我只是给了一个例子,就是刚才我们讲的这种例子,就是刚才就是我们我们以一组数据,第一个的一维数据叫某一个边的权重对吧,二维数据叫这个这个边的from点的编号是啥。

是个整数,第三个位置是这个这个边啊,它是从from指向to的那个to的编号是啥,这也是个整数,权重也是整数,如果假设我我一条一条的是这样给你的形式,可以让你处理图的。

你怎么把它转化成我们刚才讲那种图结构,来看看啊,他这个永远是n乘三的矩阵,n就代表你有n条边,但每一条边都是三个数据对吧,它的权重它from上面from的点是什么,to点是什么,好我就开始转了。

我先开始转了哦,在这里面这个顺序换了一下是吧,无所谓啊,这是零位置对吧,这是我的from,这是一位置,这是to 2位置,没错吧,那么你看我这个i呢,就是每一条边这一组数据,这一组数据叫一个i对吧。

那么i0 位置那就是权重吗,i i i i号边里面的这个e位置,它就是from点,是编号嘛对吧,二位置的这就是to点的编号嘛,所以我都拿出来,当前我处理的是去众拿出来了,from编号拿出来了。

to编号拿出来了,好下面开始我一开始见这张图啊,它是个空的图,它里面点跟编辑都是没有的对吧,那我怎么怎么做呢,来看如果这张图的典籍里,他就没有出现过from这个编号,你说你要不要溅出from的点来。

建出来不就完了嘛对吧,在图的典籍中把from对应它点是什么给建出来,再看一眼这个node,这个note就是我有我的编号是什么,设置好,一开始入度为零,初度为零,我没有直接邻居是空的。

我用我上面也没有边空的,所以就只能把自这个点的编号设置好,就是它初始化的时候干的事儿,如果一个图像里,如果一个图里面没有from的点就建出来,如果有的话,你就不需要再新建了对吧,那么在图的点中。

如果没有to这个点,你就建出来,如果有的话,你就不需要新建了,没错吧,好经过这两个if之后,我是不是现在总能拿出from编号所对应的点以及to编号所对应的点来,没错吧,没错吧,我总能拿出这两个点来。

你不你甭管是之前建立过的还是现在新建的,我总能拿出来,我拿出来之后干嘛呢,你这是一条新的边,对不对呀,好我把边建出来,边怎么建,边先建立的时候把他的权重,把from点,把他to点传进去,他就初始化好了。

一个边有它的权重,有from点,有to点,一条边就会表达好了对吧,然后这条边表现好了之后,我问你这条边是从谁出发的呀,从from出发的,既然从from出发的。

那么to点是不是应该算作from点的直接邻居中的一份子,应该所以在from点的直接邻居中把兔点给加上去,是从from出发的,是不是from的初度加加是的,是的,这条边他是从from出发的。

是不是应该放入到from自己的直接编的集合里去,是的,这些事儿都干完,把这条边加入到大图形的编辑里,一条一条一条,我就相当于把用户给我的图转成了我刚才理解的那种图的表达,听懂同学打一。

你看我我这种方法只是说它题目输入的,如果是这样一种表达图的形式,我怎么转成我熟悉的,如果他给你临接矩阵,你是不是也可以这么转成你熟悉的呀,你怎么转,他给你的就是临接矩阵,比如说我给你举个例子。

01234,这边是01234对吧,他告诉你说,如果这个如果这个自己到自己的距离是零,如果没有路,就是-1,如果有路,它就是个正直,你怎么建这个,你说你怎么把这种结构转成你熟悉的,你就便利临接矩阵。

看到是证书,你就建边嘛,对不对,打一这是不是02有条边,理解啥意思啊哈哈,02有条边,下面如果零到-3是-1,表示没边,你直接跳,然后04,这边正数就到04有条边是吧。

你还是可以把所有的边都搞成你熟悉的结构吗,那么这样一来啊,我们就把我们熟悉的图结构给弄出来了啊,或者说你现在可以开始慢慢熟悉它,因为它这个在这个结构上写算法真的很爽啊,而且你排查错误的时候。

你该打印什么,打印什么的,还挺方便的,如果你是临街矩阵,你看你你可发现好多代码下标跳转的都跳转晕了,对不对,我为什么给你推荐,这么为什么给你推荐好好的一个点里面它的编号是啥,入驻是啥,出路是啥。

直接邻居是啥,直接编是啥呀,为什么给你推荐这种形式啊,内存描述它非常干净吗,内存描述也不是说干净吧,他直白吗,你看你的边,我为什么给你推荐你权重from点兔点啊,直白啊,是不是就是典籍跟编辑的组合。

这直白啊,这这这这就是你脑海中想象的最直白的图的样子,比什么临界表法,临接矩阵法,或或者是一种什么乱七八糟的图结构要好理解多了,对不对啊,有了现在我我现在给你提供的是什么。

点击编辑图描述以及其中一个接口转化器,你自己平时遇到图的题目的时候,如果你想使用我给你推荐这种结构的话,那你就每一次写自己的转换接口就行了,大家想象一下,如果你在面试过程中让你实现低于特斯拉。

然后你只要写一个接口,调用一下你之前准备的模板,这事儿搞定了,是不是让你觉得两眼一摸黑图的题目原来做不了,现在可以做了,那不就是写一个接口的事儿吗,有没有觉得这件事情变得不那么虐心了一点。

听懂他在打一啊,小龙同学说的对啊,这个为什么有图还要存编辑,有些题目跟题目有关系,的确你感觉冗余,既然所有的点里面已经有所有的编了,为什么还要单独存一份,有些算法它只让你处理所有的边。

比如说最小生成数对吧,是这意思吧,那是不是你我首先我这种结构我是不是贪图他表达图的方式最精简,不是我贪图的是什么,我贪图的时候,我做出一个很有潜力的结构,让你改什么算法都好改,打一。

这个翔的同学理解啥意思吧,我我我做出这个结构,我并不是为了贪图他图上面的精简,不不是我是为了这种结构下,你实现什么算法都好实现啊,就只用在这个结构中拿部分就可以了,甚至是拿一部分就可以了。

理解这个意思吧,好啊,我们来看一下这个,那么我们现在就来说一下图的一些经典算法了啊,这个都在这个结果上玩好吧,来啊,有点的集合和边的集合构成,虽然存在有向图和无向图的概念。

但实际上都可以用有向图来表达啊,身上可能带有全职啊,这就是图是吧,长表达方法,连接表法,临接矩阵法,除此之外,可能还有很多表达投的方式,图的面试题,如果搞定了算法都不难,但是coding代价比较高。

所以用自己熟悉的方式,用自己最熟练的方式实现图结构模板以后再遇到图的题目,直接自己写转化器是吧,我们来讲一下图的单独线便利和深度线便利,这个东西你们经常遇到是吧,它的宽度性便利,一个深动性便利。

这个代码很简单,我们直接拿这个代码过例子来讲是吧,单子无限便利,在二叉树章节的时候,我们说用队列,注意在图里面你必须有一个东西叫set,才能够完成它的宽度线便利,为什么为什么二叉树不用。

二叉树没有还的问题,二叉树进行便利的时候,他一个节点不会多次进入站的啊,多多次进入队列的,而图有可能准备一个set结构,我给大家展示一下流程,大家就清楚了,比如说这张图。

这张图我想从a点出发玩这个无限便利,其实你会知道说我a往下走,我能到能到b c d的对吧,但他们对于我来说距离是一,因为我跳一次就到了啊,如果边上没有权重的权重,认为都是一的话。

他离我就是跳一层的节点就是bcd,所以它的输出顺序应该是a b c d e,你要注意这个b c d什么样的顺序输出无所谓,因为他们都是离a有一层的位置,这就是所谓的宽度优先遍历啊。

e底下还有就是你你就是宽度,下面理解就是先是我自己,我离我最近的一层,而离我其次近的第二层,第三层以这样的一个顺序来一次遍历出来,但是同一层内部的顺序可以无所谓,打一,是。

优先便利跟广东优先便利是一个意思啊,那么怎么做呢,我们来看一下,我们准备一个队列,准备一个好,我们现在写一个队列,投进从尾出,这是个队列,还有一个set结构,都是空的对吧,然后,你指定宽度线便利的时候。

一定是从某一个点开始的,注意这个node可是我们自己描述的这个node,这个node可是我们自己描述的note,它有自己的值,有in有out,有自己的直接邻居,有他触发的边。

你看如果你只是实现宽度宽度优先便利的话,你为什么需要整张图呢,你并不需要你只要一个点就够了,所以这个结构只是为了兼容性给你设计的,但是对于宽度性格来说,我只要一个node就可以完成所有的打印了对吧。

所有的打印了,一上来这个no的进队列,然后在set中把它加上,那假设我指定了,你就是从a开始给我深度优先对吧,你就是从a开始给我深度优先,所以一上来就把a放进去了,投进从尾出,a在这儿是吧。

放进来直接放进来了是吧,然后a加进去好,接下来就开始玩了,玩呢队列一旦不,这个队列不等于空的时候,就给我重复重复重复这个蓝色代码的区域对吧,他是怎么做的,队列中弹出一个值,弹出就打印,中弹出一个东西。

弹出就打印他的所有的直接邻居没有进过,才进去啥意思,那么a就差,那么a就出来了对吧,a就出来了,a出来就打印,哪些直接邻居呢,看图有bcd问你了,你这个b是你的直接邻居,c谁的直接邻居d时的直接邻居。

他们都在不在set中都不在,好的都放到队列里去,bcd不要忘了在赛中也登记bcd,你a可以走了,a也弹出了这个过程,周而复始,你就看出这个feat的作用了,然后这个b弹出必弹出。

我问你他有哪些直接邻居呢,ac这三个直接邻居对吧,ac这三个直接邻居,把a放到队列里去呢,不放了,为什么set已经入过他了,你不用再重复再搞这个a了,把c放到这个队列中呢,不用了。

因为你这个赛中登记了他有c说明你之前放过了,把e放到这个队列中呢,放因为set中还没有这个e,所以把e放进去,把e注册上,看这个set的作用了吧,如果你说你没有这个set。

那么你把这个b重复放a a又重复放b b又重复放a,这个代码就跑不完了,对吧,所以b弹出的时候就直接打印,然后下面ac已经放过的东西就不重复放了,只把e放进去,好的可以可以结束了。

同样在c弹出的时候弹出就打印,他又直接邻居是ab都已经放过了,所以什么也不放,直接走,弹出的时候他的直接邻居直接就没有,所以打印完了之后,他就他也没有直接邻居对吧,你看他没有往出发发散的编码。

所以直接走,最后打赢一set的作用就是为了让你因为它可能有还,如果你不加一个机制来保证它每个节点都是只进一次的话,你这个代码很可能跑不完,跟他打一,这个就是这样。

你看啊我每一个邻居出来塞特不含有的这个邻居的时候,这个set才加到这里面去是吧,这个东西加到这个队列里去,set跟队列一定是同步加的,三队列一定是同步加的,它就代表一个注册表,这就是所谓的宽度一项便利。

我来看深度无限便利,深度无性便利呢这个比较难以理解是吧,或者或者或者他他或者说他比深度优先遍历要难理解一点,我们来给大家展示一下一个宽度优先遍历代码啊,就拿他就拿他这个图老图是吧,多加几条边吧。

免得这个e也没编是吧,d也没编呢,那这样好不,它还是一个有向图是吧,我们来看一下这个图,你想想深度优先遍历怎么读是吧,深度优先遍历啥意思呀,就是一条路走到不能再走了,你才往上返回,是这意思吧。

所谓的深度优先便利吗,一条路你走到死,走到不能再走了,你才往上返回,走其他的之路,就这个意思,没有人同学有困惑是吧,刚才刚才口误了一下对吧,刚才b的直接邻居是c和e,没有a啊,也一样的是吧。

你你你你同样道理,你看你这个当时当时写的队列里面的东西是b弹出的时候,还有一个c有一个有一个c,有个d对不对,弹出的时候他们刚才讲的是它有一个直接邻居a啊,没有直接邻居c。

然后有个直接邻居e我们说这个c就不要重复录了,e进去,同样道理是吧,也是为了防止他跑不完,b有个直接邻居c c有个直接邻居,b就他俩就足以让你玩到天荒地老了对吧。

所以你还是要一个set保证一个节点不要重复进队列啊,刚才口误了一下,说b有一个直接邻居,并没有直接邻居a好吧,口误了一下,不影响理解吧是吧,不影响理解吧,好,好好我们现在玩这个do有限便利,要用对用战。

dfs也是你给我指定一个点,我指定一个点,有一个站还得有一个set,它也是保证不要重复进问题啊,因为他可能有互相指这个事,所以他要一个set来保证这种机制不要重复来回走是吧,我就现在就画好这张图。

我们假设从a出发吧,从a出发有一个站,这样画大一点啊,然后有一个有一个set,是专门登记用的是吧,那么一开始一上来,进到站里面去,进到set里去,是这意思吧,把a放进去了,这a也登记了,接下来看。

他这个打印时机是近战的时候打印,我以后的打印实际都是你看啊,这个比如说某个节点,它的后代去的时候就打印他的后代的,就他永远是进去的时候打印,同样道理,你把打印换成处理时机。

它不就是在用路优先来处理某些事情嘛对吧,这个打打印你可以替换成具体你要处理的事情,根据你的某可能下一回你做题的时候,某一个题的业务来把这具体替换成你想改个处理的具体,因为这里面打印只是只是举个例子。

对不对,好它是入的时候去打印它这个a在进去的时候,我就把a给打印出来,开始我们开始跑这个站对吧,开始跑这个站,他这个逻辑说的是什么意思,看上去也比较绕,就栈中弹出一个节点弹出就不打印了。

为啥你入的时候已经打印过了对吧,所以我们看弹出弹出的时候就把a弹出了,弹出了,这里面就没有a了,然后注意他怎么说的,从前弹出节点去枚举他的后代,只要有任何一个后代是没有进过站的。

任何一个后代是没有进过站的,做什么呢,你就把这个当前的没有进过站的后代,把他的负重新压回去,再把这个后代压到站里去,登记这个后代,打印这个后代,你想后代不便利了,这是啥意思,就这个意思,你出来了。

对不对,a有哪些后代呢,有一个b的,有有一个b的直接邻居,有一个c的直接邻居,有一个d的直接邻居,当我编辑到b的时候,这种情况就发生了,你说这个b他是不是不在set中,不在对吧好,我就把a重新压回去。

当前的b也重新压回去,我把币给登记上,这可掉了,c和d还没有来得及便利就break了,这这这这个这个逻辑,他他说的意思,看我所有我的所有直接邻居啊,只要有任何一个没有进过站,负压回去。

他的后代压进去打印直接break,然后又开始跑这个大歪了,那就是只要有任何一个邻居没有进过,你先走这条支路,他邻居在后续的某一个时刻再继续搞啊。

我们继续看,越讲大家越越明白我在干啥,那么这个b进去了,进去就打印,给我解释一下这个站是啥意思,站里面它记录的其实是你现在深度优先遍历的路径,现在走这条路,其实记录的是你现在这个站里面,他从占比到站顶。

依次表达的是我现在目前为止从头节点走到的路径,我们继续怎么继续重复刚才的行为,弹出b,出b之后,b有哪些直接邻居,他有一个e他有一个c,你是不是又不在这里,e又不在站里,所以我们是电力到e的时候。

就等于是什么,把b又重新压回去,再把e压进去,再把e登记上,111近战就打印,如果没有,等到bbc就break了,看一眼站是不是代表你现在走这条路是a b,然后一直到e站里面。

永远记录是你当前深度优先的那个路径,看到了吗,好继续,基于什么呢,继续就是一弹出哪些邻居只有一个d,他只有一个d,那这个东西是不是没有进过站的,是好,你给我进去,进去d也进去吧,负节点进d也进。

然后一进去就打印d等于说你这个站走的路径是a b d,接下来继续,那么轮到d弹出,d弹出他有哪些直接邻居,他只有一个a,没有在战中他进没进过,他进过,为什么set里面有,他说明你是优先这条路径c呢。

没有还没有c对吧,还没出现c没错,还没出现c所以说明你这条路径a aba abd这条路径走要尽头了,你再走就出环了,你这个d再走就走到a自己了,就出环了,干嘛呢,他的后代a是进过的。

所以就直接遍历的过程中一次都没有中,看到了吗,便利他的后代过程中一次他就只有一个a嘛,所以这个if就从来就没有中过,那么直接这个for循环搞完了之后,他什么也没有发生,前节点弹出就弹出了。

也不找回了,这是什么什么什么情况,就是d弹出之后就走吧,也没有发生,等于什么呢,等同你你原来的路从a b e b e d啊,跳回到重新跳回到e节点e还有没有其他之路,让我往这条路上继续走,继续弹出。

异有其他之路吗,没有它只有一个d,而d又是已经入过站的东西,说明你所有支路走了已经走完了,所以你这一弹该弹出就直接弹出了,相当于我就从原来的a b e的状态退回到ab这个状态,退回到ab这个状态之后。

b重新便利,他有哪些直接邻居,他依然有一个e直接邻居,有一个c这个邻居没错,但此时你编译到e的时候,他已经进过队列了,飞的时候是没进过的,c的时候是没进过的,没见过,干嘛把b重新压回去,c也压进去。

加入就打印,就等同于你原来的路是从a b回推到退回到b节点之后,你又走向了c的之路,一条路都是走到死。

再往上返回的就是这个代码,打一,有的同学说,那你如果b的邻居有c有e先搞c再搞e呢,无所谓,都到宽度,那都到深度一项便利,有c有e如果先循环c呢,无所谓,如果你先循环到了c。

那就等于说你选择了先走向c的支路分析,那有什么关系,那都叫深度优先遍历,再给你举个例子,有的同学可能没懂是吧,你再给你举个例子,说这个我们重新玩一下好吧,我也想深度线便利,站。

假设从a出发一进去就打印a set里面登记a a有哪些直接,然后a弹出,还有哪些直接邻居,他有b有c有d,如果先选d也行,你先选c也行,你先选b也行,你先选什么都行,他们都叫深度先便利,要深度权便利好。

那么我们假设先选b b的时候,我问你,你这个b有这个赛中出现过没有好,这是一条新的支路对吧,我没有走过的之路对吧好,我把a重新压回去,把b压进去,把b登记上进登记就打印行了,继续周而复始。

现在的路径我来到了a a到b轮到了b弹出,他那直接邻居,他有一个t有一个c先走哪条都行,都要深度性便利走向t的之路,有没有走过的,没走过,没走过,你就登记上,把你自己放进去,再把t放进去进去就打印。

相当于我走向了这个支路,走到这个之路,然后就轮到t弹出了,t弹出它只有一个支路,就是k只有一个支路,就是k k也没有走过,你t进去k进去把k注册上k打印,因为我走向了现在走向的这个分支叫ab tk。

每次都是这样是吧,每次都是这样,让我们继续看k呢,你也有一个分支,你只有一个分支,就是e怎么没走过好,所以k弹出了又压进去,这边是k这边是e把e注册上,一注册就打印,继续相当于我这个分支啊。

我a b tk又走向了,一看到一弹出,但是问题是一弹出他已经没有之路了,他就没有之路,是你这条深度线的路走到了尽头了,对不对,所以看是往上跳,所以e从这个站中弹出之后,就啥也没做了。

我相当于我的路径回退到k这条路,弹出k弹出k它只有一个支路是e我能不能知道我这条支路走过可以,为什么赛中有他,既然只有一条直路,这条支路又是我之前走过的,说明啥嗯,路已经走到尽头了,弹出吧。

回头到b t一出现,它只有一个支路,就是t k k这个支路有没有走过,走过,为什么赛中有它这个路径也走到尽头了,会会回退到ab b呢,它有一个t这个分支,有一个c这个分支,我要不要走这个分支不走。

为什么走过了,现在又走向c的分支又干嘛,b之后再把b压回去,把c压过去,相当于我回退到b这个分支之后,我又切向了c的分支,然后把c登记上,c登记就打印,然后继续什么c就弹出了,那我问你c它就指一个支路。

就是k而路是不是已经走过了,它虽然是当时t走过的,但是这条支路后续的路是走过了的,你c不应该再重复走,这个支路虽然属于c的,但他这个支路在之前某个节点的时候是已经走过了的,你现在忽略掉回到ab的状态。

c这个支路是走到了,但是没有后续的支路要走了,继续往上推,这回轮到b轮到b的时候,他有一个走向t的支路,有个走向c的路都走过了,回退到a的状态,到a的时候,a有一个直接邻居,b有个直接邻居。

c有个直接邻居d b是走过的路,c是走过的路,轮着d继续往死里走,不用再说下去了吧,听懂他在打一。

这个不抽了不抽了,赶紧讲吧,我们的深度性便利是吧,这个好,我们现在讲一个东西啊,拓扑排序,都不难啊,图算法都不难,更简单了,这玩意就更简单了,说的是啥,我们有一张图,这个脱骨牌序要求啊,图是不能有还的。

有环的图就没有拓扑排序的概念理解吗,有环的图是没有拓扑排序概念的,说无相图也不行,为什么你a到b的有向图,这这这这a到b的无向图,就等同于a有一条路只指向bb,有一条路指挥a这不是环吗。

所以提拓扑排序的时候,它一定是有向无环图,偷牌是啥意思呢,就是假设我用箭头来指向,挂,代表啥意思呢,就是你只有做完了a这件事啊,你才能去做b这件事,只有做完b跟a这两件事呢,你才能把c这件事做出来。

你看就是这个箭头表示依赖啊,依赖bc有依赖a b依赖a,e呢依赖c t依赖c就依赖e t一赖f如果要做事情的话,你给我排个序,谁先做谁后做这个顺序,a是最应该做的事情,做完之后一定要做b这件事情。

然后a b做完之后,我就能顺利做c这件事情了,这件事情做完之后,我要做e这件事,做f这件事完之后,我t的条件才能成熟,把t推出来,那么这就是拓扑排序,他就表示的是你根据这么一张有向无环图。

你把事情的先后顺序给我安排出来,听懂他在打一,这就是所谓的拓扑排序,更有没有效率更高的便利方式,这个,提到便利这个东西,它他不是有有就是有些时候你用宽流线便利来为了实现某些功能,深度线便利。

为了实现某些功能啊,他说有,你不是说唉这道题我可以用深度一些实现,可以用宽度一些实现的,问题是你如果这样,如果一道题目既可以用深度一些实现,又可以用宽度先实现的话,我个人要推荐你用宽度一些实现。

因为它代码很直白是吧,有些题目是宽度线没法做,我只能用深度优先做的,这种时候就是你没得选,图的常见便利就是要么宽度,要么深度啊,不是可以到t吗,没错,但是t它有两个依赖依赖。

c就依赖f也就是说你你做出t必须cf都具备才能做出t来,不是依赖关系,而且是所有依赖环境都具备了,才能把t推出来,这个意思你会说这个我我这个abc如果共同的能推出下一个d,你怎么拖五排序。

那abc这内部排序怎么样是无所谓的,但d一定要在它后面,同样级别的东西谁也不依赖谁的那些东西怎么排序无所谓,但是你一定要把这个事件的大块的顺序给我整理好,你像这个就是小块的顺序。

小块顺序a b c本来就确实无所谓对吧,我b谁先做谁都可以,但是d可能要怎么整体在他们后面的错误排序,错误排序是干嘛用的啊,常见的就是我们平时日常安排工作对吧,你领导安排工作谁先哪个做事先做哪个后做。

那当然这这个这个还是不够常见,什么是最常见的,就是你编译的时候,写的文件假设是a这个项目对吧,你的config文件是干啥用的呀,它是不是依赖关系啊,你依赖b这个包,c这个包b这个包对吧。

那b有他自己的config,对不对啊,b自己的config对不对啊,你依赖c这个包d这个包,而c也有自己的config,对不对啊,config文件对不对,他依赖z这个包y这个包。

你这你这种config文件就意味着bcd推出a那b呢就是c推出它,d推出它,其实就是你,你如果把整个的整个的你自己工程的所有config文件做展开的话,它就是一张有向无环图,这也就是为什么不要循环依赖。

一旦循环依赖,你这个肯定编译,不过你每一个小的文件都有自己的config文件,就是它的依赖环境,那你整张图不就是一张有向无环图吗,我们看我们吐口排序是干啥的,从最底层的包开始往上编译。

最终把你自己的项目编译出来嘛,听我同学打一,这个东西其实最常用的就是编译决定编译顺序的这么一件事啊,这真的很真的很常见,是不是算法简不简单,巨简单一说你就明白了怎么简单,在一张图中。

一张图中先找到入度为零的点啊,谁入度为零,a a就是a,然后把它删掉,删掉它的时候,消除掉它的边的影响,去找入度为零的点b删掉,删掉它的时候,把它的边的影响消除掉,再去找入度为零的点,e在再删。

再削影响找f再删,最后是c这就是脱口排序算法,这种同学打一,正确是吧,说了图的算法都没有那么邪乎,哪有那么多邪乎的对吧,它难就难在他做数据定制是吧,每个数据每个属专属于这个图的数据。

你要是硬搞一份q的话,那那就烦了是吧,好我们来看一下q5 排序,一张图,对吧,图这个图里面我再看一眼这个图里面有啥有典籍,对吧,你把这张图给我,我返回一个list捏成的一个呃。

就是由no的捏成了一个list,里面有有这里面所有的node,我们组织在历史里呢呃拓扑排序的顺序在这个例子里面依次出现,可以吧,所以返回一个排序的结果嘛,就是所有的node你给我组成一个list。

左边最左的那肯定就是排错误,排序比较小,好的是吧,就是啊啊依赖环境越往右的,就是你必须要把左侧的做完之后,依次往右边做的时候能顺利的执行完毕是吧,这就是list的,让我来看一下,我有一个in map。

这个in map是啥呢,t是某个no的,是什么呢,是这个no的还剩多少入度,这个in map里面是这个node还剩多少入度,你看我们刚才怎么说的,我们说先找到一个入度为零的点,消掉它的影响之后。

再找下一个入度为零的点是吧,所以我们其实有入度减少这件事情,就是一开始这个a啊,它往外指,它可能只b指向c c b可能还往外指,c可能还要往外指,一开始入度为零的,那么b速度其实是ec的速度也是一。

那就一开始其实你就认为b的剩余入度是一,c的剩余热度是一,那么当我a找到之后,我要消掉它的影响,那么b的入度要减成零,c的入都要减成零了,我们要用这样的一种策略来处理数据,依次找出分一次入度为零的点。

那不就是拓扑排序嘛是吧,所以要要准备一张这个一key是某一个node value,就是它的剩余入度,结构zero inq啥意思,值减成了入度为零的点才能进这个q,你当前你捡你,你不随着你这个入度。

每个点的入度逐渐变小对吧,有些点成新的,新成为这个入度为零的点,那么只有入度为零的点,或者说剩余入度为零的点,剩余速度为零的点呢才能进这个zero in q里啊,这名字也很直白,那么一上来怎么办。

我们先把图的所有的点集拿出来,你看这个图还是要看一眼这个图怎么得到他所有的点,是不是note这张表中的value就是他所有的点,对不对,这张表中所有的case是这个key,我们不要他。

我们要的是这个玩意儿,所以notes这个结构中的value就是所有的典籍的典籍,那么拿着一上来,在他所有的典籍中,这个in map初始化一下,那么开始所有的点,你说它的剩余入度是啥呢。

当然没有过任何变化,所以就把原始图中入度不该是什么,就放到这个map中,原始图中,既然你已经告诉我它是有向无环图,就必存在入度为一开始初始的第一批入为零的点,对不对。

这样的点我就会给它放到zero in q里去,每一个点原始的入度就是此时的剩余入度,因为你现在什么都没处理嘛,也你也没删掉什么东西,对不对,而p入度为零的点呢就被我率先的放到了这个zero inq里。

好,接下来,排序的结果我要依次在这个例子中把所有的点加上,最后返回对吧,那怎么做呢,in q的这些你像你像你已经进入了zero inq的点出的时候,你是不是可以直接把它放到结果中去了,他已经入度为零了。

依次从这个队列中弹出入你的结果有什么问题,一点问题都没有,谈的顺序一定就是拖五排序嘛对吧,你就加入就行了,那要你你现在这个点是已经出来的点,怎么样要消除你这个点的影响呢,就比如说刚才这个图。

我这个a点是初次入度为零的点,我怎么消除掉它对b它对b的这个入度为一的影响,c的入度为一的影响,那就看,是不是以我当前出来这个点是不是有直接邻居啊,因为现在我要被删掉。

所以因为我我我怎么样把我的影响删掉啊,我所有的邻居入都给我减个一呗,马上要删掉了,所以我的邻居因为我的影响,他们才入度,有了一,现在我我想把我的影响删掉,那就相当于在他们的热度表中减少一个。

消除我影响之后的我邻居的剩余入度吗,情况下,当然我邻居有可能消掉影响之后,它的速度变成零,邻居往这个zero 0 q里加周而复始,删掉我之后新出现的入度为零的点,放到zero 0 q里轮的。

就把所有错误排序搞好了,听我同学打一,就是蛮简单的一个算法是吧,下面我们来讲这个这两两个非常重要的图的算法的概念,就是我们的最小生成树对吧,啊这个你要是理解了并查集这个玩意儿就跟喝水一样容易。

巨他妈简单是吧,你比如一张图干啥用的,比如给你举个例子,五像图也可以是无相图啊,但是一般来讲最小生成树呢,上图也行,不像图也行啊,就是说首先要求全你,如果你是我们再强调一点,有向图和无向图没有明显借鉴。

没有明显界限对吧,无效图就是两个点,双方都有向,都有有向边的,有向图啊,它写成一个无向图,比如说这个全职是一,这全职是二,这全职是100,这全职是三,这全职是50,不能做到所有点都连在一起啊。

用整体权重最少的编的集合说我这个100这条边其实不需要存在的,这条边也是不需要存在的,这样的话所有的点也都可以连在一起,而是所有可能性中,全职整体最少的情况,这就叫最小生成树,就是你不能破坏连通性。

能破坏连通性,但是不也就是说你可以适当的删掉某些边,只要不破坏连通性,你就可以删掉某些边,问在所有的方案中,哪一种方案使得整体的权值最小,返回这个最小的全职返回这个编的集合,听我同学打一,这个。

密码这个密码同学为什么没有懂呢,就只是概念啊,原来这不是有个100的吗,这不是50的吗,我方案是把一删掉,把二删掉,也能做到连通性,用那么省嘛,因为你来留了个100,留个50,啥意思呀是吧。

因为不留这个一不留这个这个这个二呢,你把100个50删掉,这个全值不是很低,它整个全职是1+2+4+3,最少是吧,因为105是没有必要留的嘛,好多余的,废话不扯,那么这就是我们的克鲁斯卡。

也是我们平时所谓的k算法去生成最小生成树,什么流程啊,把所有的边,全职由小到大排序啊,所有的边根据全职由小到大排序,我们举个例子,他是一他是100,三他是二,他是50,是这样一个一个图。

那么我们知道一的边,二的边,三的边,50的边,100的边,这个,这么一个排序结果是吧,好我们假设呀所有的编译开始都没有加上去,开始所有的边都没有加上去,也就是说我在我边上画了对号,表示这个边被我选中了。

如果我画了叉号,表示这个边被我淘汰了,但如果我什么都不画,表示这个边只是后选要添加的边而已,听懂这个意思吧,那我就,是a这个点是a这个点是b这个点是c这个点是d好了,那我问你如果我要把一加上去。

左边的左右两侧的点,目前为止有没有连通在一起,没有为什么,因为这条边还没加上去,联通在一起了,我要一这条边a跟b原来是没有连通在一起的,现在连比如说a单独是一个集合,b单独是一个集合。

现在c单独是一个集合,然后是d单独是一个集合对吧,我这个一考察的时候,我一你问问你,a跟b是一个集合吗,不是一个集合好,现在你们是一个集合了,要这条同时把a跟b所在的集合连通,下条边二那条边要不要。

那就要看b和c是不是一个集合,b和c不是一个集合好所所以要这条边把b a b c彻底连在一起,三这条边,d是不是一个集合啊,b和d是一个集合啊,不不是一个,现在目前为止不是一个集合,好要这条边。

然后把d跟彻底连在一起,然后再51条边,c跟d是不是一个集合,已经试了淘汰a跟b是不是一个集合,已经是了淘汰,画一个复杂点的图,嗯最小生成树应该保留哪些边,还是那句话,如果我什么也没画。

表示这边仅仅是这边,仅仅是对着还没有加上去,如果画了对号,表示这个边被我要了,我要了我要他了对吧,或者画叉号表示这条边被我淘汰了,好我们来看一下,我们把所有的点编个号,所有的点都是不连通的,是不连通的。

然后我们把所有的编排个序小的边开始考虑,这有两个一,我你哪个都行,我先考虑哪个都行,假设我先考虑这个一,我就问这个两侧a所在的集合跟d所在的集合是不是一个集合,不是代表它没有连通,我就可以要这条边。

这条边之后a跟d就合在一起了,再看最小的边,开始就就就就轮到这个一了,那我问g所在的集合跟h所在的集合是不是一个集合,现在不是一个集合,好要这条边没事连在一起了,看小的边这一个我们还发现有多条二对吧。

会有多条二,这个也有二,这个也有二,这个也有二,哪条哪个二都行,假如先选这个二无所谓对吧,先选哪个都行,左右两侧一所在集合跟技术的集合是不是一个集合,不是,这条边,一就进了他们三个所在的集合对吧。

他们jh一是一个集合了,然后考了考上了这个2a所在的集合跟b所在的集合是不是一个集合,现在不是,所以要这条边,这个二对吧,从小到大嘛,h跟i是不是一个集合,不是好彻底合在一起。

a h跟i现在要连在一起了,该就该轮到三那边了是吧,那变了,有两个三,你考上哪个都行,这个这个边f跟g所在的集合是不是一个集合合在一起,f跟g g,b组在集合跟c组在集合是不是一条边,是,好吧。

b跟c合集合是不是一个集合,不是,所以把他拽进来,要这条边,完了接下来的考察,哪个该考察六了对吧,啊对该卡二六了,和i现在是不是一个集合,不是要这条边,于是他们彻底联合了。

该各自的集合跟这各自的集合彻底连成一个集合了对吧,然后考察啥了,该考察期了对吧,七你看先考到哪个都行,假设先考下这个7j和i是不是一个集合,已经是了,不要他,70还是七啊啊70对吧啊,那就那就那好吧。

那就那那你认为这是70吧好吧,那我就先考察这个七,别到时候又比估计你又你又理解乱了是吧,那这个七一旦出现c所在集合和e所在集合是不是一个集合,不是好的,在一起了。

c所在背后的集合和e背后的集合彻底搞成一片了,当你遇到这个50的时候,不要一说,不要80的时候,不要70的时候,不要剩下就都不要了,理解吧,什来做这个东西最合适并查集吗,它可以解决两大片连通性的问题。

听懂他在打一,啊它可以解决两大片联动性的问题啊,咱们编的时候真的可能把两大集团合在一块儿,冰沙机最合适啊。

k算法,啊这里面我对我的并查集啊做了一些定制对吧,其实也没改什么father map跟size map表不会通,你还是可以默认我只使用两个方法,第一个方法叫以same set,第二个方法叫unit。

好吧,你还是可以这么认为我是具体的node类型,所以我也就不再做什么外面包一层的这个事儿了,直接note它网上找的father map是no的。

这个那note它这个只有代表节点在这个size map中是有记录的,他的size是多大,这个这里面,所以我就给改了啊,一个是这两个表就够了,足足以实现并查集了,该初始化怎么初始化。

给我所有的note一进来,我先全部初始化好,跟昨天讲的一样,find的father怎么翻的,发的,怎么让链变扁平化,跟昨天讲的一样,使用same set跟unit方法,跟昨天讲的一样好,那怎么做。

啊给我实现一个并查集,先把所有的点各自是自己的集合好吧,然后边排序,根据全职小的边排在左边,全职大边排在右边,这个攻击队列干啥用的,这不就是堆吗,这个就依次把所有的边加入到这个小。

跟这加入到这个对排序策略是我自己指定的,在你们这堆是个小根堆,为什么这个小根堆呢,因为我指定的是权重小的边在堆顶对吧,通过这个比较器就可以实现吗,接下来一次弹出一条边,唉我每一次弹出一条边啊。

左边的左右两侧不是,和我要这条边联合from和to,你听懂,现在同样打一,这个我发一下我的github吧,因为很多同学发会违规啊,我发吧嗯,权限的边配合入驻山也行啊,最小生成树算法蛮多的啊。

这个k算法跟p算法只是常用的常用的两个啊,当然你可以有其他的想法和算法啊,这个时间有限就不再展开了,生成最小生成树算法真的很多,k算了其中两个而已,好我们看p算法,啊啊这个首先我说一点的是啊。

一般来讲呢,哎你看一下你这个有相图,这个肯定是对的,那么无相图的对不对,其实如果这个代码去跑无相图,他对不对啊。

它会少一侧,啥意思呢,就是,他如果你只是统计全职的话,他不会有错,一我们我们想象一下这张图,在如果真的实际上去跑这个代码的话,它是诶b有一条,b指向a有一条,而且全职都是一没错,输入是无向图的话。

他怎么给你这个无相图,他只能是a既给你a到b也给你b到a,他只能这么,你这只能这么表达无相图,对不对,我a指向c有一条二,c指向a也有一条二,然后一意味着我c指向d有一条二,有假设有一条七。

c指向d也有一条七,这就意味着我b指向d有一条四,我d指向b也有一条四,根据我们的算法,我们比如说你先把这个a到b的这条边加入到了你的这个集合中,下一回直接就会考察b到a的这条边,这个是我不添加的。

为什么不添加,因为a跟b已经合成一个集合了,当我在面对这条边的时候,from和to已经是一个集合了,所以这边我是没要的,就是如果想生成无向图的整个编辑无相编辑的话,这边之后啊,你其实可以知道他少一侧。

听着他打一,你我如果他给你的图就是无向图,他最后得到的编辑它会少一次,理解这意思吧,啊如果他只是求权重,整体权重是多大,这个值是不会有问题的,如果但是它就是无有相图,你这个也不也不会有问题。

只有说你我我我就要求你既给我a到b的边,也给我b到a的边,这表示一条边的话,那你可以通如果你生成的有向图的形式给它还原,再还原一个a到b跟它全职是一样的东西,给补补,把那个半次给补上。

这取决于用户到底需要什么样的返回,理解这意思吧,用户如果说你就给我一次a到b的,我知道他背后还隐含着一个b到a,如果用户隐含的是这个含义的话,你就不用补,如果他就是很龟毛,你给他返回a到b全职是一。

他还要求你给我返回一个b到a全职是一,实际上这个图上就是一条边,全只是一,但他如果两个都要的话,你就再给它生成另外一侧,听懂同学打一,那么我们看一下这个p算法,这个。

理解起来我觉得我个人觉得它比其实比这个k算法要容易。

你可能不这么觉得是吧,这个他是怎么样一个过程呢,是这样的嗯,我们我们写个例子嗯,就为了简便,我们还是写无向图,反正没是吧,那就是特殊的有向图,这个a相关的是1718了啊,这个是一这个是15吧,这个是二。

13,这12就是四,这边呢小1。3,怎么生成它的最小生成树,所有的边我都标了吧,这个p算法呀,它的策略是这样的,你给我指定一个出发点,哪个都行,你指定哪一个出发点都行,比如说你从a出发。

你也可以先一开始就从c出发,你也可以一开始从d触发,无所谓无所谓,好假设一开始从a出发,看到它有一个概念叫被解锁的点和被解锁的边,如果如果这个在边上的数字,我把号标好,a b c d e f。

边都有数字了对吧,那我们现在不确定一下,如果一个边的数字什么也没写,那个边还在被解锁着,数字它底下画了个下划线,表边现在被我解锁出来了,在左边画了一个对号,表示我要了这条边。

如果数在左边右边画了右右边画了个叉号,表示我不要这条边,四种状态是吧,你是所有的边都没有画任何东西,那你就认为所有的边都被都在被锁着,直到我一条边底下画了下划线,它就被解锁了。

所以你一开始指定一个出发点,我们来写一下啊,这个这个这这这个集合叫点,这个就叫被解锁的典籍,哪点解锁了,边解锁不解锁,就是根据我上面画没画东西来决定是吧,所以呢我一开始先把a给解锁出来。

注意a解锁出来啥意思,a的直接编,解锁,a这个点被解锁出来了,就意味着它相邻的八倍解锁出来,它相邻的一一倍解锁出来,它相邻的15倍解锁出来,简化了下划线,表示我可以考虑它了,它被解锁了。

如果上面什么都没写,表示还不能被我考虑到,我根本看不见好,然后我们接下来的就是说所有可以被看到的边礼,小编,这个边他的有没有新节点,有c,如果出现了这个新节点,我就把c给解锁出来,把一画个对号。

可以考虑的边左右两侧没有新节点画叉号啊,就是被解锁的边两侧有新节点画对号,要它被解锁的边两边没有新节点画叉号,所以要这个一并且把c解锁出来了,那么c解锁出来之后就意味着什么呢,c相邻的所有边。

选择的边不要重复解锁,所以已经被我选过了,我就不重复考虑它了,所有画的下划线的便利,再选一个最小的就选了这个二,测是否都是新点呢,有一个新点b k b就被我解锁出来,解锁出来之后。

就意味着b相邻的边再去解锁,就是先开始有个点,他去解锁一批鞭,从编钟挑一个最小的,再去解锁新的点,这个点再去解锁它相邻的边,再从中挑包括最小的再去解锁点,周而复始,这么玩下去,一直到把所有的点都解锁。

这个过程好,你现在b出来之后,哪个边被心解锁了十,所以你画个下划线,我再在所有画下划线的边里再挑个最小的,它的左右两侧是否是新出现有新出现的点呢,有e所以要他这个e就加进去了。

那么出现有没有把新的编解锁呢,有把四就解锁出来了对吧,我继续在所有画的下划线,又但是没有打对号,也没有打叉号的编译,再小个再选个最小的,就把这个四选到了,那这个四左右两侧是否都是新点呢,有一个f好。

f就被我解锁出来,出来之后又有哪个边被我解锁了,那三就被我解锁出来了,那我在下在所有画下划线里的边中挑一个最小的,看它的两侧的点,都是新的点d是新的好d就被我解锁出来d你能不能解锁新的边呢,没有了好。

我们继续在剩下的边,哪个是最小的,但左右两侧的边,两侧的点都已经被我解锁出来了,所以这边不要,再看这个八ab已经都解锁出来了,所以这边我不要,再看10b跟e已经都解锁出来了,所以这边我不要。

12c跟f一能解锁出来,说这条边我不要,15a跟d已经都被我解锁出来了,所以这条边我不要传承数,听懂再打一,是吧,哦对这不行,先先讲,先讲一个概念,就是我在这个过程中,我需不需要并查集,不需要,为什么。

k算法需要并查集,这个不需要了,因为你是一个点解锁一批边,在这一批边里面把一个点拽到集合里去,你发现每次都是一个一个一个的点进到集合里去的,你根本不存在两大票集合要合的问题,所以你怎么表解锁的点。

一个正常的set就够了,听懂他在打一,我们为什么这个就不需要并查集呢,啊边还是用堆,没错啊,边还是用堆来组织从小到大,但是点单集合其实并不需要用并查集,因为我们总是一个一个点的进到里面去嘛。

他没有你通信这个问题是吧,我总是一个一个点拽在在拽啊啊,解锁啊,什么c e怎么解锁呀,轮到刚才轮到c的时候,他当他他刚开始相邻的所有边都被我解锁了,c的时候,c相邻的所有边当时都被你解锁了。

所以这个c一被你解锁了吗,然后你到你跳到他的时候,你就选到它了吗,对不对啊。

好,小编组织这个小分队啊,这还是按照小小权重较小的边来组织,然后呢,和set对吧,对吧,只要一个就够了,这是哪些哪些点被解锁出来了,最后要了哪些边,请你放到你去对吧,你最后要了哪些边,生成了最小生成树。

请你放到s里去,它也是一样的,如果你是有向图,你就想让你要两侧都有,你就最后得到之后,你再在里面每一条边再拷贝出另外一半来就行了,跟我们刚才说的这方法一样,如果你只要整个边的权重要返回一个整形的话。

那就不扯这个蛋了,你直接把所有的边的权重加给他就行了,是这意思吧,啊就看你实际的需要,那我们看一下这个东西怎么做大,要管这个为什么写一个for循环啊,你不用管,我这样把这个布瑞克加上什么意思呢。

就是说我们说了,我们生成最小生成树的时候,从哪个点开始都行,到一个点都可以,所以你就可以在无相图。

挑一个点出来,只做这么一遍,就break就行了,理解这个意思吧,布克加上。

也就是说你先不认为这个for循环有什么实际意义,你先不认这个for循环有什么实际意义,我关键就是做这么一坨东西对吧,这东西给他玩明白就够了,就是所有对小生成树就生成好了,那怎么玩呢,来看哈。

出出发点肯定是不在set中的,先把它放进来,出发点肯定是不在set中的,先把它放进来,它所有的边进到眼组织的小根堆里去,唉这一句请注意,被放入的边,轻轻放了有可能,但是他不影响结果,为什么。

我们举个例子啊,出发你有一个这条边,一这条边三二这条边被你放了,这条边被你放了,这条边被你放了,那么下这个c出来的时候,它可能有临近的某些边,这个三会被重复放,但是不要为什么不要紧。

因为你你你即便重复放了啊,你从a出发这个三的时候,a跟c已经解锁了,你如果c又把这个三重复放,那么再次遍历到它的时候,a跟c都是在,所以这个边即便重复放,也会自己跳过,要防止歧义,我们加个结构。

放入的边别重复,所以我们加个结构是为了让你回头回回头会把这个代码更新就发给你,好不好,在在那个b的号上,所以我们这里面加结构,加个什么结构呢,加个边的结构啊,虽然他这个最后是不会影响结果的。

首先要说不会影响结果,但是为了防止歧义,而且为了性能上的考虑,我们给他不要把重复的一条边不停地放到考虑的边里啊,所以就是那怎么就是有一个边的集合,我们把上面叫做,先给他改个先。

先来个名字叫sat 2是吧,叫node set,然后把下面这个结构叫这个编的set是吧,age s,他是他是这个,那就是已经已经已经考,已经考虑过的,或者说已经进入过啊,已经考虑过的边不要重复考虑。

表要表示要要保持它是吧,诶啊什么事说,那么怎么表示这张表呢,怎么用呢,就是这样的,边它临近有哪,每一个点是吧,第一个点进来之后,加入到这个note set里,这个点所有边没进过的才进去,是这意思吧。

啊所以就这么写,如果,set,不含有此时的这条边,此时的这条边,那么,也加入他啊,set本身也加入了它,同步更新,是这意思吧,但是你不加的话,不会影响你的功能,但是会让效率变慢,确实是这样的啊,好。

每一个边呢他之前这条边啊没有加入过小分队里面,我再把它加进去,那接下来是就轮到了,我从小跟边的小跟堆里面挑一个最小的边出来对吧,挑一个最小的边出来,我那么肯定是在编点的集合理的呀。

因为我就是从这个点的集合里拿,当前上了这个节点,直接加入点的集合,然后从那我只用检查它to是不是在点的集合里就行了对吧,from你是不用查的对吧,from肯定在点的集合理,所以我就查to。

如果这条边to方向上,如果我发现这条边的to方向上的点,的集合理好,那就说明我要要这条边,否则我就不要这条边,对不对,如方向上的点呢不在这个点的集合里,那么这个图这个点呢就进入我点的集合,这条边啊。

我也要加入到结果中去,兔这个点的to这又解锁出一批边再跑,重复跑这个while了,是这意思吧,所以一上来其实说发的原出发点,先第一轮把它所有的边进来,没以后,每一次都是弹出一条最小的边解锁一个点。

这再由这个点解锁所有的边,再弹出一条边解锁一个点,再把所有的这个to点的所有边放入小分队,重复这个过程,所以这个过程跟刚才是一样的,也要加这个判断诶,进过小分队那边,我才给你加。

你的你的next age没加过,我才把你next的位置给你加到小去对吧,我相当于我这个result就生成好了,再重重新来看梳理一下,你先别管外面那个放循环,假设我这个代码就跑这一段。

所以一上来就这个node,先把这个note是什么呢,原出发点对吧,原出发点出发点加进来,第一批的编解锁进小分队以后,每一次弹出一个最小的边,检查边的左右两侧是不是新的,如果是新的就保留,如果不是新的。

就跳过,真的就把这个to no的解锁出来,这个边我就要那么to又有它所相伴随的边加入到这个小根堆里,周而复始的这么玩儿啊,但打一,说一下这个整个这个for循环是干啥用的,干啥用的,其实没什么必要。

关键有一点就是防森林,我什么叫防森林,他就是就是这个图啊,这个区域我的天,一张图里面我有好多点,我有所有的编,但它本身它是一片森林对吧,你如果有多个连通图的话,那我你看我我我如果做一个for循环。

我放到这个点子的时候,我会把这一大片所形成的最小生成树返回,然后我再放,然后我做完这件事之后,我for循环的时候,我再遇到这个点我就会跳过了,因为你已经大陆了对吧,再说到这个点我也跳。

我在放的这个点我也跳过了,再放到这个点,我也跳过了,整个这个连通区域是由他出发都搞定了的,但是我放到这个点的时候好,你再给我去搞这片连通区域,所以这但是干嘛用的防森林用的如。

但是本来讲你们的题目中并不会出现一个无向图的森林。

所以这个for循环啊,你可用可不用,你把它删了也行,你把它保留也行,听我同学打一,这个图它就是不连通的,那我得针针对于每个连通区域都做最小生成树嘛,对不对,所以也行,你保留也行,好吧嗯,还剩一个。

我们下午继续吧是吧,这有点有点讲不完了,因为迪迦特斯拉有改进啊,啊我改进啊,我们下午继续,好吧好啊,其他的算法呢啊这个基础班是没有涉及的,剩下有可能会在别的班里面再提一些图算法,比如说网络流啊。

包括那个同学提的f算法呀,这种啊啊嗯最小生成树其实用的场景蛮多的吧,就是你这一张网格,你想求最经济的情况吗,是我们把基础班讲完之后,下周直接开始,不是下周,下周可能讲不完,下周我们把收掉。

然后休息直接就干啊,嗯,分满分十分啊,你你如果不满意的话,真的要告诉我,说老师讲的哪块不好是吧,我和我会我会配合学学员给我的意见反馈去改进的,好吧啊,这个是绝对必要的啊,群里面那个维维老师吗。

你找他反馈,他会告诉我的好吧,我们下午继续好。

系列 2:P7:马士兵老师JVM调优:7.压力测试方法论 - Java视频学堂 - BV1Hy4y1t7Bo

要回滚没错,回滚到回滚到上呃,上一个运行环境去啊,替换等等,但是所有人要是有人要是说说我自己写个代码,马上把原来那个代码给他替换掉的,凡是这样的,全是中小公司小p项目,唉我告诉你。

大公司的这个事儿是不允许干的,你已经上线了,你还能随便的把服务器停掉,然后在部署上好多好多的部门协调好的这些个程序上去,你在开玩笑呢,你知道大型公司一次性的部署要花多长时间。

预备要预备一星期往上部署要花一两天,所以阿里我提供了这个功能,这个功能叫做ref,唉,又死了,不会吧,还没死,这个功能叫什么,叫redefine,redefine refine什么意思啊。

refine的意思相当简单,就是你直接在内存里头把那个源码给改过来,然后编译好就放回内存,不惊动线下的代码,演示一下好不好,内存里直接改代码对,当然这个是应急性的操作。

不是说所有的正规的操作都是这么干的,这是应急性的,应急我明天马上就要双11了,今天发现了一个代码,有一行写错了,本来应该是个二,要写成三的,给我给写错了,我的我的折扣要打0。99折,哎,里边写了一个0。

01折,完蛋了,我要是现在下线不行不行,不方便,那我现在我我怎么办啊,应急用的记住了吗,所以不要太过于去苛求它,这是应急用的,我给你演示一下啊,大家看这个小程序,我这里有一个小程序叫t t。java。

这小程序特别简单,我觉得我就不用我解释了,有一个m方法打印一个二出来,就这么简单没了,然后我还有一个小程序叫t。java,自己看,我在这个t。java里头一个main方法。

这个made in方法里头不断循环循环的时候在干嘛呢,cd dinner read,我读一个字符进来的时候,我就new一个tt调用一下他m方法,小程序太简单了,就想起来这个t,回头但是我回下车。

他就输出一个二,我回家之后再输出一个二,回下车后再输出一个二,好,这小程序到现在能理解吧,来get到同学给老师扣一小程序,很简单,就是我们扔了一个二上去,现在呢我现在上了线之后,我发现这个二写错了。

我要重新编译,再往上传,我的整个项目组是不允许你这么重新发布的,不可以,那怎么办,我想在线的直接就把它改成,把这个二改成一,可以不可以呢,可以怎么干,这么干,看这里,a i t d点加了。

首先你把这t点加了,这个二先改成一,全程一分分退出,叫ca tt完成号,编译好了,大家注意啊,这个时候是什么情况呢,你们要理解,现在有一个程序已经上线了,这个程序叫tt,这个tt里面输出的是一个二。

后来我发现这个二有问题,我现在在线下,我改了一份新的代码,这个叫tt。class,在这个t t class里面,我把它改成一了,现在我直接要把它替换掉,在不停整个服务器的情况下,直接把它给替换掉。

听清楚这个流程了吧,来听清楚同学给老师扣一,这里面其实呢如果稍微往深里讲一些的话,大家知道任何一个类呢在jvm里面都是被class loader给漏进去的,class loader如果你听过老师课。

老师是讲过class loader,怎么样自己重新定义自己的class loader,它里面有一个方法叫什么呢,叫define,这个define的方法呢,其实你自己去读一下。

就是把一个一段字节数组给它翻译成一个类,给它定义成一个类,一个对象啊,一个类,所以我们现在要干这么一件事,就调用在os里面调这个命令,启动一我在os里面调这个命令,调什么命令呢,叫re define。

重新定义,重新定义水,重新定义每个class,root。tt的class,我把这个新的class扔到内存里替换掉,原来那老的回车好看,这里redefine success已经成了。

我回到原来这个界面去敲回车,看见了吗,这程序我可没停,直接变一了,好这是阿特的干的事儿,还是挺牛的,这是临时的补bug用的,那以前有同学抬杠说。

老师这个里边你你你要是错了十处十个文件的100个文件全错了吗,大哥您100个文件全错了,那你还不重新发布啊,你还在线还真在线改啊,那有同学说老师我改完这个代码之后,那老的版本还是还是有问题的,那怎么办。

你下一个版本如果把它修修复bug呀,大集群怎么办,大集群你就不能同时替换呀,写一个脚本直接就同时替换了,没有问题的啊,不要认为大金军干不了啊,炸包咋整,这跟炸包有跟妈性关系吗,你直接替换掉一个类啊。

类似于热不属热部署,你是要把那个项目停掉,再部署上去,再启动那个项目的,这个是直接类级别的热部署,可以这么来理解,当然这里面呢它有一些个限制,就是有什么限制呢,你不能够修改属性,你说这个类里面有个属性。

这属性原来叫m,你给他给他删了,还这不行,你给他加一个,这也不行,现在这个这个版本不行,据说阿斯下个版本要把这事儿给加上,你给你添加了属性,可以没关系,凡是涉及到的我都给他改完,你把这属性删了。

其他代码牵扯到的我都给你改的机会,据说要这么干,但是我还没见着,还有一个不能干,你不能改方法名,你说原来这这方法叫m,你非得改成叫美眉不行不可以,为什么,因为有别的类也用到了这方法了。

人家直接调的就是m,不过据说下个版本也可以,唉这事儿得等他下一个版本行行不行了好吧,这个类正在被调用,会出现什么现象,原来从二变成一了呀,你跟正跟那打折,刷了个0。9000。01折,你正真的美呢。

一下单的时候倍儿变成0。99了,这酸爽,ok,关于阿瑟斯,我就就讲到这里了,好不好,我们就聊到这里,呃更详细的一些其他的功能的话,大家自己去翻吧,我觉得一个工具的话,那我教给你最主要的就可以了。

而且工具这个东西没什么可教的,自学都能搞得定的东西,对不对,我主要教教你他的思想在哪里啊,他能干一些什么样的事情,那么到现在为止,我觉得你的简历上应该是可以写这件事了,不知道你们敢不敢是哪件事呢。

就是。

诶跑哪去了,这件事不知道大家敢不敢写,给大家演示了,反正就是我在项目之中有过调优的实际经验,定位jvm的这种o m的溢出,这种经验,这是调优实战经验,可以写了吗,敢敢不敢写,好同学们,听我说。

作为一份简历来说,有的人水平是100,他敢写80啊,太牛了,任何人去面试的,你放心,因为他水平100,问你80,他就写80,大多数人问他就是80的问题,顶多问你90 100的问题好,这个时候我靠。

太牛了,他居然肯定能肯定能拿下这份岗位,这份岗位月薪25000,但是很不幸的是,这哥们儿本来值3万,知道吧,结果他拿了2万吧,他自己还很美好,有一哥们儿比较横,水平就2万的水平,60写80 十个减十个。

十次面试挂了八次,这个呢是十次面试成了八次诶,这个是十次面试挂了八次好,最后成了两次,这两次拿到25000来,同学们告诉我一下,你说谁亏了,唉醍醐灌顶对吧,你为什么有的人报名了两天。

他就涨了2000块钱,为什么有的人经过我们批完面,批完他的简历啊,他就直接涨2000块钱,你现在是不是有那么点感觉了。

好我看刚才有同学说了,说老师不是有十个案例吗,对是有事干,你自己去体会好不好,就别让我在这儿从头到尾的讲给你听了,嗯啊例会总一堆啊,我给你讲个比较好玩的吧。

面试官不给面试官不给面试官看,我跟你讲比较好玩儿了,好不好,来看这里,讲一个比较好玩的诶,这好玩的是什么呢。

这是实际当中确实发生过的,而且这家公司叫小米,这家公司有一批成员,2c加加的,然后由于他们的项目转了java,所以他们呢从c过来写java,他们写完java之后产生了频繁的gc,产生了内存的溢出。

听懂了吗,那为什么,原因是什么,好你们仔细仔细思考一下,他干了这么一件事儿,他重写了类的finalize,final finalize方法,大家知道那里面有一个方法叫finalize,finalize。

有印象吗,大家知道java程序员都知道那个类那个方法是不建议你重写它的,对不对,唉结果呢ci成员就把它重写了,第一个我问你第一个问题,第一个问题,why,为什么c加加乘以r会重写finalize。

为什么y,原因是什么对,因为c加加是乘以,他们写惯了手动释放内存,手动释放内存,你要delete掉,要在你的类里面写析构函数,就是那个函数啊,小小小波浪线加一个名字。

而他们认为java里面应该有一个函数,也是虚构函数,看到了finalize,欣喜若狂,我靠终于有西构函数了,光机给它写进去,既然是虚构,我肯定要释放资源,在里面释放各种各样的文件,打开的内容啊。

什么各种各样的锁呀,各种各样的数据库的连接呀,好全全放到这里头去,接下来你们自己想想它本来这个finalize呢一个垃圾回收器,回收这个垃圾的时候,他要执行这方法的,这方法执行的时候本来不费什么时间。

结果它里边放了一大堆费时间的东西,本来的一个对象我要回收的时候一个毫秒,结果他放了这么一堆东西之后呢,十秒钟才能回收一对象,但有点夸张,一秒钟,然后你内存肯定会越来越多,你分配对象速度又比较快。

内存很快就占满了,这是它产生溢出的原因,好不知道大家听清楚没有,这是实践当中有人犯过这种错误的,当然你如果还不知道,你如果还不知道面试官怎么说,你就写一最土的,你说我我有一个同事。

你千万别说你自己他写了一个类似的,然后他就不断的往里装装内容,他不释放,哎这个可以吧,当然谁写这么土的代码啊,哈哈哈哈,当然我就不说了啊,十个案例你自己挑,自己去挑,都是相对土一些的案例啊。

还有十个案例是给vip准备的,我就不说了,o,那么到现在为止呢,没人问你们不called rereview吗,called the review,另外一个同事,他比较睡得昏昏沉沉的啊,眼眼迷迷瞪瞪的。

code review,没有review过,有什么关系吗,好,呃其实到现在为止呢,实战部分内容呢就大体的非常粗的一个流程,我就我就给大家讲完了,呃我们简单的稍微的回顾一下啊,这份文档的内容比较多。

我只挑了其中的比较粗的流程来讲给大家听的,但是至少我觉得你到现在为止应该是有这样的一个收获,第一你弄明白了,原来垃圾会说其实有很多种,第二你调优的时候一定是针对某种垃圾回收器回收调优的。

第三oom的问题,你至少应该知道用什么样的工具去定位它,面试官问到你的时候,你用什么样的说法去说服面试官,好有这方面收获的同学给老师扣一,这个文档会发吗,会的没有问题啊,那我下面讲一点比较难的。

就不讲女的了好吧,我讲一点比较难的,这个比较难的问题呢,呃目前面试官问的还不多,但是今天有面试官在场,所以他们可能就会问了,那这个比较难的问题是什么呢,这个比较难的问题是我昨天讲ccm的时候。

有同学已经特别感兴趣了,问了我好几遍了,追问了好几遍,说老师这个c m c m s里面不说cms里面,不是说我的工作线程和我的垃圾回收线程是同时进行的,对不对啊。

三色标记我的工作线程和垃圾回收线程是同时进行的,那么我垃圾回收线程在回收这个对象的时候,很可能被工作线程又又把这个对象变成不是垃圾了,那这种情况怎么进行处理,目前也只有美团问到过这个问题。

其他的大厂还没有问到过,包括阿里也没有问到过,好如果说到这一点的话,你能够说的偷偷车车详详细细的,那么肯定会呃得高分啊,非常高的分啊,当然对不起啊,应该是也问到过,因为他这个问题呢问的不是特别直接。

就是关于这类的问题,我给你看一眼啊,就刚才这些问题其实是包括了它了。

呃其实这一类的问题,这类的问题呢都是比较难的,讲一个最熟悉的垃圾回收算法,那么你如果你讲三色标记,我去这就牛了啊,你要讲一个对熟悉的,讲一个什么拷贝,那个太简单了。

还有一个其实还有一个我记得有一个问题是问的什么呢,就是呃你能不能把cms和g一的这个垃圾回收算法,你你给我,你给我说一下,忘了是哪个公司问的了,就是凡是问到这类问题的都是超难的。

还有一个就是这一类比较葛的问题,某个有病的企业,某个有病的面试官都说用一句话证明你这个水平很牛,我就教他嘛,我说十种垃圾回收器所有算法都明白,我靠太牛了,十种垃圾回收器所有算法全明白。

好吧算你狠好,估计除了老师之外,没有人敢这么说,哈哈哈哈哈好,下面我们讲可以加高分的这样的一个算法,好大家看这里,嗯就是强软弱虚指针打开错了。

哎呀为了给大家讲清楚,这个专门给大家画了一个动画,动画画起来很难演示,三分钟就演示完了,好首先请大家记住这个名字,这个算法的名称叫做三色标记,好看这里三色标记,三色标记是什么概念,这是我们首先定义啊。

这个三色标记呢就是当垃圾回收器去标记那些个对象的时候,他得把那个对象给标出来,哪个是垃圾,哪个不是垃圾啊,这个垃圾这个飞垃圾,这个垃圾这个飞垃圾好,他得干这件事,得识别出来,那么它到底怎么实现的呢。

在尤其是这种并发级别实现,如果是那种不是并发的,说你所有的工作线程你都给我停了啊,一边给我待着去,那就随便标了对吧,每个对象还怕他找就行了,找出来的全都不是垃圾,没找着的全都是垃圾,这就是最简单的。

但是实际当中现在的这个需求是什么,现在需求是你一边干活儿,我一边标识,那肯定会有标错的情况,这是肯定的,我们再来我们看它实际当中是怎么实现的,这种情况呢叫做三色标记,三色标记是什么概念。

首先第一点先认清楚这个概念,他会把对象在逻辑上分成三种颜色,三种颜色其实对象不是真正的那个颜色,对象全是零一了,他有一个标记位,比如说零一代表就是黑的啊,一零代表就是灰的,零零代表就是白的等等。

就是干这个使的,那三色标记是什么,一个什么概念,逻辑概念,它分成三种类型的对象,哪哪三种,黑色的,灰色的,白色的,黑白灰三种,黑白灰三种的概念是什么,就是我在找到这个对象了,我找这个对象。

但是呢我还没有识别它,它到底是不是垃圾,我还没有识别它,我们说还没有对这个对象做标记好,这种对象称之为白色对象,好我又找到了一个对象,这个对象呢我已经识别了这个对象了,它不是垃圾,确认它已经不是垃圾了。

而且呢我确认它不是垃圾之后呢,我得顺着这个对象的成员变量去顺着往下找,但是我还没有进行这一步,我还没有找它的成员变量,到底它是不是垃圾,成员变量指向这些对象到底是不是垃圾,我还没有找到这步,好。

这个叫灰色的,如果我找到一个对象,这个对象我已经确认它不是垃圾,并且它的成员变量我也找完了,这两个变量我也就标出来了,这两个变量找出来了,标完了是灰色的还是白色的,全都标完了好,这种的叫做黑色。

黑色对象叫黑白灰,黑的叫什么,自己标完了,儿子也标完了,这个叫做黑色,灰的叫什么,灰的叫自己,标完了指向的对象还没有标,这个叫灰色好,没有标到的对象叫白色,黑白灰来理解,同学给老师扣一,好这叫三色标记。

那么假如说我们在整个的整个我们程序,我们jy m的线程,也就是我们垃圾回收线程,在回收的过程是做标记的过程之中,我已经标成了a啊,确实是黑色的了,b是灰色的,他的b的孩子还没有标好,在这种情况之下。

突然之间我们整个应用程序,因为应用程序也是在不断地运行的,它用运行的过程之中呢,他把b指向d的这个引用给消失了,就转成一个人变成没了,假如发生这样一种情况,b指向d的引用消失,同学们,你们想一下。

注意啊,这个d还没有被标注呢,没有被标注了,同学们,你们这样想一下会不会产生问题,这种情况会不会产生问题,仔细想想,因为这里头相对难一些,全是算法,全是抽象的问题,会产生问题吗,其实是不会的。

哎为什么呢,为什么不会呢,因为这个东西呢叫做floating garbage,咱们的这个垃圾回收啊,它是一轮一轮的,还记得那个可中断垃圾回收吗,没处理吗,哎他是一轮一轮的一轮一轮进行。

我这一轮儿标到这儿之后,然后没有把你这个b给你找出来,因为刚才你还连着呢,但是呢下一轮来了之后,我就找不着你这个d了,你这个d就变成垃圾了,我就把你给清了,所以没有关系,这是一个浮动垃圾。

浮动垃圾的意思就是诶这轮没把它给干掉,下一轮再把它给干掉,让你多活一小会儿,所以这个没事,这种情况下是没有任何关系的,好刚才这小段听明白的,给老师扣一,就是说他可以他早晚被清掉。

只是早一会晚一会儿的问题,有一种问题是什么问题呢,看这种这种就比较麻烦了,这种情况是这样的,你仔细看,假如在垃圾回收的过程之中,标了a和b,a是黑,b是灰,还没有标到d在这个过程之中。

另外我们的工作线程干了一件事,他把b指向d的引用给弄没了,与此同时a有一个引用指向d了,再看一遍,这两个是都是必要的条件啊,b指向的d的也就没了,与此同时a指向d了,看到了吗,这时候会产生什么现象。

来仔细看一眼,同学们,你们想一下a的颜色是什么颜色,a的颜色是黑色,黑色代表什么,黑色代表已经标记完了,那下一轮垃圾回收器在进行的时候,下一轮来的时候,它还会标记这个a下面的成员变量吗,还会标记吗。

不会了,结果这哥们就被回收了,知道吧,因为那垃圾回收器已经认为没有任何引用指向性了,因为我不再会去找a下面的成员变量了,与此同时,所有指向你的其他的那些引用也都没了,再看一眼,这就是问题所在。

只有在这种情况下,它会产生问题,它就会产生漏标,漏标就会产生内存泄漏,b指向d的也就没了,同时增同时a指向d的引用增加了一个,b b没关系啊,b是灰色的,如果那就b没关系啊,b它是不是灰色的吗,灰色的。

我下一次来的时候还是要去找他的孩子们的,对不对,他的孩子没有必要呢,结果他现在孩子这个孩子已经没了,他可能有别的孩子,如果有的话,那就直接去找,如果没有的话,就把它变成黑色了,这哥们儿就成黑了。

黑的就可以直接回就可就是弄完了已经结束了,好了,好这个过程大家听明白了,对不对,注意还没完啊,因为这个这个里边算法特别深,我得一步一步确认,你们都明白了,就是说灰的纸箱白的也就没了,黑的增加了一个。

由于黑的已经不再被扫描他的孩子,所以这个地不会被扫描到了,再出问题了,ok我们继续可以继续同学给老师扣一,为何a添加了指向d,那a里面有个成员变量a点小a等于d,这不很正常吗。

你写这么一个代码不就完了吗,正好执行到这段代码了,这种问题还卡嗯,不对啊,喝口水,为什么指向d,因为业务逻辑变了,业务逻辑在运行,你自己写代码的时候,会不会写你自己写代码的时候,会不会写这种代码,a。

b等于new什么,或者等于某list里面get什么,会不会写,好看这里,我们现在要解决这个问题,要解决这个问题怎么办,解决这个问题有两种方案,认真听这两种方案,还有第一种方案。

第一种方案就是c m s的解决方案,semi方案就是叫他的名字叫什么呢,叫做incremental update,昨天我说三色标记是一种中性词,三色标记会产生问题,cms。

对于三次标题解决问题的方案叫做incremental update,好什么意思,看他是怎么解决的,他是这么来干的,b指向d的,没了,a指向d的诞生了,好这个时候干了一件什么事呢,他就把a标成灰色。

就干这么一件事儿,很简单,那么下一轮我们的垃圾回收器再来下一轮的时候,它会扫灰色的,因为灰色的还没他的孩子们还没扫完呢,所以他肯定会把灰色的都扫一遍,就这么简单搞定了,非常直观好。

这就是cms对于三色标记算法的一个改进方案啊,一个公正方案叫做incremental update,搞定了,那他是怎么让黑色变成灰色,我的妈呀,你想气死我是吗。

系列 2:P70:左神算法-暴力递归到动态规划1 - Java视频学堂 - BV1Hy4y1t7Bo

喂,大家好。

大家好,我再等两分钟,我们这个今天的课和明天的课是一在一起的啊,就是首先我们要我们要先看一些尝试是吧,这个常见的一些写的递归的过程,然后明天的今天今天可能会开始动态规划了,已经对吧,下午开始动态规划。

想动态规划的时候,其实国家描述清楚这个尝试到优化的这么一个过程,因为动态规划就是某一类尝试行为的进一步优化啊,动态规划就是场暴力,任何一个动态规划的问题,都是以某一个暴力尝试过程的优化后的样子啊。

是这样一种关系啊,所以,很强烈建议大家这个今天的课跟明天的课一定要多来啊,因为这个非常关键啊,这可能是这可能是这么多年来给我讲课总结的最成体系的一块儿了啊。

之前我们讲过的一部一大套东西叫二叉树的递归套路是吧,这个可以说后面这个今天这两节课的内容,比那个之前讲过那个总结那个套路还要全一些啊,嗯,其实其实动态规划的本质是某一类的暴力递归啊。

这种这种某一类的暴力递归设计的时候,它是有原理的,而且也是可以可以给你很多提示,然后让你想出来的啊,呃因为面试中的动态规划它不可能难到一定的份上,所以正是因为利用这种,你可以就哪怕你刚写一个暴力递归。

你就知道靠谱不靠谱,他能不能改出来规划了啊,别的老师可能不会教你,这个是我教你点实际的,就是马上能猜出来这个方法靠谱不靠谱,就是你只要把暴力递归的参数表写出来,你都不用写,具体的你都知道。

靠谱不都跟更靠谱,更不靠不靠谱了啊,然后啊才报名之前上网课都没有听过,听得懂吗,那你要看你的基础是吧,我们之前的课讲了好多内容了啊,然后还有就是我们要更正一件事啊。

就是这个是我才注意到的,这么多年讲课也没有,其实我我也我也没有实现过这种是吧,就是之前的课讲了一个小的内容,叫二叉树的序列化和反序列化,其中我说这个我在课堂上重点讲了。

先叙的方式序列化和暗层便利的方式序列化是吧,而且还写了对数器啊,能保证它正确,但是我就提了一句,我说这个中序方式跟后续方式序列化也是同理的啊,但具体我就没写了,然后有群里有个同学问我。

中序方式怎么序列化和后续方式怎么序列化,然后后续的方式可以实现,因为后续方式先说一下,后续你这个先叙方式是中左右对吧,这种方式你会序列化对吧,他就是其实这个其实是先序的方式来序列化吗。

然后你后续是什么呢,左右中是不是啊,是左右中的顺序对吧,后续是左右中的顺序,那你那你那你如果把这个后续遍历的序列,你反过来看,他不就是中右左的顺序吗对吧,你说你你说你先去左中左右,你知道怎么反序列化。

现在给你个序列只是这样一种顺序,是中右左,你你会不会把它序列化出来啊,这没什么问题对吧,我们来看一下code啊。

比如说嗯,这是我们先叙方式序列化对吧,你得到一个假设,你得到一个队列是吧,这个队列的顺序就是先序方式所得到的一个序列,序列化的时候先建先建节点再见左数再见右数,依次是递归矩是吧,一次去递归去,没错吧。

这就属于我们先叙方式序列化的形式,上上节课啊,在当时那节课的时候给他讲过了是吧,我们再看后续方式的序列化,如果你得到这个是一个后续遍历的序列,你先干嘛,你先把所有的你先把这个队列中所有的元素啊。

你给它加到站里去对吧,那这个站的顺序它就是逆序了吗,对吧,你原来的顺序是左右中,对不对,然后你你你加到站里去之后,那么在站中的顺序就是什么呢,就是中右左,对不对,中右左了。

上面上面这个先叙的方式是中左右的序列化,你现在得到一个中右左的序列,你会不会把它给也给序列化了,反反序列化了是吧,那不就是先建头节点,再先再见右数,再见左数就出来了吗啊。

所以后续方式的序列化它没有特别的跳跃是吧,也也不会很难写,然后唯独要注意的是中序方式序列化,中训方式是可以序列化的,但中训方式反序列化,反序列化不出来的。

也就是说你想成套的把一个数序列化得到的结果再给它反序列化回去,中序遍历是做不到的,为什么呢,你比如说这两棵树,这个是二维头节点,以为左孩子这么一棵树,这个跟一为头节点,二位又还是这么一棵树。

是两棵树是不同的数,对不对,但是如果你根据我们序列化的说法,你补足空位置之后,它的中序遍历的结果其实是一样的,你看中区别,那结果是先来到一的左孩子位置空,然后把返回一,然后一的右孩子又是空对吧。

所以前三个是空一空往上二,接下来空了空一空二空,没错吧,这棵树序列中序序列化结果是空一空二空,下面这个数据的话,结果也是空一空二空,你比如说一的左孩子它是空的位置,空一该遍历右数二。

但是先打印二的左孩子空,回到二再打一二的右孩子空,所以这两棵树它中序编译的结果都是这个序列,那也就是说我中序变量既然不同的数能够得到同一个中序编译的序列,他就说明中序遍历,你得到这个序列。

即便你补足了空位置,他是有歧义的,就这一个反例就可以说明你反序列化是反序列不回去的,除非你这个中序辩证的结果中,你再加入一些新的信息,比如说你再用一些特殊字符,或者是用一个特殊的位置来表示左数怎么样。

右数怎么样的一种划分才能够做到,但是我们约定好的这种,如果一个没有节点的位置,就拿空来站住,如果是有节点的位置,拿值依次往下走的这样一个链,就是类似于链表顺序或数组顺序的形式。

其实是做不到序列化和反序列化的,因为它有奇迹好,这是我们做一个把我们的课程做一个就是呃也算是一个刊物吧,因为当时讲的时候,我就中旭跟中旭跟后续是一是一句话带过的啊。

现在告诉你说中序遍历是没有办法成套的序列化和反序列化的,好这个内容听懂他在打一,先去跟后续是不会有歧义的啊,因为他提前规定好了头节点,它是先规定头节点的方式,然后左数右数展开的。

而你中序遍历的时候是左数,窜完之后来到头节点,再去右数,严格来讲,你原始序列中,你你其实头节点不知道在什么位置是吧,啊,好啊,那我们就接着接着来讲这个代码我已经推了啊,这个群里面也发了pc的地址是吧。

那么接下来讲这个尝试,我们上节课讲了n层汉诺塔问题是吧,这个大家在当时的时候管我要非递归版本,我已经把代码推上去了啊,自己看一下吧,汉诺塔问题的非非递归版本是吧,递归版本都都都讲过了吗。

还讲了好长时间是吧,飞机归版本大家自己看一下吧,啊这我我我实在不行,你就把三层汉诺塔问题,自己在那个飞机柜代码里面写一下它的调用过程,把递归函数展开一下看一下对吧,这个代码已经推完了。

然后我们再看下一个就是打印,怎么样打印一个字符串的全部子序列,这是一种很经典的尝试,什么叫先说一下啊,这里面说一下这个字符串的子串和子序列是什么区别。

字符串的子串啊,它指的是必须连续的一段啊,举个例子,你比如说a b c d这个字符串,它的子串是必须连续的,那么我们怎么来枚举所有的子串,比如说从零位置开始了,哎,零位置开头的子串。

零位置开头的子串是吧,a a b a b c a b c d没错吧,然后一位是开头的,有哪些子串呢,bbc b c d2 位置开通哪些子串的c c d对吧,三位置开通哪些子串呢。

就一个d这是他所有的子串,我们是怎么枚举的,是根据任何一个位置开头的情况下去来枚举的对吧,你这样枚举是肯定肯定可以枚举全的是全部都有的,那么这个东西就叫子串,刷题的过程中。

总有同学问我老师子串跟子序列啥区别是吧,或者说你根本不理解子串跟子序列的定义的话,你这个这个题没法做是吧,这就是子串啊,所以我们怎么枚举子串,这个简单不需要递归方法,你写两个放循环是吧。

第一个放循环规定开头,然后依次加加是吧,第二个空循环就规定结尾吗,结结尾是从开头开始,然后依次加加,是这意思吧,两个空循环就可以描述去打一个所有的子串了,那么子序列是什么呢,子序列它不是这样的。

子序列比子串要自由,比如说a b c这个就是子序列,指的是我在原始序列中,我也要从左往右依次拿字符,但是可以不连续,不连续是不连续,但是要求你相对次序不能乱,啥意思呢,就是我不会有一个子串叫ba啊。

我不会有个子序列叫ba,为什么,因为b这个字符在a这个字符在这个序列中是左侧的,而我们原始串不是这个顺序,这个就不是,所以注意子序列它并不是全排列的意思,子序列严格来讲就是说我任何一个人。

任何一个位置的子串我都可以要或者不要,那我能够生成哪些子序列呢,那怎么生成呢,这种经典的方式就是每个位置的字符要跟不要所有的路都走一遍,啥意思唉,零位置的字符我到底是要还是不要两条路,对不对。

当我选择要,那就要了这个a那不要呢就没要这个a0 位置的字符,接下来继续展开,来到了一位置,一位置的b我也可以选择要和不要对吧,你要是走零位置的这个决策到一位置。

你也可以选择要这个b和不要这个b接下来每一层都展开二位置,二位置,二位置二位置是吧,来到二位置,二位置呢,我也可以选择要这个c,不要这个c,这个二位置也是要这个c,不要这个c,这也是这都一样。

为什么老连笔,我说烦是吧,稍等一下,我调整一下屏幕的倾斜角,老是连笔,可以选择不要这个c是吧,要这个c,那么我们来看一下,要这个a要这个b要这个c。

你得到子序列就是a b c要这个a要这个b没要这个c得到子序列,就是a b要这个a不要这个b要这个c得到子虚的,就是ac要这个a没要这个b也没要这个c,你就得到一个a,不要a要b要c就得到bc对吧。

没要a要b不要c就得到b所有东西都都能写出来,这个最后一个什么也没有空虚脸,那么这个就是我们所有子序列的生成方式是吧,我们把一个位置的字符彻底的要跟不要都展开,得到所有的序列。

就是子序列a b c那就是所有位置都要了,那这个a b呢就只要前两个对吧,a c呢就跳过了,这个b没要单独写下来a c但相对次序也没有乱,是这意思吧,最后呢只要这个呃。

只要这个a那就是a到了后面两个没要,这种方式其实可以把所有子序列都生成好的。

听懂同学打一,好那我来开一个扣的啊,来啊我们来看看这code,这个code是什么意思呢,其实,这就是我们刚才说的那个方法啊,我们来解释一下,就是我们看这种我们想实现这种机制。

最后能打赢他的所有的东西对吧,想想实现这么一种我们脑海中的尝试啊,这现在目前为止只存在我们脑海中是吧,或者只存在板书上,怎么把它变成实线呢。

我来看一下这个就是原始字符串,它是一个固定参数,string这是一个固定的固定的参数是吧,它就是它它它这个永远里面的字符是不会有变化的啊,不变,那么这个底下这个index呢就是现在来到的位置是吧。

index就是此时来到的位置,啊此时来到了位置,就是你现在当前这个位置的字符,你到底是要呢,还是不要呢对吧,就是来到了index位置,来到了spring中的index位置,这个当前字符要根不要玩过。

做决策对吧,这个东西是啥啊,这个东西就是这是一个string类型的一个列表是吧,闻过而且它的名字叫answer,那么这个answer是啥意思呢,就是当如果我是啥意思,就是如果。

如果index来到了string中的结束位置,就终止位置,终止位置啊,什么叫中指位置呢,就是最后一个字符的位置,再往右一个位置是吧,如果index来到中的终止位置。

我要把我沿途路径所形成的答案扔到answer里去。

你看这个也是看我们脑海中是吧,我们沿途路径是啥呢,我们要了这个a要了这个b,要了这个c,这是我们的沿途路径吧,要是这个a要了这个b没要这个c,这也是沿途路径吧。

所以我们就是说当我来到了一个不能在选择的位置的时候,请你把这个所有的结果,每一个结果都加到这个list里面去对吧,请你把沿途的每一个结果就是最后一层,每一个结果都加到这个例子里面去,这就是这个意思说。

那那我们就必然还需要一个参数,叫沿途路径是啥对吧。

最后一个参数就是沿途路径对吧,就是也就是说之前做的之前做出的,之前做出的选择就是pass,大家不要觉得写递归是一件很难的事,你可以一开始只设计一个string index这样一个参数对吧。

你为什么觉得他写不下去了,你就你就自己硬写这个代码,你发现诶怎么和我想的这个实现不了,那一定是缺东西,如果你感觉到缺东西了,你就在补参数嘛,一直补到你可以把这个东西尝试完吗。

所以不要觉得这个不要觉得这个这个所谓的暴力递归过程非常的难写,事实上你只是缺点动手能力,理解这个意思吧,你一开始可以设计非常糙的暴力递归,比如说你连可能参数都是缺的,那你随着你逐渐写下去。

你发现你怎么实现你脑海中那张长试图对吧,你怎么样实现你脑海中这种长视图,如果你发现你少参数,你缺什么就补什么参数,然后你看看你在递归里面用什么吗,怎么用它吗,理解这个意思吧,啊就是很多同学觉得难。

只是缺点动手能力,自己去写一写是吧,你缺什么就补什么,这种长逐渐的你就适应了好,那么这个递归的含义,我们现在没有讲它内部,但内部也很简单,我们来看一下,当我index来到了终止位置干嘛了。

我们要把沿途的路径所形成的答案放到answer里去对吧,这是不是这说的是这个意思,底下这一行是吧,如果我来到终止位置,我就把沿途的路径放到answer里去,然后return多么直白是吧。

那么我每一那如果我没有到终止位置呢,我就继续,我就继续,我怎么继续,你看第一条路径,这就是我的第一条路径,它调用了自己对吧,是去下一个位置做选择,诶,我之前得到什么pass。

我的no就完完全全是这个pass往下传了,说是啥意思,你并没有把你此时index位置的字符,index位置的字符往下传,那相当于就是你走了一条分支,就是沿途路径是不包含当前字符的路径往下传了。

下面一行就是诶我之前得到的pass对吧,我之前能做pass对吧,之前的那pass我加上了我index位置的字符,这个路径叫yes,然后我让index加一位置的东西往后做选择,所以这条路径是什么呢。

就是我没我要了当前位置的字符去展开,那这不就是不含字符的时候展开,这是含字符展开。

我每个位置我都这么干,这不就相当于我实现了我脑海中尝试的图图。

这整个图景吗,对吧好,那么这个递归方法看的同学打一,咳咳,我不知道新报班的同学能不能听懂啊,我感觉我讲的还是挺细的对吧,我不是说凭空给你个概念,我给你先画个尝试图,然后再教你怎么写,对不对啊。

那如果还有打二同学呢,把过往的课看一下,好吧好,那么那对啊,同学说的对,这也是一个深度优先便利对吧,为什么呢。

你看我是先走这条路,走到死,然后往上推再走这条路,走到死,然后再往上推再走这条路,走到死,再往上推再走这条路,所以他也是一个深度有限便利对吧啊,这也是一个深度优先遍历。

没错啊,好那么我们这个主函数怎么调是吧,主函数呢就是用户用户他不不想调这么多参数,他觉得烦是不是,所以我就给他写一个主函数,帮他做一下组织是吧,他给我一个字符串,怎么生成这个字符串的所有子序列。

先转成字符类型的数组啊,然后path等于空字符串啊,answer准备一个空链表啊,哎这些东西都帮他做好,然后给它放这四个参数进去是吧,从零位置开始,你给我做决策吧,每一步一步一步全给我展开是吧。

那么这样一个调完之后,那pass那个answer里面就是用户要的所有子序列了,我就给用户返回了。

是吧啊,这就是主函数好,那么我们来看一下这个你怎么样打印一个字符串的全部子序列,要求不出现重复字面值的子序列,什么意思,当我一个字符串中,如果所有的字符都不都不是一样的。

比如a b c,比如a b c,对吧,你说这个字符串它在它在它里面,这个所有字符都是不一样的,那么它天然会得到字面值都不同的子序列,但如果,这个字符串就是三个a呢,你用原来的递归方式啊。

你是回头你会得到一大堆一大堆相同的字面值的子序列,我说的是字面值理解吧,什么叫字面值呢,我给你举个例子,我要了零位置的a,要了一位置的a没要二位置的a得到子序列是啥,是不是a a。

他是不是和我没要零位置的,要了一位置,再要二位置得到字面值一样好。

所以呢我们下面一道题,就是说就这个这个这个进这个进阶,就是说不要出现重复字面值的子序列,你给我返回哎,这个看起来就是说他他这个我们先看一下,正常来讲你就是把一个是所有的子序列的历史的生成好。

然后你再去个虫吗。

是这意思吧对吧,好所以你看我来展示一下啊,这很好理解啊,就是什么意思呢,你看如果我我我我我我这个递归含义跟上面其实没有太大的区别,这个第二个递归啊,protest 2,这个递归说的是啥呢。

也是string是什么还是什么index位置做选择对吧,但是我收集的容器是赛跑哎,我不再是一个,我不再是像刚才那样的是一个list了,我这个直接收集容器的时候是个s对吧,我收集容器s。

他自然能够再把一个答案加进去的时候,帮我去重,为啥不是集合嘛哈希赛的本身就是保证不重复的,对不对,所以跟上面完全一样,只是你只是你在这个加入的时候,它是一个set,天然就给你去过重了。

那么主函数在调的时候,其实就是我先把这个set生成好,你如果想要list类型的答案,就是list的结构的答案的话,就是你把你所有的答案放在list里面,你别给我set是吧,那我就单独再把set遍历一遍。

给你生成好答案返回,就这么简单,告诉他打一,这里面有一个拓展啊,这个拓展先跟大家说一下,有兴趣同学可以想一下。

我如果想知道一个字符串中,所有不同字面值的子序列有多少个,所有字面值不同的子序列个数,就是我不要你把所有的不同的子序列都给我了,我不要你最终的那个子序列的样子。

我就问你string中有多少不同字面值的子序列个数,这个问题是一个动态规划啊,大家平时可以想一想,我们会在我们把这个基础班开完之后,开始直接开训练营,会给你讲这些题,好吧,这是一个经典问题。

就是spring中到底不同字面值的数量有多少,他其实可以用动态规划做,但是你现在还没给你讲,所以我们也就现在这里不展开了,把这这今天跟明天的课讲完之后,我们就可以开始做我们这个训练营的练习了,是吧好啊。

在这里先挖个坑吧,我放心,我说的坑一定会补的。

我们再来看,那么打印一个字符串的全部排列,之前讲过之前讲过是吧,之前的课这个东西是讲过的,那我们来点不一样的实现,因为之前讲的那个呢这个是在哪里讲的是吧,它它实现起来其实不够简洁啊,呃什么叫不够简洁。

就是你可以写出一个全部排列的东西,就是你每次克隆吗,我们之前的方式是每一次克隆一下对吧,但是为了但是有些同学新进来,他可能不知道我在说什么,那么也就开,那么也就从头开始讲这个题,因为实现方式是不一样的。

而且这种接下来实现的方式呢。

就其实哎我看一下,我准备准备内容实现了,啊准备的是这种实现啊,全排列的实现,它这种是比较简洁的样子啊,这种比较简洁的样子,我们来看一下啥意思。

先先想一下我们这个实际过程怎么样搞全排列,假设有一个数组零位置,字符是a,一位字符是b,二位字符是c,哎我们不想每一次都准备一个新的结构去执行这个全排列,所以我就想这么干怎么干呢,这样来弄啊。

这个数组原来是a b c,零位置一位置二位置对吧啊,然后,我这么尝试,零位置的a还在零位置,这个叫一位置的b来到零位置,下面叫二位置的c来到零位置三种方式,如果你走的是这个分支。

那么零位置的a还在零位置,它就会继续往下传的是a b c这个数组继续往下是a b c,如果你说一位置的b要来到零位置,那你往下的数组就是b a c,为什么,因为一位置的b和零位置的a交换了。

如果你二就是二位置的c来到零位置呢,那你往下走的数组就是c b a,因为你把二位置c2 位置的c和零位置的a交换了,然后这呃这里面比较多对吧,我靠这个画不下了,怎么办,那就写小一点好吧,写小一点啊。

把abc给你展示了,怎么搞个全排列,就是我们从始至终只有一个数组,能不能实现全排列,你别给我搞新的结构,我觉得烦是吧,可以啊,第一个分支零位置的a还在零位置。

那就接下来这个数组就应该是b a b a b c的样子对吧,这个数字就是a b c的样子,然后这个分支呢就是一位置的b来到零位置,他要交换,那么这个数组的样子往下传的就是b c这个样子对吧。

二位置的c呢来到零位置,那我就希望这个他后面往下传的样子是c b a它,但是它依然是一个深度优先展开是吧,好我们就说这个这就是我们在这就是我们在谁来到零位置,这件事情做了决策,下面干什么。

谁来到一位置来做决策,谁来到一位置来做决策,好,这是零位置,这是一位置,二位置我们已经走过的位置,这就已经来到了位置,就是这个零就是此时来到的位置,在上一步的时候,零就是此时来到的位置。

下面就该轮到什么,此时来到一位置对吧,一位置,那么谁来到一位置呢,你不要再把一左边的东西再放到一位置上,你只能从一开始往后的这些位置,这些数可以尝试放到一位置上,啥意思呢,就是香港轮到谁来到一位置了。

但是谁来到一位置这件事情你不要再把你已经放在零位置的东西,反复的来到一位置,这个全排列的思路就是说你看你如果你不分顺序,a b c我先我问你先零位置的可能性有多少种,三种对吧,意味着可能性有多少种。

两种可能性多少种,一种就这样的东西,所以就是来到零位置的时候,你所有东西都可以选来到一位的时候,来到一位的时候是已经决定好谁在零位置上了,你就别他就不能自由选择了,懂这意思吧。

来到意味着就是你零位置的已经是决定过的了,你就不要再自由选择了,剩下的字符中谁来到一位置,同样道理,你来到二位置的时候也就直接确定了,因为零位置一位置已经固定了,相当于你只有一种可能性支持你的二位置好。

那么具体来说,你你你听你听一个影子是吧,我会给你彻底展开的啊,会给你彻底展开的,你看你就知道明白啥意思了,那么在这个数组中呢,我既然零位置是已经选择了,我就画条线,它不要动了。

那么这个分支就是谁来到一位置,第一个分支就是一位置的b还在一位置,这个分支就是二位置的c来到一位置,没错吧,如果我意味着那b还在意味着那个数组的样子,就是a b c,对吧,就是a b c还是a b c。

如果我让二位置的c来到一位置呢,数组的样子就是a c b,好接下来就是一种选择了,就是二位置的c还在二位置,是二位置的b还在二位置,没有办法选择了,为什么,就像我们说的,来到二位置的做选择的时候。

前面的东西你不要再重复的往回放了,所以如果二位置c还在二位置,那么最后得到的样子就是a b c好,你就打印这个a b c,它是你全排列的一种,如果二位置的b还在二位置呢。

你就打印a c b它是你全排列的一种,这我们就搞定了是吧,好我们再看这个分支,就是一一,它还是一个深度,它还是一个深度,像便利,最终你会回到原始大问题的第二个分支上,没错吧。

那么接下来你继续再展开一位置的b来到零位置了,他也是哎谁来到一位置呢,一位置的a一位置的a还在一位置,那就是b a c接下来又是不能选择了,所以你就打印b a c还有一个什么选择呢。

就是二位置的c来到一位置,那你接下来数组的样子就是b c a对不对,那你他他自己最后一个二位置也是没有办法选择了,直接打印b c a再看这个分支,这个分支也是啊,是轮到一位置的b还在一位置。

那就后面下面就得到cba,最后打印cba,这个呢就是二位置的a来到一位置,二位置的a来到一位置,那你得到什么样子呢,c b因为二位置的a要跟一位置的b交换,最后打印c a b所有全排列。

从始至终其实只需要一个数组就可以做到这件事情,我们马上看代码懂我在说什么意思,同学打个一,啊去啊,对吧,我们想实现这样一种事情。

来我们来看代码,这就是它好简单,对不对,你说这个参数好简单,当然你也可以实现成复杂的样子啊,这是什么意思呢,就是string,就是这个这个递归含义是,i及其往后的所有字符都有机会来到,i位置对吧。

string i往后所有的字符都有机会来到i位置,好,那你什么时候是不能再自由选择的了,i如果来到中指位置,是不是所有东西都确定了对吧,因为你看那你你说i往后所有字符都有机会来到i位置。

那之前的呢都是你已经做好决定了,the dream,从零到a减一啊,都是已经做好决定的,已经做好决定了,而i往后所有的字符都有机会来到i位置,是没有决定的,现在要决定对吧,如果要来到终止位置。

那你说明是不是零到n减一都已经做好决定了,是这意思吧,这个时候请你把全排列的结果加入到result里面去,或者他叫answer对吧,或者他叫answer,来到终止位置呢。

那就说明啊这个string string当前的样子就是一种结果对吧,spring当前的样子就是一种结果,然后把它放入到把它请你把它放入到answer,就是那个所有结果的release里面去,好就这么干。

这个代码就这么短,我们刚才说的一切这么多,打这么多科,其实就是短短几行代码,i在中指位置的时候,result加入,此时死dream所表现的样子,你看string是个啥,他现在是个字符类型的数组对吧。

请你把这个字符类型的数组转成string,放到result里面去,转成转成一个字面值对吧,转转成一个字符串放到result里面去是吧,当然你也可以在这加return,你也可以不加。

你也可以在这加rn直接return了,你也可以不加,反正你如果越界的话,如果如果越界的话,已经终止位置,下面那个for循环是不会不会执行的对吧,你加了return也行,你不加return。

它下面过程也会直接跳过,那下面是什么呢,重点就是看我i还没有到终止位置的时候,他怎么做的,那就是我的ipad,如果如果ipad没有终止,如果i没有终止位置,没到终止位置。

那么接下来是不是从a往后所有的位置都可以来到i位置,对吧,从i往后所有的位置都可以来到i位置啊,是这意思吧,那我这个g实际上就是i往后所有的位置都可以尝试着来到i位置,大家看啥意思。

你看我这个g是从i开始,g不越界g每次加加,所以这个g就在尝试这个g实际上就在尝试什么呢,这个g就在尝试i后面所有的字符,都能都有机会对吧,i后面所有的字符都有机会,这位置的东西跟i位置的字符做个交换。

相当于。

比如第一步啊,比如说这一步一位置的b来到零位置,它所以a跟b要做交换,b a c这个样子就变成了b a c然后继续往下走了,对不对。

这就说明交换你交换完了之后,继续在i加一位置上,人人都有机会,但是i加一之前的别动了,最后你一定要把这个执行过程执行完了之后,你一定要把这个东西给它拧回来,哎过往的课我们讲了,为什么要恢复现场讲了四遍。

之前的课,现在理解的同学打个一,不理解同学打个二。

啊这个这个原因是很简单的,就是你希望恢复现场啥意思,你看你比如说你最底层,你怎么拧成acb的,我不管,但是你你要想走这个分支,你是不是得得你是不是得依次往外退,退到这一步,再退到这一步再退上来。

这个分支对吧,你一次退的过程中,你必须想办法把这个样子啊,给它变成a b c的样子,然后执行这个分值才是对的,也就是说你每一次交换完了之后,你一旦返回了,你要把它交换了哪些东西再恢复回来。

不然的话他没有办法还原回原样子,给你做每一个不同的分支,这就是理由打二有同学理解了吗,大二同学理解我在说什么,同学理解了吧,大二同学就是我啊,你理解就行了,如果具体不懂的,可以去看之前的课好吧。

就是为了恢复原来的样子,恢复现场,然后才能够正确执行好,我看一下啊啊对你i判断n减一位置也可以,以你以i等于n减一位的时候,中指也可以的啊,也可以的,那么这个就是我们优雅的实现。

这个非常优雅是吧,我就一个位置的东西,我不用再申请新的了,我不用再申请新的了是吧。

我们再看这个题,下面这个怎么打印一个字符串的全部排列,要求不出现重复的排列,还是跟我们刚才哎这个就很有意思了啊,这个就很有意思了,他还是跟我们之前的子序列是一样的,爷爷你也可以像刚才的。

你也可以像刚才那种子序列问题一样,先生成所有的排排列,然后去重是不是可以可以的,在这里面我就要给大家讲一下分支线界这个东西了,分支限界这个东西了。

来我们来展示一下啥意思,如果我们要是硬改会怎么改。

注意我不是在拖时间,而是我们改出来这个版本它不是最好的。

要给大家讲一下这个问题啊,比如说我们现在写个f函数,这个f函数我们可以把它改成哈希set,没错吧,可以把它改成哈希set,然后呢这个f函数往下掉的时候,它这个就掉f掉自己对吧。

的时候我们只要把这个哈希赛特answer l,把哈希set这个把这个字符串转出来,加到这个哈希set里面去,就自动帮我们驱虫了,你可以这么做,你可以这么做,我们看下面这种时间下面怎么实现呢。

我们这么来实现,我举个例子,a a,我们再来举这个例子,aa原始序列是a a0 位置,一位置,二位置我们怎么说的,哎你你可以把零位置的a放到零位置,对吧。

然后你刚才我们那个实验方式是你继续尝试一位置的a放到零位置,还有二位置的a放到零位置,你可以这么尝试好,我们现在不这么试了,怎么试,注意这样,我们把我们在每一层,如果有一个哈希set。

零位置的a来到零位置好,你已经你你零位置,你零位置已经你零位置已经尝试过当前字符是a了哟,然后他会去跑一大圈分支,他会去跑一大圈分支对吧,因为我有这个set的存在,我下面进行了一个分支是什么。

一位置的a放到零位置,我直接把他杀死,我为什么只可以把他直接杀死,因为我用一个set已经记录了零位置上a这个字符的后续,我已经尝试过了,如果你再把一个重复的字符再放到零位置上。

这条路我杀死我直接不给你跑,后续了,所有后续全杀死,同样的道理,这个分支也是二二位置的,a来到零位置,我也杀死,我,为什么杀死,因为我零位置上已经摆过a这个字符了,我不要再重复尝试了。

这样一来我们就取虫了,他他这种方法就叫做分支线界,什么意思,你可以把整个递归你的,你脑海中那棵树彻底展开,所有情况都列出来啊,然后收集完所有的答案之后再过滤,这不叫分支衔接。

这叫你呈现了所有的可能性之后,再在其中筛答案,它是一种过滤暴力递归加过滤的方法,分支限界是分支线界,它也是暴力递归,但是它在进行某一个支路的时候,直接用机制就知道此时的支路我以后都不需要走。

这叫分支限界,就是你人为的给它增加限制,如果没有必要的支路在源头的时候就杀死,你说哪个会更快,当然分支衔接听懂他在打一,分支限界也是暴力递归,分支限界也是暴力递归。

但是它是一种增加了提前就是提前杀死之路的暴力递归,对吧好,那这个东西怎么实现,类似计划搜索吗,哎不类似,他可不类似,记忆化搜索,不能乱用记忆化搜索,可是我要好好讲的东西,对啊。

他记忆化搜索他就是利用限制提前杀死之路。

就要分支衔接来,我们来看一下这个怎么写的,把这个函数擦掉了,好吧,这没有用,这是过滤的方式,方法下面这个方法就是过滤的方法啊,就是分支线进来看,这是啥概念也一样,他跟刚才的概念一样。

你要实现的功能是一样的,功能一样,机制不一样啊,还是一样string啊,零到i位置上已经做好决定了对吧,零到i位上,零到a点已经做好决定了,现在来到i位是什么意思呢,i往后所有的字符都有机会来到i位置。

如果还是终止位置死人当前的样子就是一种结果,加到水里面去,加到里面去好,i等于终止位置的时候,你还是可以把它加到里面去,然后return这可以加return也可以不加好吧,可以加热,它也可以不加好。

接下来看假设就26种字符,或者如果你假设不了26种字符,不只是六种字符,那你这个v的就搞成哈希表的形式,这是啥意思,visit就代表零位置,就代表a这个字符,你有没有使用过b这个字符。

你在当前位置有没有使用过,下面就是c这个字符,你在当前位置有没有使用过,这就是我们26个长度的布尔类型的数组就可以代替哈希表,a字符出没出现过,b字符出没出现过,c字符出现出没出现过。

一直z字符出没出现过,是不是就够了,对吧好,接下来咱们怎么写的,来看,没看还是这尝试每一个位置的字符,但不是所有支路都走的,如果这位置的字符减掉a的阿斯卡码啥意思,字符被转成了数,a被转成了零。

b减a的阿斯卡码被转成了1c减a的阿阿斯卡马被转成了二,理解吧,你看所以就说这种字符没出现过,我才去走之路啊,这种字符没出现过号,我登记他不以后,它就是就算你使用过了,哟对吧,这种字符没出现过。

我登记他才走接下来的之路,如果某一种字符,这位置字符是之前出现过了,我鸟都不鸟,if直接让if没中,直接进行下一个蜘蛛的判断,看着他在打一,这就是分支线进它肯定是比我们过滤的方法要快的,判断没看懂啊。

那你哎呀这个啥意思啊,就是你说你当前string g,如果他是a字符,如果如果string g他就是a字符,你告诉我string g减a的阿卡玛是谁,是不是零对吧,那你去其实判断visit 0啥意思呢。

就等同于你判断a字符出现过了没,理解吗,如果你string g是b字符,就是v字符,如果你死jj是z字符,我问你,那么z字符减掉这个a的看法是谁,是不是25等同于用visit 25来判断z出去没出现过。

这玩意儿就是哈希表,你就把他认为这个哈希表只是我们这样做,快一点理解吧,准备长度也很小,就可以替代哈希表的功能吗,你每个位置的字符没出现过,我才去试这条支路以后,我还要登记它为处。

为了保证他以后不要重复走这个支路,现在听懂同学打一没懂还是没懂,同学打二,这个visit不共享啊,整个过程不共享,对啊不共享啊,我只是在当前这个过程中加了此时我的威廉呀,那又怎么样呢,那又怎么样呢。

共享才麻烦了呢,就是想让他不共享,对不对,你行了啊,不共享啊,对就是不共享啊,谁告诉你共享啊,我啥意思啊,你我现在问你,我不分顺序,a3 个a两个b一个c0 位置有哪些,选择三种,要么a字符的展开。

要么b字符的展开,要么c字符的展开,是不是三种,接下来甭管是什么,之前你去做了什么选择,比如说你零位置,你零位置使用了一个a,其实对于你后面过程来说,就是你你你只有你只有这些东西了,一是不是a可以展开。

b可以展开,c可以展开,本来就不应该共享啊,对不对,我当前位置选什么字符,为什么要跟其他位置共享呢,都明白,同学打个一,啊好嗯啊。

这个就是咱整挺好是吧,给你讲分支线界了,分支线界我们以后还会用到啊,就是他其实是利用去找用利用限制的方式提前杀死一个一个分支啊,他会比你整个都展示完所有可能性之后得到结果再去过滤,那要快多了对吧。

远原本的过程我就没有让它发生,你说他能不快吗,是不是啊,所以我们来看这个这个题我们上节课讲过了啊,这个题我们上节课讲过了,把题读一下,我们休息两分钟,继续不会同学发弹幕,休息两分钟,继续把这个题读一下。

这是当年我们也facebook的原题,注意啊,我们我们现在大家知道我这个课有多么庞大吗,就是关于动态规划的这样一个东西,给你讲得很好,现在目前为止所有的尝试都是从左往右的尝试模型,这只是一种模型。

你看一下这个,哈喽卡不是序列,是不是从左往右开始试,每个位置要跟不要全盘,每个位置开始是每个位置是什么,是什么,该是什么,一直一直往后,从左往右尝试模型,也是从左往右尝试模型,背包也是从做网友尝试模型。

这只是一种模型诶,动态规划跟你讲四种模型,一个模型能够改出来的递归非常的多啊,光一个模型解决的问题就是无穷的,我告诉你一共有四种模型,而且我告诉你,你面试中超过这四种模型的,几乎不会出现牛逼。

这就就等于说什么,你掌握了四种模型之后,哪怕你一个题没思路,你你一个模型不,一个模型套,你也能套出来,听听出来打一,听懂啥意思吧,哈哈哈,这么多年他就有没有之外的模型,有学术上是看是很多的。

但是只是看面试的话,只是看面试的话,模型数量就这么多,这四种模型没有cover住动态规划问题,在学术上是很多cover不住的,但是在你们面试中没cover不住的部分,5% 5%,这么多年都是,好对啊。

就是面向面试我已经说了,算法算法算法算法这个东西,你你你究其一生也搞不完,你怎么在我的课上货机获得一点实际的,那可不就是面向面试学习嘛对吧,还给你讲的基础给你讲清楚,但是告诉你面试他是什么样子。

这是不是你们最需要的对吧,那这个为什么是从左往右的尝试模型呢,它怎么就从左往右尝试了呢。

怎么来看,我举个例子全是一,我问你有几种转化,五个一,这么试的,第一个部分你转出来的第一个部分单独一个一,我问你能不能转,可以转变成什么,它变成了a剩下的四个一,你继续努力去吧,二个分支诶。

你就两个一开头的两个一能不能转11位置的字符是啥,a b c d e f g h i j k上k剩下部分的三个一,你继续努力去三个一,能不能转不行了,所以就这么两个分支,还还是从左往右的尝试模型。

根据第一块儿我要画多大,来枚举,结束了啊,他要打一,所以它还是它就是一个从左往右的常识模型对吧,都是通过网络传输模型都是一种啊,就是我们来具体问题看一下这个递归递归很简单的。

其实而且它是可以改成动态规划的,我们会把我们会在明天把这个题改成动态规划啊,规划的方式给你写了,现在你看不懂不要紧,明天讲啊,一个参数,因为他问的是有多少种转化结果对吧,没要你所有的转化的样子。

他就要你有多种转化的结果,要那个数啥意思,这个地位啥意思,零到a减一上,已经转化完了,那么就是说0i之前的位置如何转化,已经做过决定了,你不用再关心了,就问你零。

如果你只能转a出发及其往后所有的字符串有多少种转换的结果,这就是零到a减一,你可以认为它没有,所以就认为他没有看i往后我问你有多少种转换的结果,如果是这样一种含义的话,主函数应该怎么调,从零出发。

我问你一共有多少种转化的结果吗,递归含义,理解主函数为什么这么调,也理解,同学打个一,接下来我们就看这个抛弃这个递归递归说什么,等于终止位置的时候,为什么return这个e我们解释一下。

来到终止位置的时候,返回这个一是什么意思,可以有两种解释,你能理解哪一种都行,第一种解释,没有字符的时候能不能转化,能转化成空字符串解释第二种解释,找到了一种有效的转化,零到a减一,已经转化完的部分。

你当我终止位置的时候,我收集这么一点答案。

幺幺,那我就让开头的这个一自己作为一个部分,它转化成了a接下来轮到零位置的一去转化,他也用自己单独一个一位置的一一位置的一座,转化了一个a来到终止位置,好之前的这个转化就找到了一种结果。

我就返回一个点数商,返回往上返回,他就收集到了一点,继续这边儿我可有两个一拼成一个k转化,接下来他就来到中值位置,他就找到了一种有效转化,什么呢,转化成了k一个点数往上返回。

他在上游会把这两个一加起来作为总的转化方式,两种,你你这两种方式你哪种理解都行。

你可以认为i为i到中a到终止位置的时候已经没有字符了,我也可以转化就转化成空字符串,我我也可以认为我找到了一个点数,就是我零到a减一上已经转化完了吗,不是他们共同构成拼成了我的这种转化。

第一这种方案叫a和aaa的方式,a的方式,第二种方法单独一个k的方式,就是我之前转化完的部分。

它就是构成了我的一个点数,听懂同学打一,那么这就是我们的base case终止条件返回一点,他没有终止,我i没有到终止位置上来,如果string压中的是零字服务,后面怎么都没有办法转化了。

因为零字符没有转化的方式,我们说了一对应a26 ,对应z只有这些值有转化,零是没有办法转化的,return 0,听懂同学打一,0。2,你你你会在什么情况下让i位置的字符,会在什么情况下。

i昧着字符压中零字符啊,举个例子。

比如说一上来就有个字符串,我让你转化075转不了,为什么零没办法摆,你就直接返回零种方法了,解吧,还有哪种情况,还有这个一零,什么是一零呢,第一种转化方式叫单独一个一转化成a还有一种转化方式叫一零。

你给我转化成啥,k之前a b c d e f g h i j j是吧,这个分支我是可以走到尽头的,已经走到终止位置,返回一个点,如果我让开头这个一转化成了a,你就让你接下来让一位置的字符面对零这个字符。

一位置的字符面对零这个字符,不好意思,它是无效的,反为零种有效的转化,懂啥意思吧,就只要当前av的字符压中了零,后面你就认为无法转了,彻底return 0,说明你上游转化过程让你下游转化不下去了。

那你整个分支都就都应该零种方法。

可以解为分支限界嘛对吧,你可以理解为分支线界吗,你之前做的决定居然让我面单独面对一个零字符,那不好意思,你之前错了啊。

右边还有这样,所以右边g这个位置是有效转化,你会返回一个点啊,左边你左左边这个这样的原始字符十是吧,零位置一位置,位置一位置,那么我就做决策嘛,第一个分支是单独让零位置上的一转化成了a吗。

然后你接下来就要面对什么一位置了,出现了一个零字符,它转化不了,因为我就整个return一个零,但你不要忘了你上游还有一个分支是一零,这个分支可以转化成g那就到哪个位置了,你一零都已经使用过了,对不对。

所以你接下来面对什么位置,一位置,零位置跟一位置你已经使用完了,现在是面对二位置,一个中指位置好,中指位置返回什么,返回一最上以后,他会得到这一个点,没得到左边的点吗,那方法数是不是就一种啊。

是一种转化成这样,刚才问题同学,你现在理解了吗,啊啊啊。

这就是我们,只要你让我单独面对零字符,我就给他两种方法,好的,接下来下面就是我如果我还是没有return,说明什么,i没有终止,而且stri位置不是零字符,对不对,我会我会一直往下继承这个条件对吧。

没到终止,到时候为止,你提前返回了,是零字符,你也提前返回了,所以你接下来的这个就默认是什么呢,没有到终止位置,并且iv是字符,不是零,好,我来想一下了,但你看着代码多,实际上也就那么回事儿。

怎么讲来,我来想一下当前i位置啊,你确定不是零字符了,上面会有哪些字符呢,当然可能是19,i为什么字符当然可能是19,那我问你,如果你安慰着字符是3~9的话,有没有第二种决策,什么叫第二种决策。

第一种决策是单独让i位置的字符去转化,第二这种角色是让i位置跟a加一位着字符共同转化,然后a加二位置去递归,但如果你iv是字符是3~9的话,其实你没有第二种决策。

你根本无法让你根本无法让i位置跟a加一位置出一个数来转化,为啥你第一位都已经是三了,后面这个这是i位置三,比如说3a加一位置,不管是什么数,都会超过26,对不对啊。

这说明我这就是说明我只要iv的字符是39范围上,我只有一种选择,就是单独让i位置的这个数去转,画完了之后让a加一位置去递归,听懂同学打一,我iv字符是39的话,给大家看啊,我们先看最后一个分支。

最好理解的,我第一个字符是一,咱们再讨论,如我第一个字,如果i昧着字符是一,那咱们再继续讨论,还没讲,如果iv是字符是二,咱再记,咱再单独讨论,还没讲,但是如如果既不是一,也不是二。

你就直接返回了一个string a加一位置有多少种方法,最后这个return中的是什么,是当前位置,字符是3~9范围上,你根本没有其他选择,你只有加一这一种选择,听懂他在打一这两个衣服,你都不用管管。

最后一句。

我现在单独讨论一下string当前位置字符是一的时候,当前艾瑞字符是一的时候,是不是我总有两种选择,你安慰的是一,你后面不管是什么数,它都不会超过26啊,对吧啊,你说你11~19。

你你这11~19你都没有抄,你完全可以转,所i位置是一的情况下,总有两个选择,一总有两个选,第一个选择就是让i自己上面这个这个这个一转化成a来,a加一位置去就够递归选。

第二种选择就是让i位置和a加一位置共同同构成一块,接下来让a加二位置,你给我自由去递归去。

是这意思是吧,总有两种选择好,我就看,第一句,其实就是第一种选择,先让这个最总的方法数或者第一种选择下产生的结果有多少,有有多少种,对吧,你看我接下来让i加一位置自由去选择了。

等同于i自己作为单独的部分,后续有多少种方法数,你先告诉我,如果我a加一位置没有越界,是不是我总可以让a和a加一作为一个部分去,再有多少种转换的方式累加起来啊。

e等于一的时候两个分支看懂同学打一没懂打二,当前字符如果是二的话,他和一一样,总可以做出第一种选择,就是让自己单独这个部分转化完,接下来a加一位置去自由选择对吧,它转成b吗,单独让一个二转成了b吗。

接下来问后续的东西,自由去选择,先获得一个方法书,我接下来就接下来。

其实看上去很烦,但其实不复杂,你i位置已经是二了,能不能让a加一位置跟你一起做转化,然后让a加二去自由做选择去,那就要看你i位置跟i加一位置一起拼的这个数它有没有超过26,对不对啊。

你说你下面这个数是三,没有问题,23可以转,如果你是26也没有问题,26可以转成z如果你到了27或28或29了,不好意思,你没有第二种选择,你只能老老实实的让二自己作为一个部分,i加一,你去搞吧。

因为你那你一起拼27无法转,28无法转,29无法转,对不对啊,所以看。

i加一位置没有越界,并且一个a加一位置的字符是0~6之间的,就知道跟我i一起拼,他不会超过26,我就有第二种选择,如我这个if不成立,不好意思,我只有第一种选择,听懂同学打一,就结束了啊。

只和尝试有关对吧,虽然他条件多,但它只和尝试有关,而且是什么模型,从左往右的尝试模型,男性整理好在模型下有利于你的发挥,最大家有没有发现最难的其实是你根本不知道怎么去想,就连你怎么整理可能性都不知道。

完全抹抹一两眼一抹黑的状态啊啊那我现在告诉你,起码现在你具备了一个模型,从左往右的城市模型,对不对,一最后一道题目出现,我就先按从左往的尝试模型,我去套我这个模型下,我就先写一个最简单的样子。

index先写出来缺什么信息,我在补嘛,但它都叫从左往右的尝试模型,对不对,明白我说啥,一个同学打个一没懂打二对吧,这个模型啊它不是死板的东西,它是有利于你发挥的一个东西,就跟我们写唐诗一样。

如果你没有五言,没有七言,没有韵律,你写那玩意儿叫什么呢,什么也不叫对吧,但是有这些韵律了,影响你写诗吗,反而会激发你的创作理解的,我本人是个编剧啊,我只是兼职给你讲课,是不是全职给你讲课。

但是我平时写剧是吧,这个它它这东西都不是死板的东西,它是在这种模型下大量的题目发现啊,都属于这一个模型,那你就从模型出发对吧,你就从模型出发,能够帮助你去想啊对吧,能够帮助你去想。

给你们讲课之余自己写写剧啊,接下来我们要解决一个经典问题了,诶可以改成动态规划,而且它很好改,不要急,放在明天,同样我们今天只讲背包的尝试行为啊,一些尝试行为都可以改,动态规划。

下午啊大家看一下这个,有两个数组,这两个数组是等长的,这两个数组是等长的,这啥意思呢,就是假设长度为n,如果长度都是n的话,它表示有n个货物,为此数组中的i表示i号货物的重量是六四。

i呢表示i号货物的价值,那么一共有n个货物,当然就有你你你这两个数组当然要求等长的对吧,你n个货物,你每个货物都有重量跟价值,那你这两个数组当然是等长的。

所以就这两个数字可以表示所有货物的重量和价值是吧,好,我们把这个题目搞得生活化一点,就说我们认为每个货物都是有重量的,而且都是有价值的,而且都是正数,可以吧啊啊,那我在给你一个袋子,这个袋子呢就是载重。

载重它也是正数,所以这里面就没有负数,没有零,全是正数,你就这么理解你,你装的货物不能超过这个重量的情况下,你装的最大价值是多少啊,可以选挑货物,你可以挑货物对吧,你挑的货物呢最后挑了一个结果。

挑了要冒要某个货物或不要某个货物是吧,最终挑挑了一个结果,挑这个结果中这个袋子里装的这些货物啊,它这个重量没有超过它的载重,而且要在所有的选择中得到的价值量最多同样打一,背包啊,这是最经典的背包啊对吧。

我都已经告诉你怎么做选择了,要某个货物,不要某货物吗,什么模型,从左往右的尝试模型对吧,多往右的尝试模型对吧好,我们来想一下,那你怎么想这个事儿啊,怎么写这个递归都非常随意的,我给你举个例子啊。

比如说我题目是怎么写的啊,我们这个题是咋写的,你看这是我们的这个递归过程是吧,下面一个尝试过程,实际上两种思路下的递归,我们先看第一种,缺什么就补什么,什么意思呢,来看啊,获得重量在w数组里。

价值在value数组里,这俩东西是不会变的,有任何一个时候需要改动他俩啊,该是啥就是啥,不会我不会去修改这两个数组好,现在轮到index的货要跟不要,那这个是啥,之前做的选择。

得你已经达到的负重是多少啊,那应该做货物的选择,使之使得逆境达到的重量是多少,就是我的already w,bag就是袋子的总在中,它也是不变的,他带字的总载重,它是它是不变的,它是一个条件嘛。

所以什么是不变的呢,这东西w数组,数组以及这个bug值大众永远是不变的好,所以这个递归什么含义,x及其往后的index及其往后的货物自由选择之前。

已经让你形成的载重较already w在不要超过bug的情况下,价值是多少,总价值指的是index往后的货物形成的价值,你之前做的选择的价值管理解这意思吧。

这个总价值指的是index往后的货物产生的最大价值是多少,之前的选了哪些货的价值,你不用管,你不要操心,好那我来看,我的already w超过了总在重返回-1,注意返回值是-1,表示。

这种方案啊就是我单独单独规定考,我单独规定一下,就是如果返回-1,a,没有方案,返回-1认为没有方案,如果返回的不是-1,代表有价值,只是价值是零啊,这有价值就是那个返回的值啊,如果返说的不是-1呢。

就表示它是正常的一个反一个价值的值好吧,如果不返回-1,如果不返回-1,认为返回的东西是一个真实的价值,这是我们这是我们第一种尝试是吧,来我们来看一下之前的货已经形成的载重。

如果是w这个w如果超过了bag,你说你index往后还还不仅没得选,而且直接无效返回复一,看到同学打一,那你如果没有在第一句返回说明什么,说明你你现在重量没超,对不对,唉如果你现在重量没超,你又没货了。

为零的价值,它表示方案有效,但你要的价值是index往后的货会产生多少价值,我不用管之前的价值,那我就是零嘛,因为我现在没货了,我又没没有超过你bag的载重,对不对啊,返回零很好理解,对吧啊。

首先我这我我到了终止位置的时候,我重量没超,说这种方案其实到最后是有戏的,证明了他之前的选择有戏,但是问题是你要的价值就是index往后的货,它产生多少价值,所以返回零好,接下来我看两种选择。

一种选择叫我没有要当前的,没有要当前index货的情况下,后续的最大价值怎么体现,already w是不是没有动,你看你原来l a w,你直接把它传到index加一位上去,那就说明什么。

说明index的重量你没往上加,对不对啊,那第一种可能性,那么第二种可能性呢,第二种可能性就是我要了index位置的货,所以往下index加一位上做决策的时候,我是之前得到的already的重量。

加上了我此时获得重量,这个递归我往下传的,p一就是我没有要当前货,请问接下来的货会产生多少价值最大的,第二就是我要了当前的货,面的货物产生的最大价值是多少,是这意思吧,如果后面的过程,如果后面的过程啊。

后面的过程它不是无效的啊,后面的过程是个有效方案,我总共的可能性二的价值是多少,这个是说我后面的货在我要我当前a max或者情况下,后面的获得最大价值,唉你是不是要了他。

所以当前年货的价值加一个后续的最大价值,它就是可能性二的要打,既可以不要当前的货形成p1 ,我也可以要当前的货形成p2 ,你说我怎么返回可能性,一种可能性二中选对我最好的呀,因为我要的是最大价值。

我要打一,就是我们的这种尝试,看着有点绕对吧,你也能写出来的好,我们再看这种尝试,可能你就更好理解了,这是我们最经典的尝试,啥意思,好简洁,省了个参数啊,好棒,是啥意思呢,过程一样。

index位置开始往后自由做选择,我还剩多少空间,对吧,我max或往后做选择,我还剩多少空间叫rise的,这是我们见到的最经典的表达啊,背包问题最经典的写法就是这么写的,来看啊,剩下这么多空间了。

index及其往后的或自由做做选择,这个后面就删掉了啊,但是剩余空间不要小于零对吧,返回index所有的货物能获得的最大价值,啊来看在某一步我剩余的空间已经小于等于零了,获得零的价值,你也可以返回-1。

如果是返回-1,单独标记-1的含义的话,那你在这得到任何一个返回值的时候,你都要自己再判断一下,当这里没有问题啊,我们想想有没有问题啊,还是给你其实没有问题,但是为了你好理解,我怎么写呢。

我这么给你写吧,没问题啊,但是我会让你好理解,如果小于零一表示无效方案好吧,天数已经小于零了,那当然无效方案嘛,我没有小于零,我是大于等于零的,我是大于等于零的,如果没有小于零,我是大于等于零的。

如果来到终止位置,货物返回多少价值呢,零的价值这里面也没有问题,对吧好,接下来一种可能性,第一种可能性,到当前的货,因为我剩余的空间没有任何变化,对我这个p一也没要index货物的价值,因为没往上加吗。

我只是获得了index加一后面货所产生的价值,因位置的价值是不是完全没有被算进p一里,算进去的话,他就应该在后面再加一个,加一个v index了,对不对,是这意思吧,应该加一个东西,对不对,但我没有加。

我就让你后面货物的价值,我就直接是我的p一了,这说明什么,这就是不要index此位置货的时候所产生的价值,是这意思吧,好我们再看,可以这么写了,如果我小于零,就return-1的话,我就可以这么写。

还是跟刚才一样,p2 先认为它是一个无效方案,那么如果那么我的我的p2 的后续啊,我p2 的后续后续就是后面的货物产生多少价值,我就直接这么写,就这样来把这一放,index位置的货,我要了他了。

我怎么体现的,你看我剩余空间,我掉了一个index位置货的空间,那我剩余空间变小了嘛对吧,我们说的所有东西都是正数嘛对吧,那我生一就变小了,接下来我这么写,如果t2 的后续是有效的。

p2 的后续是有效的,-1就有效嘛,那么p2 我就可以让它等于什么呀,当前index位置的货物加上一个后面的一个后续,如果这个是无效的呢,那p2 依然维持-1,就表示你没有p2 这种可能性,它是-1。

你没有改过他的-1,对不对,最后继续p1 p2 做决策,我们是用的是一旦空间减成零就返回无效方案,如果你这么写的话,你就要你就需要在调用的时候要判断p为什么不用判断,因为p一也是-1,p2 b是-1。

那你返回直接就是-1了对吧,如果是-1的话,你p2 b是-1,为什么呢,你你想你你p一吧,p一不可能是-1,为什么rest一进来的时候,它就是不小于零的,你p一的rest是没有变化的,你说p一能违规吗。

他违规不了对吧,后续可能违规,但单独调p一的话是不会违违规的,那你就调就行了,p一跟p第二种返回最大那个跟刚才写的没有什么区别,无非就是我已经把已经形成的重量变成了剩余空间。

这种表达听懂再打一。

你已经就有同学问有没有重复计算,当然有重复计算,我们没有改动态规划之前肯定都是重复计算,rise的初始值怎么设置,好问题来看主函数怎么调啊,当然从零位置开始要货物,什么是他的剩余空间bug吗,打一。

递归过程重复计算这个问题啊,留在动态规划的时候,你现在就只用去只用去理解它的尝试就够了啊,尝试这件事情,你有感觉就够了,能看懂暴力尝试就够了,理解吧,好姐,我们来出柜另外一个尝试模型,另外一个尝试模型。

把这道题讲完,我们就该下课了啊,接下来这个n皇后问题,我们下午的课开始,大家看一眼这个题很有意思哟,我已经告诉你它是另外一个尝试模型了,所以他能不能用从左往右的尝试模型搞定呢,不行,它是另一个模型啊。

对模型的总结啊,对于模型的总结,可以说我在国内的算法教学中是第一个人,很多我指的是算法教学中啊,是第一个人,当然之前的sm高手,他们肯定都会这些模型,但他们不叫学,你们老师不会按照模型跟你讲的。

是看一眼这个题有问题,发弹幕,好吧啊,要继续,举个例子啊。

这道题可能我举个例子来啊,给你写个东西。

这是这个东西啊,爱跟玩家必绝顶聪明,这件事是博弈论的设定,我在学术上严格的定义,让你不能因为绝顶聪明,这是个相当主观的事情是吧,绝对理性这种东西都是感觉跟公理一样是吧,你最好不要引入公理,那么他怎么说。

在博弈论里面叫当玩家啊,这怎么说的,那句话叫,双方玩家都会使得对方在单独改变策略的情况下不会获得更大收益,这么说的题,这句话是吧,双方玩家都不会在对方单独改变策略的情况下,让对方得到收益。

这博弈论的基础啊,当然你你你作为你作为这个小白是吧,你就可以认为玩家a和玩家b都绝顶聪明就够了。

那么怎么说,就这样给你举个例子,你就明白了,这个纸牌是一,第一张是一,这个是100,这个是这个是这个是这个是八七十吧,第一张纸牌70,这个是100,是一这是四,玩家在玩的时候只能拿走两侧的纸牌。

玩家a和玩家b如果绝顶聪明,双方都会去算计,怎么让自己得到最大的值,这里面还是设定它全是正数啊,那么其实你最后你会发现正不正无所谓了,但是我们现在为了好理解,可以认为它都是正数,那你想a会怎么选。

表面看起来我拿走70跟拿走四七十好对吧不行,玩家他是个他是个他是个心机婊是吧,他会想我,我拿走70了的话,我就会把这个100暴露给b,所以我不拿这个70,我就拿这个四,他就拿走了,玩家必想,我靠。

你真心机是吧,那没选了呀,我拿走一也会暴露100,我拿走70也会暴露100,我就对我最好的,我拿走70吧,70之后,a说哈,一步步都在我的算计中,你终于没有碰到这个100万,我拿走了,b只能被迫选择。

只有一个一,那么谁赢了,a赢了104,这张如果是很多很多纸牌,双方都会按照最好的方式来算计,请问返回最后获胜者的分数,听懂他在打一,一开始所有的牌都能够被互相看见,是所有的牌都能够被彼此相互看见。

不是取石子问题,取石子问题,同学你见的够多是吧,取石子问题,或者说合并食子问题,这个东西是这个东西是动态规划里面特别难一类问题叫四边形不等式,有空再讲是吧,但是面试中考的不多。

但是我是打算把我们搞到这个训练营里讲的,那那个话题有点太深了,我们还没到那份儿上啊,然后现在往下写看,首先我问一个问题,是不是a一定会赢呢,当然不是110,a他赢个屁对吧。

都说因为你最看面试的只有两张一,a就只能拿走其中一个一嘛,那b就拿走100了吗,那b就赢了嘛对吧,b的分数是100吗,返回获胜者的分数就是100嘛,是所以a不是b赢的。

他还是要根据数组的状况才能就是a算到极致,他也可能赢不了,要要跟状况有关,是这意思吧,到底怎么做,我们先不想,我们先不搞那些里格楞是吧,当然但像这样,我现在想这样一个问题,第叫做先手过程。

f函数first的意思,到r的范围上,如果我是先手拿的话,请返回最好的分数,递归含义含义很简单,在阿瑞的l到r范围上,我要拿纸牌的话,如果我是先手,最后获得的最大分数,好那我们来想一下这个递归。

我们来想一下base case是什么呢,一张牌的时候嘛对吧,肯定是最后就就你你又是先手,那贝斯case就会只剩怎么表达,只剩一张牌的时候,号等于r的时候,就是只剩一张牌的时候嘛,你这个范围只有一个。

只有一个,只有一个位置了,不就只有一张牌嘛,所以这个f函数怎么写,巨简单,如果l等于r,先手,那你把这张牌拿走不就完了吗,一就是我们的base case,如果你剩的不止一张牌呢,两种选择。

第一种选择把l2 位置的牌拿走了,选择,他走了,l位置的牌,本来是什么过程,既然这个过程是这样的,是我我是不是变成后手了呀对吧,我拿走了l牌之后,我就变成后手了,所以我们如果再有一个后手函数。

这个函数假设叫s的话,这个s second的对吧,后手这个s还是这么不规定,l到r上,我是后手拿,请问获得的最大分数是多少,l到r范围上,我是后手拿,请问能够获得最大分数多少,所以当我拿走l之后。

我接下来其实是阿瑞加一到r这个范围上,后手拿能够获得最大分数,你现在我们会讲这个后手怎么写是吧,我们会讲这个后手怎么写,你先认为他就是个黑盒,可不可以,可以吧,这是我这选择,我拿走了左侧的牌。

接下来就在因为范围是l到r的吗,你拿走了l之后,剩下的范围是不是l加一到r没问题,所以在l加r上,我是后手的姿态,问我最大分数多少,是我的第一种选择,那我的第二种选择是什么呢,我的第二种选择是阿瑞。

我拿右侧的牌,我右侧的牌接下来在哪个范围上,我后手了,还要到,而减一范围上,我后手嘛,所以加上一个后手函数,二位r减一,我就这么两种选择,我选什么,当然对我最好的,听不懂,同学打一,管这个后手函数是啥。

你只要理解它的含义就行了对吧,具体是啥,我们接下来马上讲好,为了这个f函数,我们是不是得去把s函数是什么东西搞清楚好,现在我们开始搞s函数是什么。

s函数是什么呢,s函数就是在二位上,l到r范围上,如果我后手,请问是什么逻辑,是只剩一张牌的时候,如果l等于r这个范围上是后手,什么意思,就是人家先挑,然后轮到你只剩一一张牌了,人家就挑走了。

你说你获得啥零吗,一张牌你又是后手,那你拿个球啊对吧,拿个球对吧,看球啊哈啊,就是逗一下好,那如果不止一张牌呢,不止一张牌呢好如果你先是后手,对不对,你现在是后手姿态,如我先手,他拿了阿瑞l。

你拿了你的过程其实应该是什么,如果先手挑走了2l之后轮到你了,所以当先手挑完阿瑞l之后,你不就先手,有的在阿瑞l加一到r上轮到你了吗,对不对,那么我先手他拿走的是阿瑞尔,这个是你的对手对吧。

这个现在的先是你的对手,你自己是后手对吧,如果先手拿走了奥瑞尔,接下来就轮到你了,轮到你是什么范围上,你又该你拿吗,l到r减一上,该你拿对吧,那我们来想一下这首会怎么样,会怎么决定。

会按照对你最不好的方式决定,为什么,因为所有的牌都是正数,你拿他的少,他一定拿得多,你们是零和博弈,对不对,先我会把什么过程让你去选择,你自己是无法选择的,为什么当前不轮到你挑,对不对啊。

所以你你这两个过程谁帮你选的,其实是对手帮你选的,对手会怎么帮你选的,一定是最差的嗯。

这个反函数啊巨简单无疑是吧,来看先手函数就这么短。

如果这里面把i改成l好吧,在二位上l等于r那就是只剩一张牌的时候,l等于r只剩一张牌的时候,只剩一张牌的时候,你就拿走这张牌就完事儿了,跟我们刚才说的一样对吧,否则你就能选,能选你有哪两种方案呢。

第一种方案从左侧的牌以后就轮到我l加一啊啊啊啊,l加一到r上后手了,这是第一种方案,第二种方案,那就当我拿走了右侧的牌,当我拿走右侧的牌,就轮到我l到r减一上后手了,那我会怎么选择对我最好的。

为什么我可以选择对我最好的,因为现在轮到我拿我来决定,对不对,s函数,那么s函数怎么说的呢,s函数还是这样,不改了,你知道i跟g就是一个范围就行了,a到g好吧,a到g如果这是外面没有。

如果上面只有一张牌了,你是后手,轮不轮到你拿呀,不轮到你拿,所以你拿到拿到零对吧,接下来有两种方案,某种方案,第一种方案是你在i加一到g上先手,这就相当于对手,对手其实是把在在挑了阿瑞i的情况下。

它扔给你的,后续叫它,但阿瑞还是不应该算作你的分数的,因为他是对手挑的对不对,所以你能获得什么分呢,i加一到g上先手的情况下,你获得的分数,对手不拿阿瑞i,他就只能拿2g了,因为你只能拿两头的牌嘛。

如果对手挑了rg,就轮到你fa到g减一上,你先手了,对手一定会扔给你最差的,因为里面都是正数,你们俩是零和博弈,怎么掉在这儿呢,在零到n减一上获得的分数和后手在0~1n减一上获得的分数。

谁赢了就是获胜者的分数,谁大谁就获胜,就是获胜者的分数,所有代码就这么短,看到他要打一,我觉得大家可能是欠缺例子,那我们就来搞一个例子啊,啊我们来搞一个例子行不行啊,说一下主要说这个啊。

你说这个是啥意思啊,在array 0到n减一上先手,a能够获得最大分数对吧,是不是a面对领导减一自己先手啊,是的,所以这就是a获得的分数,蓝色的,那底下是啥呢,零到n减一上后手,这是不是b获得最大分数。

一开始面对领导人减一就是后手啊,没问题吧,所你说最后谁获胜了,两个值谁大,谁获胜了,我最终要返回获胜者的分数,可不就返回他俩最大值吗,这不懂这不懂是吧,我给你举个例子。

你就懂了,比如说,就110 七这个范围,啵啵啵,你你是后手的话,会有哪两个选择给我挑走,100在1~71,你就在你你你就在这个l加一到r上先手了,就等同于你去先手挑一七,挑走了七。

那你就在l到r减一上先手了,那就100,你可一你去挑这个这样一个分数吧,这是你后手的时候,你说你说你的对手会扔给你什么过程,当然是这个人家会把100挑走,换的话,他他他可能不求当前的最大。

但他一定会扔给你,后续的最小,选择对你最不好的方式让你挑,他一定会让你面对一七去挑,不会让你面对110去挑,因为110挑就把100挑走了。

对嘛对吧,对手一定会要么拿ri,要么拿rg,这个都不是你的分数,你你你只能被迫接受两个状态,a加一到g或者a到g减一,而且是对手决定对手一定会选择对你最不好的,这不你不是说你想选,你非得搞mean。

不是是你没得选对手扔给你这两个中的最小听懂他打一,你你都已经是后手了,你你在当前不,你有什么选择的,你你有什么选择权呢,没有不对啊,这个范围上你目前是后手。

你忍着你忍着别人挑完你剩下剩下的你挑对手会怎么给你最小嘛对吧,你拿的小是不是他一定拿得多,求和怎么没求和啊,这不是求和吗,分手的时候,你挑了一个分数累加上那个什么后续过程。

这不是求和吗,举个例子吧好吧,看了很多,很多人不懂是吧,那就啥例子啊,这个,嗯,七我们看先手过程是啥,你说他会这个这个这个线的过程是啥啊,就是012,没错吧,我们分别展开一下主函数,这么吊的主函数需要。

f函数02范围上获得的分,一对吧,函数也需要知道02范围上,后手的时候获得的分是b然后a a和b中要选一个最大值作为获胜的,是这意思吧,好我们分别展开f021 在什么,零二它依赖的是这样的。

我第一种选择我拿零位置的排这样一个后续,第二种选择呢是我拿二位置的牌,七甲一个,后续是这意思吧,好如果你是选择了3号,就是零零位置的这个零位置的牌呢,它后面变成了自己在一二范围上给我后手去拿吧。

如果你选择了二位置的七呢,接下来就变成你在02范围上后手啊啊,01范围上后手就拿了对吧,我们二被你挑走了吗,这个三是零位置,所以你身上的范围是12上后,你后手这个二位置,所以剩下的是01范围。

让你后手好,我们再看s12 跟s01 都是啥,一二是什么过程,他需要他需要知道,如果如果对手拿走了一位置的牌,拿走的对手拿走了一辈子的牌呢,你就会剩下在二二上,只剩一张,在二二这个范围上先手。

你去拿了对吧,如果对手拿用了二倍的牌,你就会在f11 这个一一范围上先手去拿了,这不是这不是a,如果这是a的过程,这是a的过理解吧,a开始在0~2范围上先手,他要么挑走这个分支,要么走这个分支。

但是接下来这个过程呢是他后手在1~2上又轮到a后手了,这是b在挑,看这个也是b在挑这个分支,那b会挑哪一个是什么,f2 是只剩一张牌了,f22 是不是只剩一张牌了,会往上返回七,一也剩一张牌了。

所以它会往上返回100,挑b舍得把后续100给你吗,绝对不会,b会把后续的七给你行了,所以a这个人这条分支得到的总分,他就是十分,啊我们再看这个分支,那这个分这是底下s01 ,如果b把零挑走了。

就剩f11 ,如果b把一挑走了,就剩f00 ,f,是谁是1~1范围只剩一张牌返回个100f00 是谁呃,只剩一张牌返回三,那么b他面对后续100跟后续三的过程,他舍得把100给你吗。

他舍不得他会给你三所,你最后获得不管左分支跟右分支,你的最好分数都是十分,有没有毛病啊,打一,同样的你在展开s02 嘛对吧,因为你既需要f02 ,你也需要s02 ,这不是你选择的哦,你选你没得选。

是先首先手决定你接下来在1~2范围上先挑,还是在零到,b这是b这是b在选择对吧,b在对后,或者是b在选择b开始是一个彻底懵逼的状态是吧,b在零二范围上是a帮他选完之后,扔给他两个过程。

要么你走f12 的分支,要么你走f01 分支,是这意思吧,是选的a帮的a跳了零,你就去一二上,你发挥去吧,如果一跳了二,你就在101上发挥去吧,好但是自己是b下一轮这这个这个画方块的。

这是a来帮他做的选择,这个画方块就是他自己选择了,因为他是后手嘛,就该轮到他了对吧,第一种选择是我挑了一位置的数,就是100加上某个东西,100某个东西,那就把一位数跳走,接下来轮到s2 到二范围上。

我继续后手,这只剩一张牌了,所以我是我获得个p对吧,我获得个球,我选择了二位置的数呢,我就是七加一个,后续七加个后续,这是我可以自己挑的,接下来就轮到s11 上,我后手了只剩一张牌了,所以我也获得个球。

但我会怎么选呢,我当然选择对我最好的,因为我能选吗,我当时选这个100,这个分支好,往上返回这个100,再看这边这边也一样,我b是可以再拿走零位置的牌的,零位置排是什么,零位置排是三,所以是三加一个。

后续后续是什么呢,又轮到s11 上,我后手了,这个是返回个零的,或者另外一个分支,我拿走一位置的牌,一位置排是100,100加一个,后续后续什么呢,s00 让我后手,我也获得个球。

我还是会选择对我最好的100,b不管怎么选,洪福齐天对吧,他会选择对自己最好的返回102的过程嘛,你把所有东西都摊开看有什么问题啊,最后分数你最多获得十分,你最多获得100,谁获胜,100会获胜。

返回获胜的分数吗,听懂同学打一,成都可以改成动态规划,这种就是范围上的尝试模型,它不是从左往右的尝试模型。

它直接就在这个函数在上l到r范围上,你给我求个最多的分数对吧,范围要尝试模型,我们这道题为什么可以想到是范围上尝试模型,废话提议就告诉你,你可以拿走左侧的牌或者右侧的牌。

他恨不得逼着你的脑袋往从左往范围上尝试的模型,在提醒你听懂的同学打一,啊这个这个4795,怎么样的,四个数步骤可能会比较多啊,但是算这个你自己去调一下函数吧。

好吧,我们把4795调一下,f函数,你在4795是,123是吧,0~3范围上先爽,这个是三三分钟后手,没保存吧嗯,获得13分后手获得12分,他怎么获得的,稍等,之后蓝色给它去掉,如果看795的话。

得到他的七五会落带对吧,对于b来说,七五都会落带,所以b先挑这个七吧,九五的话a肯定会挑九就赢了,b挑五最后获得13分,b获得12分,毛病吗对吧,只是利用自然之会干预一下。

实际上它底层递归它该怎么调就怎么调对吧,只是我用自然之会告诉你,直接跟我们直接看过这个小样本去分析了,实际上你理解这两,那么递归它会自己去试的,它会把所有情况都裂开,特别好,老师你每一步不就是俩分支嘛。

拿左拿右就这么难吗是吧,可以了,然后这个我们怎么样怎么样去选择这些模型,别急是吧,就给你大量的题给你练,让你去选啊,怎么选择这件事情啊,不是很容啊,因为一道题目是有可能用多个模型解的。

1111道题目是可以用多个模型解的,模型是很强的,刚强的,他们就代表着一种尝试的组织,大家理不理解啊,就是我我我想把大问题按照什么组织拆成小问题,它是一个基本根本的组织问题,它不是可可能性,怎么去罗列。

它是一根本的一个玩意儿,就是你这个你这个你这个往下拆子问题的组织是什么样的,就是其实就是代表它的模型是什么样,大家听懂这个这次同学打个一,这就是为什么一个模型呢解决的问题很多,因为在同样的组织结构下。

有可能有非常多的可能性,对不对,每道题目都属于这种组织下,看你能不能不能列出可能性来,如果能练,那就是那个模型就可以把这个题解掉嘛,就是模型是非常强的一件事情啊,也最难是吧,因为它太太过好用。

而且太过于灵活了是吧,那我给你清楚了好下午呢会把n皇后讲了,然后动态规划我们可以开始了是吧,我们会拿,因为这有些题目真的非常难,我可能想到还会给你加题,所以我们会把啊下午晚安皇后问题讲了之后。

今下午剩下时间和明天两天就四个小时,一共是五,应该是五个小时吧,给你单独讲改暴力递归的过程,可以吧好啊,打个满分十分,群里面大家都帮一下,我就是有的同学说说这个怎么怎么样,就劝他去看视频对吧。

讲得太细细致了,真的我自己都觉得讲得很细致,不会的,真的看完过期过往视频,你怎么说句,你只要高中毕业你就能听懂,是这意思吧,啊我已经是最通俗的表达了是吧。

系列 2:P71:左神算法-暴力递归到动态规划2 - Java视频学堂 - BV1Hy4y1t7Bo

大家好啊,就中午休息了一下,下午我们继续啊,在讲尝试之前啊,大家扯两道题吧。

早来的同学有福了是吧,嗯哼,出两道题吧,就是讲一些比较简单的是吧,那个比如说这样一道题是吧,好像最近还考了,就是是哪个公司忘了找面筋,你能找到这个,假设有一个人,这是一条河是吧啊这河里面有鳄鱼是吧。

嗯嗯嘿嘿鳄鱼是吧,那有个小人呢,他要过河啊,他过河,但是他是这样的一个设定啊,就是这个鳄鱼它会一一下把人吞掉啊,就是这个鱼啊,他会一下子把人给吃了是吧,要吃人呢,但是这个鱼吃了人之后会变得非常的虚弱。

是吃完之后会非常的会非常的弱是吧,然后他吃了人之后没有任何反抗能力了,因为他很很撑是吧,他难受是吧,那么他吃了人之后就等同于他变得成了食物,其他的鱼呢就能吃它对吧,其他的鱼就能吃它啊。

就是一旦一个鱼它吃了人之后啊,它就变得虚弱了,就是感觉就是大的一坨食物一样,其他的饿的鱼呢就会把它给吞掉,然后呃,也是一口吞掉,那么如果一个一个鱼吞了一个另外一个鱼吞了这个吃了人的鱼。

它也变得会非常的虚弱,那其他的鱼呢就那就用来吞它,对吧哈哈禁止套娃是吧对就是套娃,一旦一个什么东西吞了东西啊,一个一旦不管是什么鱼吞了一个东西,它就变得很弱,别人就能来吞它。

然后假设鳄鱼呢都是绝顶聪明的,假设鱼是绝顶聪明的人未必是吧,这个鱼是绝顶聪明的,非常的是吧,赛高是吧,那么问你这个人,他什么时候该过河,什么时候不该过河,听懂提议同学打个一,听懂题,同学打个一啊。

就是他他要他趟过这个河水之后,鱼就吃不着它了啊,但他汤喝的时候很危险,这个结论是这个盒里面是这河里面是奇数之鳄鱼的时候,它不该过河,是偶数之鳄鱼的时候,它能过河,很匪夷所思,是不是这个为什么呢。

我们来想啊,假设盒里面只有一只鳄鱼,他能过河吗,他他不行是吧,为什么呢,他过河的时候,这个鳄鱼把它吞了,毫无风险,对不对,因为这个鱼把它吞了之后,即便这个鱼会变虚弱,但是也没有其他的鱼了呀。

所以一只111只鱼的时候,它过河死定了对吧,但你想想如果是两只鳄鱼,过两只鳄鱼在河里呢,这个人其实过河的时候,那买哪个鳄鱼也不敢吃,因为这个鳄鱼一旦吃了这个人,他就变成了当时过河的那个人了嘛对吧。

那就会被另外一只鳄鱼不虚弱的鳄鱼给吞掉,所以两只的时候呢它非常的安全,这个人就可以过河去,同样道理,你这三只鳄鱼是啥情况呀,如果你是三只鳄鱼的话,这个人过河他死定了,第一只鳄吞了他的鳄鱼。

非常的安全了是吧,你想想这个人在过河的时候,如果一个鳄鱼把它给吞掉了,这个人在鳄鱼肚子里是吧,那么这三只鳄鱼这个鼎立的局面,剩下这两只鳄鱼敢吃它吗,不敢吃,就等同于当时一个人过河的时候。

就有两只鳄鱼在那盯着嘛,现在我就变成了人,这两个鳄鱼就等同于刚才那个两只鳄鱼的时候,人过河那种状况,往下推,你就会发现奇数的时候不要过河是吧,先吃到的鳄鱼吃完了之后,别的鳄鱼都不敢动。

但是偶数的时候你可以放心过河,因为没有人敢吃,你没有鳄鱼敢吃,你听到他在打一啊,啊哈哈是吧,这是一些简单的博弈论对吧,还有就是这个海盗海盗分硬币问题也是这么个事儿是吧,海盗分硬币是咋回事啊。

这种尝试都是从小地方你你在那个面试场合,你发现这样一个问题啊,你有的时候怎么分析,有的时候它是别的算法,有的时候它是尝试的算法,那你都想一想是吧,比如说你你你你你就从小的样本量开始想嘛对吧。

没有鳄鱼的时候啥样有一只鳄鱼的时候啥样,两只鳄鱼的时候啥样往上推,那你就找到思路了,对不对啊,就找到思路了,对不对,还有就是我们那个著名的那个海盗问题啊,海盗问题是啥呢,这种东西都是小品是吧。

感觉都是提的小品,我们课上都不会大量的讲,为啥,因为没什么意思是吧,嗯就是就聊呗是吧,就聊聊好了不就完了嘛,但是你聊的过程中,他是日有他其实是有讲究的对吧,它是有它是有讲究的,什么讲究呢。

就是你从小的样本量开始,往大的样本量推,那海盗分硬币问题啥意思,就是假设有五个海盗a b c d e是吧,这个年头有点久了,不确定自己还记不记得,今天大家提到了,我就讲一讲,我感觉还记得啊。

这五个海盗呢有100个金币,他们抢100个金币,然后那么这100个金币啊,他们就想这五个海盗就想要提出一种分配方案啊,这个a呢是大哥是吧,b是二哥三,c是三哥,d是四哥,e是小d是吧,就是从a开始。

每个人提出分配方案,从a开始,每个人提出分配方案,如果大家同意这个人啊,就就就然后就对于这个方案呢,大家会投赞成还是反对啊,每个人投赞成还是反对,你的票数才通过,是超过一半,至于如果要是大于等于一半。

那是另外一个题,我们说必须超过一半才能,你这个你这个当前方案才被采纳是吧,你这当前方案才被采纳,那我们来讲就是如果你的方案被采纳了,那我们就按这种方式来分硬币了是吧,如果你的方案没被采纳。

那提出方案的人会被杀死对吧,后果是非常严重的,会被杀死啊,提提出分配方案的人会被打死是吧,那么就行,那我就最后要问大家,就是每每如果所有的海盗都绝顶的聪明。

巨巨巨聪明是吧啊当然这个他们就只是分这一次硬币啊,这个也是这个也是博弈论的一个基础,就是博弈论里面有一个只只是一次就决定的事情,还是说我以后长期合作要形成共谋,这个在博弈论里面他就是另外一个问题了啊。

我们就说这个我们只分这一次,然后就各各回各家,各找各妈,以后再也不见面了,可以吧啊啊,那么我问你这个这个a作为第一个分,第一个提出方案的人,就就想了我怎么样提出一种方案,首先我自己不会死。

在我自己不会死的情况下,还能够获得金币数量最多应该是怎么提出方案,听起来脑袋挺绕的是吧,我靠那你的方案数超过一半才才才你才能活下来是吧,而且并且分硬币,感觉这个a好难啊是吧啊,这个听懂题的同学打个一。

这个,那题也没懂吗,嗯我们来想一下啊,就是说a提完了之后,如果没同意a杀死他,也以后也不用再参与分金币了,但如果同意了呢,那大家必须投票数超过1万是吧,那怎么样a提出一个什么方案,能够保证自己活。

还能够让金币数量获得最多,必须认为海盗绝顶聪明是吧,我们来想一下,如果你是两个人的时候,比如说我们就剩一个人了,假设就剩一个人e了,不知道是怎么样剩了这一个亿的是吧,之前那人到底提出什么样惨绝的方案。

被人这么这么痛殴是吧,就反正你现在就认为只剩一个亿了,那么剩100个硬币一投什么方案是不是都通过呀,他总不能投自己反对吧,除非他想自杀是吧,而且他又是绝对聪明的人。

恐怕自裁这件事情不会发生是所以如果只有一个亿的话,他肯定会给方案说我我我我我就100个硬币全给我自己,所以你想这个如果升b一的时候,之前的人不知道怎么投的,反正就只剩第一了。

那你说这个这个d会怎么提方案呢,d死定了对吧,d不管提什么方案,一都反对,然后你的方案数就超过不了一半,然后d就被杀死,一独得100个硬币,现在这样听明白,同学打个一两个人的时候,对吧,是这意思吧。

我我我生两个人的时候地死定了,是这意思吧,那我现在想假如剩三个人的时候,剩三个的时候,d d现在肯定怕死了是吧,我抖的跟个筛子一样是吧,我靠千万你你大哥你别死啊是吧,你一旦死了,我死定了。

那e那个小子没憋好屁是吧,所以c会怎么算计c自己拿100个,d也会同意的,为什么d只要自己别死就行,你提什么方案,d都同意,然后c自己投自己,呃甚至可以这么理解吗,还有的人说法是c自己99的给d一个。

d原来是得零个,而且还会死,现在我给他一个,他就感激涕零了对吧,但你如果把这个这个模型中所有人都想尽量杀死更多的人呢,这样就是人性本恶来考虑的话,其实d知道自己如果c被干掉了。

自己面对第一只剩第一这种状态,d死定了,所以dc提什么方案,d都会同意对吧,是这意思吧,听懂三打一啊,好我在想,那么c分配下,他就是他投的方案肯定是c自己得100个,d得零个,e也得零个。

你一反对没用地址是不想死而已,他什么方案都会通过的,所以我就给自己100个好,我们现在假设有b了,这个b进来之后,他会想了,如果轮到c去分配方案的话,这哥俩只能得到零个,而且都不会死,是这意思吧。

如果我如果我的方案,如果我死了,只剩c d e的话,那么d e这哥俩呢他们肯定会得零个,因为跟跟我们刚才说的一样,c d e这三个人去分的话,c100 个,剩下人d肯定会同意的,e肯定反对也没用对吧。

所以b会怎么想,我活着提出的方案,如果我死了,d跟e只会得零个,所以我活着的时候,我只要给第一个,给e一个都不会死,且得的数量比c分配的时候多,我一定能活下来。

所以自己独得98个给d给e分别一个听懂他在打一,对吧,那么d为什么要给d一个呢,给d一个的原因是因为反正c来分我也不会死,对于d来讲,他说c来分我也不会死,我得零个对吧,那我就想把你弄死。

反正我都得零个嘛对吧,有总比没有强对,所以d得一个感激涕零了,而e呢e想哎呀,反正轮到c分,我也得零个,那你现在给我一个,我就同意你吧,是这意思吧对吧,那我们现在想啊,那轮到a分了,在b分配的时候。

它一定是98 011,那a会怎么去拉拢呢,a肯定不会是拉拢b的啊对吧,a肯定不会是拉拢b的,他最好拉拢的人是c对吧,因为我我我b活着的时候,c只能得零个嘛,他是最好拉拢的,所以我给c一个。

b在当时分的时候,给第一个给义一个,我自己投,我自己赞成c我给他一个,他也会赞成,我只要再拉拢一个,是不是就够了对吧,我要给第一个,那跟b的时候一样嗯,所有人性本恶的话,d想反正我都得一个,我就让你死。

因为我很饿对吧,所以我给d两个或者给一两个,是不是都能拉拢成功了,所以a自己读得97个没毛病吧,听说同学打一,是吧嗯,是这意思吧,嗯,这就是从从小地方往外想是吧。

嗯还有一种设定叫投票数量刚到达一半的时候,就算通过,还有一种设定叫人性都是善的,除非我的利益真的受了损,我才投死你,否则的话我就让你活在这样一些模型下,它的它这个它的设定下,他的答案是不一样的。

所以你看到不一样的答案很正常,你看一眼它的设定,理解这意思吧,啊这里面有两个因素决定,第一是你到底什么叫投票通过是吧,第一个设定啊,到底什么叫投票通过,也是超过一半,还是刚到一半。

就算还有就是每一个人在得到硬币一样多的时候,到底选择杀人还是不杀人是吧,所以这个题可能会有很多变形,但基本上分析都是一样的,从小地方开始往外分析,听懂啥意思吧,嗯好啊,想讲今天开始开始新的同学打个一。

想让我再加一道题,同学打个二是吧,我可以再给你举个例子啊,还想听是吧好,那我们来啊,哈哈哈哈哈啊,行啊行啊,再给你来一个啊,就我们非常著名的欧拉信封问题,这个也是从小到大往外推的啊。

从小往外推的是这样的,就是一个村里啊,我规定啊一个村里,这个村里呢这都是很多年前的压箱底儿的题啊,当时分析明白之后就不管了是吧,他也不能够作为算法的讲述,因为它不成体系,它完全就是一种思路。

就是从小往大往外分析,看你自己能把这个条件拆分的多多细致啊,所以他严格来讲没什么技巧的,就靠脑子,但是靠脑子呢有一个重要提醒,就提醒你,从小样本到大样本,村里面呢有一些人,我规定好。

每一个人都必须往外寄出一封信,不能寄给自己,每一个人能往外寄出一封信,不能寄给自己,每个人只能收到一封信,每一个人只能收到一封信,只出一信,只收一信,如果你收了别人的信,那个那其他人就不能给你寄信了。

理解吧,只收一信好,那么在这样一种情况下,我问你这个村里面人有多少种寄信的方式,听懂同学打一,好我们想这个这个如果这个村里面只有一个人是吧,他也够牛逼的是吧,根据我们的设定,有几种寄信方式呢。

零种没有办法是吧,他肯定是零种记忆方式,我已经说了,我寄出的信不能寄给自己,那你就记不了吗,所以一个在一个人的情况下,那就是零种方法对吧,一个枪就是零种方法,如果两个人毫无疑问只有一种方法。

为什么一个a一个b只有一种方案,a寄给bb,寄给a吗,还能有啥是吧,并不会存在别的方法了,所以是两呃,两个人的情况下只有一种方法,三个人的时候呢,那就给他分个类是吧,如果a把自己的信寄给了b。

和如果a把自己的信寄给了c是不是两种大情况啊,我们看看还能不能拆分了,如果a把信寄给了b,b能寄回a吗,不行,因为如果bg回a的话,c难道自己寄给自己吗,对吧,你看如果bg给了ac就没有办法寄了。

所以b必然是不能寄给a的,所以b只能寄给c,那c自然就寄回给a了,这是一种方法,所以在在ag给b的大前提下,并没有其他可能性了对吧,在a g给b的大前提下,没有其他可能性了,它就只能是b g给c。

c g回a这一种可能性,所以是一种吧,那如果a这封信寄给了c呢,在这种可能性下,依然没有其他可能性,c不能寄回给a,因为b会没法记,所以c只能寄给bb寄回a,所以在三个人的情况下只有两种。

这是我们前几个样本都听明白,同学打个一,啊你说第一种情况,a寄给b c为什么不能寄给b,我已经说了,每个人只能收一封信对吧,a寄给b c不能寄给b了,因为每个人只能收一封,每个人必须寄出一封。

收一封就是限定嘛,好那接下来怎么分析,我们假设五个人的时候,也当然你也可以假设四个人无所谓好,如果我们定义一个函数叫fi,它表示挨个人的情况下寄信的方式数,请你返回,可以吧,这个函数可以理解吧。

这个i就表示如果村里面有挨个人挨个人,你给我返回有多少种寄信的方式,那么f一我们知道了它等于零,f2 我们知道了它等于一种f3 我们知道了它等于两种好,接下来只要掌握一个递推就行了嘛。

所以我们现在假设有五个人,有五个人,你拿谁来分类都可以好,我们现在假设啊,就要把自己的信寄给易,先假设先假设一个假设,b就要把自己的信寄给e,这是一个这是一个确定的条件,这是一个确定的条件。

那么下面我们来分析了,如果那就接下来就就就就哪些情况呢,一把自己的信到底是寄回给b还是不寄回给b是这意思吧,在这样一种假设条件下的第一个小情况,就是e也决定把自己的信寄给逼,那你看一下。

如果e把自己的信寄给b的话,其实你就是一个三个人的欧拉信封问题,听着同学打一,因为你你你必寄给e e又寄回给b,整个系统跟他俩还有关系吗,是不是没有了呀,所以实际上就剩下a c d在玩了,对不对。

是这意思好,那我假设第二种情况,第二种情况就是e啊,他没有把信寄给b,他把信寄给了一个不是b的人,我们假设一下啊,这个e假设把自己的信寄给他,寄个c,这个时候应该怎么分析啊,很有意思啊。

这个东西确实很有意思,怎么分析呢,你想一下啊,这样来啊,呃e决定不把信寄给b,e决定不把信寄给b,我们并不假设这个e要寄给谁,并不再继续假设e要把信寄给谁了,反正他不寄给b,那我们来想一下。

你这个你我们可不可以现在就把b看成一个人了,是可以的,为什么呢,还等着寄出呢,寄出给谁,他不知道是不是有一个初步,而b呢还等着一个人,还等着收信呢,它有一个入度,所以你就可以把b看成一个人。

a c d3 个人在跟b e这一个人在玩欧拉信封问题,所以是四个人的欧拉信封问题,听懂同学打一,对吧我我这个币啊,我还等着收信呢,我这个e呢,我等着寄信呢,他俩就认为是还没有玩的那个欧拉信封的人。

对不对对吧,所以在第二种情况下,你并不用假继续假设一把信寄给谁了,他直接就是欧拉信封私人问题,懂啥意思吧,好那么这样一来,我们就想你假设的是必把信寄给了一,你能哎你假设的是必把信寄给了一。

所以我们现在求的是五个人的欧拉信封问题,或者擦一下是吧,我们现在是f5 ,求f5 呢,那五个人的拉细胞,我们知道在我这样一种假设下,是f3 加上f4 ,在这样一种假设下,f5 等于f3 加f4 。

你也可以假设必把信寄给了c,也可以假设b把信寄给了d,也可以假设b把信寄给了a一种假设是必把新机给了e,一共几种,假设四种,假设整个可能性就是根据b把信寄给谁来划分可能性,所以前面乘个四。

b把e的情况这么多,b把信寄给a是不是也是这么多,b把信寄给c是不是也这么多,b把信寄给d是不是也是这么多,所以f5 等于四倍的f3 加f4 ,听我同学打一可能性的分类是必把信寄给谁这件事情。

当然你也可以假设a把信寄给谁也一样的对吧,听风打一,没能打二,没懂啊没懂没懂,我说一下是吧,就是,首先,我我我这么来问这个问题吧,就是我们在看谁寄信,谁收信的过程中,如果我们就是先关注a把信寄给了谁。

然后看所有不同的方法数,他等不等同于我们就先关注b把信寄给谁,看有多少的方法数,它等不等同于我们先关注c把信寄给谁,方法数它等不等同于我们先看d出发,把信寄给谁的方法数,就这个可能性的划分其实非常的多。

哪种划分下得到答案都是一样的,你可以先关注a把信寄给了谁,也可以先关注b把信寄给谁,你先关注的顺序并不会影响方法数的总和,听明白同学打一,因为因为一个有效的方法,一个有效的方法总有先有后。

而这个方法本身是整体的,至于你你看的顺序是先后顺序,这有什么关系,对不对,那你既然承认说我先关注a先关注b,先关注c,先关注d还是先关注e是等同的。

你现在的情况是不是就可以变成我b我就如果b把信寄给a的情况下,后面有多少方法数,如果b把信寄给c的情况下,后面有多少方法数,同样道理,b把自己的信给d b把自己的信给e有多少方法数。

你只用列出这些可能性就行了,他和你先关注a还是先关注c还是先关注d还是e毫无区别,那既然如此,我们之前假设的是一种情况是这么多,那一共有几种情况呢,答案是四种啊,我d我就关注b。

他只可能把信寄给a或者寄给c或者寄给d或者寄给e吗,一定是不同的方法,所以是四倍的这么多,听懂了懂同学打一,还没懂,我来打个二是吧,我不知道你卡在哪了,或者你发弹幕哦啊,所以我们来写个同样公式嘛。

前三项是这个,剩下所有的fi,拿个公式去玩去吧,听了三打一,讲到你觉得爽是吧,这个好再统计一下,还希望我在加题的同学打个一,不希望看想想听下面内容打个二,还希望我加类似,替同学打个一。

希望继续往下拼个打个二了啊,这已经一半一半了是吧好,那我们以后再讲了是吧,打二同学已经相当多了是吧,那我们就来开始今天的内容啊,把这个给收了,这很多啊,随便讲,这根本就不能单独占用时间来讲了是吧。

好n皇后问题,他讲的是在n乘n的棋盘上要摆n个皇后,n乘n的棋盘上,棋盘上要摆n个皇后,然后要求任何两个皇后不同行不同列,也不能同斜线,请你返回输入一个n返回n皇后的白法有多少种,举个例子。

如果是1x1的格子,就是一个格,能摆下一个皇后吗,可以或者说你也可以认为能摆,你也可以认为不能摆,你为什么可以认为能摆呢,因为这个皇后就摆在这没有毛病啊,他跟谁也不冲突对吧。

但是我们讨论的是任何两个皇后之间的事情,只有一个皇后就显得蛮怪的是吧,你也可以认为有一种方法,你也可以认为有两种方法随你的便吧,反正一皇后问题他也不是应该来说它不称之为一个问题,对吧好吧。

那如果是二皇后问题呢,二皇后就是2x2的格子了,那就四格啊,我有办法摆吗,没有没有办法摆的,你比如说我这个皇后摆着这个皇后摆,这不行,虽然任何两个皇后不同行不同列,但是同对角线啊。

我如果把这个皇后不摆阵摆阵,那更不行,同同列啊对吧,所以二皇后问题是没有答案的,是零种方法,我们在看三皇后问题能改吗,如果真好好改正,哦这是有点过去,我先调一下,看看能不能摆啊,没有方法。

三皇问题也是没有方法的,就你怎么摆都不行,比如说就是没有是吧,就是没有啊,就是你怎么摆都冲突都打架是吧,然后四皇后问题好像就开始有解了,有两个减四黄号问题,就是4x4的,那怎么摆呢,我们先假设一下。

假如这个第一行的皇后摆正这一行就摆不了了是吧,下面这个皇后呢不能摆正,因为这会共列,不能摆正,因为这会供斜线是斜线,是两个方向的,这也叫一条斜线是吧,这也掉一条斜线,所以是两个方向的,斜线是两个方向的。

所以所以这个你要注意这个供斜线这件事情啊,所以这个四皇后问题怎么是一种有效的,我想一下啊,就是我第二行的皇后就不能摆,这也不能摆这了,那我试一下这能不能行是吧,如果摆这呢,那么第三行不能摆这儿。

不能摆这儿不能摆这儿也不能摆这儿对吧,摆这跟第一个重,摆这儿跟这个共斜线,摆这呢跟这个共列,摆这呢跟这共斜线,所以就说明我上一行的皇后摆错了,上下行后我怎么摆的,假如上方摆在这儿,我看我能不能摆。

第三皇后不能摆,这哎好像能摆这儿,因为摆在这儿的话,他不跟第一个打架,也不跟第二个打架,没有共行,没有供电,也没有共斜线是吧,那看第四个换号,第四个皇后不能摆,这儿不能摆,这也不能摆,这更不能摆正。

哈哈啊,因为不能摆,这是共列,不能买,这也是共列,不能买,这是供斜线,不能摆这供列是吧,所以第四个皇后没没活路了,这说明上一部的皇后虽然当前位置不违规,但后面没有没有减,所以这个皇后我再抢一下调哪。

我先给大家展示的其实就是我们n皇后问题的谥法啊,那我看过这个皇后,我能摆正吗,不行,供斜线这个皇后能摆正吗,不行,巩俐,这说明我上面这个皇后也摆错了,那么这个上面这个皇后来到最后一个位置。

已经是最后一种可能性了,这说明什么呢,这说明我第一个皇后摆错了,我第一个皇后不应该摆在第一个位置,我要试一下,第二个位置,我看这样能不能试出来是吧,那么第二个,那么下一行的皇后不能摆这儿不能摆。

这也不能摆,这只能摆这好,那在这种情况下,我看这个皇后能摆正吗,可以他没有跟这个打架,也没有跟这个打架,所以能摆这对吧,所以能摆这第四个皇后不能摆这儿不能摆,这好像能摆这啊,能摆这好。

你看这就是四皇后问题的其中一种解,每个皇后都没有共行,没有供电,也没有共斜线啊,听懂同学打个一,除此之外还有一种,还有一种是啥呢,你把棋盘翻转一下吗,你把这个,棋盘,给他翻过来就行了。

就是现在大家面对的是正面,你从下往上翻过来,翻转过来,从下往上翻转过来,就是形成了第二种解,这个值翻转上去之后的,在这,这个值翻转位置就来个这这个值呢翻完了之后看到这个位置。

这个呃这个点翻就是从下往上翻过去之后来到这儿,这个值翻完之后来到这个位置是我格子画好啊,这个只是翻完之后它会往上来来到这,这个是翻完之后它往下来到这儿,其实这个也是一个解是吧,就这个棋盘。

这个棋盘从下方跟上方,你假设上方固定住,别动,它是一个轴,你把下方的这个棋盘从下往上翻上去,就是这个这个东西是吧,这是第二种解,当然你不用得到翻转啊,我们这个我们在试的过程中没有翻转操作啊。

好我们想一下这个n皇后问题应该怎么试,其实我已经告诉你了,我在试的过程中,我一行一行的是啥意思,假设我是一个九皇后问题,我第零行,第一行,第二行,第三行,一直到第九行,我就每一行在摆皇后。

我每一行首先我每一行摆的皇后,我每行只摆一个,我规定好我在试的时候,我每一行只放了一个皇后,这样一来的话,我的尝试本身就可以规避皇后在行上打架的问题,因为我限制好,我每行只放一个。

所以我就不牵扯皇后在行这个维度上打架的问题,听我同学打一,就我硬性规定他每一行放一个的话,它不会存在皇后在行上打架的问题是吧,好,那么我就那么假设我我我在第零行上摆的皇后,我记在一个结构里。

第零行的皇后,他是什么样的x0 它是什么样的y0 ,我记好,第一行的皇后在摆的时候,我只要防备临行的皇后,不要共列,不要供斜线就行了,听懂同学打一,好这样一来我就有很多选择,对不对。

那我假设我有了一个选择,我选择在这儿了哦,我第一个皇后放在这儿,我会有他这个这个皇后的x0 和y0 记下来,第二行我放这儿会有他的x一跟y一记下来对吧,那我看我第二行的皇后怎么摆呢。

第二皇的皇后就是你要保证他不会和银行的皇后共列或共斜线,也不会和一行的皇后共列和共斜线,我就能知道二列的皇后摆哪了,二列皇后摆好之后,我再记录一个x2 和y2 ,轮到三行的皇后去选择的时候。

我要保证跟之前所有的皇后都不共行,也不供列,我就这么试,如果我发现我在某一行的时候不能摆下任何一个皇后好,我退回到上层去,你的皇后摆的位置不对,举个例子,比如说比如说我们我们现在来到了第五行。

第第五行我们做的第一个选择是把皇后,把把皇后放在某个位置啊,这个是第一个合法的对吧,这是第一个合法的,但是如果我们发现往下摆的过程中,比如说第六行,它皇后已经没已经没有办法让他在所有行上做选择了。

你怎么办呢,你退回到第五行,让这个皇后的位置往右挪一个,然后再看看这个分支下六往下能不能继续摆,所以就是到每一行的时候,我就是到这个位置的时候,下路走一个递归,走完了之后,我在在这个位置的时候。

下路再走一个递归,走完之后在这个位置的时候,下路再走一个递归,周而复始,听不懂同学打一,没等到,好你不懂不要紧啊,我们来看一下这个扣的,你就能具具体就理解了啊,看一下看一下扣的结构概念就有了,空讲的话。

这个结构概念很难讲出来,没事似懂非懂不要紧,看完code你准懂。

比如说这个家不要想不要想下面这种写法,下面这种写法我一会给你讲啊,巨他妈是吧,这个我们看这个啊,这个啥说的啥意思,process一就是我们的尝试过程,说的是啥呢,说的是你现在来到i位置。

他指的是我现在在i行上,我要放皇后,我现在在i行上,我要放放皇后,所以目前来到了第i行,但是零行和n减一行的皇后都存在这个record里看了吗,潜台词是零行到n减一行就上面行的皇后啊,我都存在了。

record里,你你你会想,这个为什么只用一个数组就足以表达上面皇后所有的位置呢,这个是很显而易见的,什么意思,你说你零行的皇后,他是不是一定在临行啊,所以你就record 0位置如果等于七代表啥意思。

零行的皇后放在了七列就够了对吧,因为零行行数皇后每一个皇后,你说他在第几行,零行皇后一定在临行,一行行后一定在一行,所以我只用一个record的整形数组就足以描述上面皇后所有的位置了,你说你说我啊。

我我第七行的皇后摆在了七第一行13列的位置,假设对于我这个数组来说,它就是record,他就是record的七位置,七行的皇后在13列,我用下标来表示皇后的行数。

用这个具体的值来表示皇后的列数就足以做到这一点了,就是为什么我不把皇后的x y下标一起封装,只用一个数组形式就可以表达,这一点,听不懂同学打一,好啊,那么我们就看,所以呢这个这个就是说我当前来到第i行。

record 0到i这些位置的值才有意义,i往下包括i自己在record里面你都认为是无效的,那值还没用到,只我只需要使用零到a减一的皇后的列数,那么一共假设有n层,一共有你n皇后问题当然有n行吗。

当然这个n是个越界的位置,是中指行,所以其实你的有效行数是零到n减一,是不是n代表整体一共有多少行,但是其实有效的行数你下标如果是从零开始的话,它有效的行就该是零到n减一行,零到n减一行是你有效的。

如果你已经到了n,它表示其实已经越界了啊,零到n减一行其实是有效的,如果你已经到了n,那就说明他这个已经越界了啊,你要停,那我就问你,上面的皇后已经固定了的情况下。

哀往后还能有多少种不同的摆法保证它有效,这是啥意思啊,举个例子就这个意思啊,假设我现在i来到四行,这是一个非常大的n皇后问题,假设是13皇后问题,假设我现在来到了第四行。

那你i等于三的时候已经做过决定了,a等于二的时候也做过决定了,等于一的时候也做过决定了,i等于零的时候也做过决定了,好假设上面一种摆法是一个有效的,这儿这儿这儿这儿有效,好,轮到你i等于四的时候。

你去摆它返回什么,它返回的是在我前0~3行必须为这种样子的状况下,后面还能搞出多少种可能性,让它整体都有效,就是上面的问题,你不用操心,上面的只是描述了一种限制。

你最终返回值就是你你要把整个13x13的表填满,但是零行一行二行三行必须是这个样子的情况下。

你有多少种有效的懂我们这个地步返回值含义的同学,打个一,好那么我们主函数怎么调啊,record要准备一个n的大小,这是肯定的,因为一共有n n n行的皇后需要摆对吧。

那我一开始是不是从零行开始做的决定了,那你从零开始做的决定,你整体都统计完,这不就是我们要的n皇后问题的答案吗,现在还没有讲递归,看懂递归函以及以及主函数为什么这么调的同学打个一,没毛病吧。

刚才不懂的同学现在是不是清晰一点了是吧,还一知半解吗,刚才打扰同学,刚才说懵懵懂懂,那个同学现在你感觉如何,好啊,那我们就来看一下这个递归函数该怎么做,i等于n的时候,中指行,你i已经来到中指行了。

就是没有皇后要摆了,你说有多少种合理的办法,一种哪一种上面的状况,这一种听懂同学打一,对吧,是不是有一种忘了中指行的时候,就找到了一种上面的,这叫上面的状况好,那底下的潜台词是什么呢。

就是你没有到最后一行,没有或者说没有到终止位置,还有皇后要摆,来我们来看你怎么试呢,是法是当前行在i行尝试i行所有的列,尝试我当前第i行的皇后摆在i行所有列上,就是这个g那这个g怎么取值,从零列开始。

在i行零列,i行一列,i行二列,一直到i行n减一列,每一次g加加,具体尝试的时候来看这个是啥,大家现在把它理解为一个黑盒,什么什么意思,这record里面是不是放着上面的所有的皇后,是的。

你当前的皇后是不是在i行j列,是的好,我去这个函数里,我找过所有的皇后,看跟你冲不冲突,如果不冲突就叫有效,如果冲突,你赶紧试下一列,你现在把它理解为一个黑盒,之前的皇后全在这个record里面。

我当前的皇后就摆在了i行j列,如果它是有效的,就是他可以摆的话,好哀皇把i行的皇后在哪儿记下来,你给我去统计a加一行后续的所有可能性累加起来,也就是说gg摆到一个位置都算后续的可能性。

再把下一个位置都算后续的可能性,这再把下个位置都算后续的可能性,所有都加起来返回答案,但是我必须保证ig位置是能摆的情况下才加,如果他压根跟之前的皇后就冲突,你直接这跳下一个听懂同学打一。

啊对这里面你会看到说哎你这个record g了g你为什么不还原回去呢,为什么不还原回去,我第一回做到零的决定,record让它等于零了的ip,让它等于零了。

我下面的决定直接就改record的iv值等于一,下面在下面决定直接就改i record的i等于二,是直接改的,你有什么必要把record的i先还原回原来的值再改呢,你直接改不好吗,不是说不需要还原现场。

而是我们还原之后也要重新设置值的,这就是为什么我这个record的i直接等于g就行了,并不需要在跑完之后再再再再在这儿再加一个什么还原,因为我一旦进来,我就是改值,所以我没有桃园现场。

但实际上你也可以加听不懂他在打一,那么就只剩一个问题了,怎么验证他不打架,只要把这个怎么验证他不打架这件事就搞搞搞清楚,那么整个代码它就是非常顺利的代码了,怎么验证他不打架呢,这个方法比较秀啊。

好我现在问大家一个问题啊,假设一个下标叫a和b,另外一个这个皇后在a行b列,另外一个皇后呢在c行d列,如果两个皇后冲突,a b c d的值会有什么关系,如果共列,那b等于d,这是肯定的对吧。

首先我们不用验证它是否共行一,因为每一个皇后他必然不共行,所以我们在验证方法里面,我们没有必要加上行的判断,你一行皇后一行的就只会放一个皇后的,你肯定不会在行上打架,这就是列打架的逻辑。

好用斜线怎么什么样的形式比较简单,这样的啊,举个例子,假设我在七行十列放了一个皇后,他这条共斜线是啥啊,九列对吧,他这好呃,八行九列对吧,就是它斜线位置,它下行包是啥,七行七列对吧,它在皇后是啥。

八行六列对吧,如果是这条斜线,你看满不满足这个,a减c的绝对值等于b减b的绝对值等于吗,我这个位置是八行九列,所以a减c就是7~8,绝对值是一。

b减d我这个b在10d在90 10-9也是1a绝对值关系满足对吧,所以这条这个这样一个方向的斜线满足这个关系,这这样一个方向的斜线也是这个关系,比如这个斜线这个皇后在哪,八行11列,八行11列满足吗。

我的我的a是七,我的c是八,所以a减c还是-1,绝对值是一,我是我,我我这个d等于11,那个b等于十,d减b 11减十是一,不管是这样一条斜线还是这样一条斜线。

都可以用a减c的绝对值是否等于b减b的绝对值来表达。

才打一,当然你也可以分开写啊,当然你也可以分开写好,既然有了这样一种简洁的表达。

检查任何两个皇后的关系,他就是,过,只要这个条件满足,那就是不达标是吧,是这意思吧,只要这个条件满足,那就是不达标,这只是这两个皇后之间怎么验,那我怎么验。

你看啊,这是我当前皇后在i行j列,我遍历所有的皇后,我从零一直变异到i减一,因为我自己皇后在i行,我只能看上面的皇后跟我的关系,所以我便利到i减一好任何一个皇后是什么,中间任何皇后在k行bo k列吗。

是这意思吧,你你你k等于零的时候,第零行的皇后在零行record 0列位置,皇后在k1 record的一一列位置,所以任何皇后都是k行record的k现在的皇后是什么,i行。

于是你看如果g等于record的k那就是共列或者o的k减g的绝对值,如果等于a减k的绝对值,那就是这个,只要有这么一个违规,甭管是哪个皇后跟你打架,都叫你无效,如果你验完了之后都没有返回false。

那就说明你跟哪个皇后都不打架,返回tru,至此,所有的尝试我们讲完了,听懂快打一,接下来,早点开动态规划的课,但是还是我们我们这个算了,给你讲吧,因为我觉得还蛮有意思的是吧,这个我告诉大家啊。

目前想得到n皇后问题唯一的解,现在目前为止最好的施法没有更好的了,就业内研究这么多年,这就是最好的施法,施法上没有突破了,所以n皇后问题又被测试,现在就是他首先可以并行啊,他他怎么去拆他的并行尝试。

这个它是各个国家大型的巨型机计算能力的一道题,就是n皇后问题,他非常的著名,在业内非常著名,尝试方法就是你在刷题阶段,或者说你不是接下来继续深造的话,那你了解这个n皇后问题的视法,这已经是极限了。

并不存在更好的优化了,从事法上是法上没有优化了,但是我们可以把它常数项方面加速,把它常数项方面加速,我先给大家展示一下啊,比如说这是我们,13皇后问题,用加速的方法40ms。

因为我们刚才的方法就毫秒告诉大家,复杂度是一样的,就是因为优化后的方法常数好,你再看一下14号的问题,我们优化后的方法是228ms,刚才讲的那个方法,五秒只是常数项,有优化时间,复杂度完全是一样的。

因为是法上没有更好的了,所以呢我还是给大家讲一下这个优化后的方法啊,这个怎么做的,那15皇后问题那就更更加的复杂了是吧,可能两个都不是可能算得完了啊,这个优化后的方法是一秒多,我没记错的话。

我们不优化的方法要跑一分多钟啊,所以我们就停了,给大家讲一下,这个蛮有意思的,就只优化了常数项,你说用什么优化回答,我听过我课的同学,你觉得用什么用,你觉得用什么优化是吧,对运算是吧,好啊。

还是发个运算的,你将来必得offer是吧,而且是大公司,你心仪的offer是吧,没有发的同学,你将来一定也能得offer,但是没有那么强的祝福啊啊啊,这个,哈哈哈,那我们来看一下,这就是我们的方法二。

他在用微运算来做啊,看不懂了是吧,看不懂了不行了是吧,说什么鬼是吧,我们来慢慢讲,我们慢慢讲,我们怎么讲呢,我们这么来讲这件事是不是,比如说我是一个八皇后问题,比如说我是个八皇后问题啊。

我先申请一个状态,用一个整数表,用用整数的二进制的状态来表示具体的状态啊,就是比如说我是一个八皇后问题,我就准备一个状态,是这样的,后面是八个一,剩下的东西都是零,这是哪个整数,不要紧啊,我们不求。

我们根本就不用这个整数的值,我们只用这个整数的状态问题,你就先准备这么一个数,后面是八个一九符号问题呢你就准备一个数,后面是九个18号问题呢你就准备一个数,后面是十个一,这意思吧。

嗯好就准备这么一个数好,那么我们想了,你会发现你每一行点皇后的时候啊,比如说你想在i行零列上放皇后,其实这件事吧就等同于你他把这个把这所有的列想象为一些二进制位,说我们说八皇后问题三,45678号问题。

如果我在i行上把零列位置放了个皇后,就等同于呢我放完之后他状态是啥呀,就等同于1000万,前面位置都是零嘛,和我在一列上放过皇后呢,相当于是这个位置上是一的状态,剩下位置都是零吗,同学打一。

关于放皇后这件事情,其实我们可以用位运算的一个1v一来代替对吧,这意思吧,理解吧,嗯好,那么你当前放皇后的时候,你跟什么东西有关呢,i位置想放皇后的时候,他可能在某一行i行的时候想放皇后。

他跟什么东西有关,那只其实只和三个位置有关,第一其实只只只和两个因素有关,就是我之前的皇后占据了哪些列,这个位置我就不能放对吧,还有一个因素就是我之前的皇后的左对角线贯穿到了什么地方,我也不能放。

还有一个就是我我之前的皇后的右斜线贯穿到什么地方,我也不能放好,我们现在干嘛,我我现在准备三个值,第一个值叫,防线值这个值啊,我们先把这个数先放在这儿,这个数干啥用呢,一会给你说再准备一个值。

这个值这个值叫列限制,这个值叫列列限制,limit,我一开始在零行放皇后的时候,列上是不是没限制好,所以都是零的状态,全是020,这都是两,啊这个我们区分一下这个划分点在这儿,这就是八个零是吧。

我在0号放缓后的时候,肯定在列上是没有限制的,所以这个分割线左边分割线的右边是八个零,上面一个限制也没有对吧好,那再准备一个变量叫左斜线限制,一开始在临行的时候,上面没有皇后,所以左斜线限制也都是零。

那么再准备个变量叫右斜线限制,那优先限制零行皇后的时候也没有限制,所以也都是零,对齐一下,大接下来这个零行,他很爽是吧,他发现自己列上也没限制,左上也没限制,右上也没限制,所以他就开始尝试了,是什么呢。

我就想在这个位置上我放一个皇后,事实上位是可以放的,因为我上面没有限制吗,好的你注意看,当我在这放了这个皇后之后,就把这个变量改一下,改成一,你干吗呢,然后大家想一下,我接下来到一行的时候。

他的左对角线限制应该是什么呀,应该是我此时的,此时的点到皇后的位置,它的这个左对角线会来到这个位置,就是下面是这个,虽然它没有-1行,我们想象一下,我们想象一下,因为这个一的影响。

导致你左斜线这个位置实际是放不了皇后的,他是不是我列设置完了之后左移一下,就是它下一步的左对角线限制啊,这,大家想一下,如果点六皇后,如果我我下一行的右斜线限制是什么呀,应该是我列的限制,又一一下。

就是我下一行不能放,因为右边对调了,因为右斜线的限制不能放皇后的位置对吧,讲到目前为止,听懂同学打一没能打二,没懂是吧,那我们我我我我我给你举个举个举个好点的例子,假设我们现在啊现在不拿-1太怪了好吧。

-1太怪了吧,银行皇后,假设我放在了四位置,我这几个我这几个变量怎么变,你先别管其他含义什么,就看看这几个变量怎么变了啊,这个我在银行上把皇后点在了这个位置,是个一的列限值是在哪个位置上点一呢,这儿。

一的位置就意味着以后再放皇后,你不能在四列上再放了,什么意思吧,这个列限制我们是要往下传的啊,这个限制往下传的好,那你这个你你现在四位置点了一,你这个列上是不是以后就这个四列上就不能放皇后了,是啊啊。

这所以这个名字叫列限制,理解对吧,那你想一下,如果我来到一行的话,一这个位置是放不了的,这个位置是不是也放不了,这个位置也放不了,为什么呢,因为你有左斜线限制,你也有右斜线限制啊。

你影响你下一行哪个位置上,皇后不能放呢,三列也不能放,三列也不能放,它是怎么来的呢,它是你列限制整体向左移动一位,你就知道下一步的左斜线限制了,同样这道理,你下一步这个位置也不能放,为什么呢。

因为这个一它有右斜线,所以这个位置你要想这个位置就影响着他的右斜线,就影响着你在五列上,其实你也是放不了的,在这个位置上,你得你得你得给点个一,它是怎么来的呢。

它其实你列整体向右移动一位所描述出来的几个变量指导,为什么这么变的同学打个一,那我问你,我我第零行,我第零行放没有放皇后放了,在列上面这个位置被我们描黑了,就代表我放过皇后了,好我下面来到第一行。

我问你,你怎么知道第一行上还能放哪些皇后,你怎么知道这一行上哪些列能放皇后,哪些列不能放皇后,魔幻的来了,把列后八位或上左,我limit后八位,再或上又limit后八位,玩的整体就代表总限制,举个例子。

这位置是一,这个位置是一,这个位置是一,你获完之后是啥,你后八位的状态是00011100,这三个变量或完之后,我就知道这三个位置上如果放了一,我就别选,我选选择可以,还没有变成一的东西,我继续放皇后。

同学打一,知道我们设计这几个变量在干啥了吧,那设计这个变量就想迅速的得到哪些位置能放皇后,哪些位置不能放皇后,这样这种机制我利用我利用位运算是非常快的,好好那么假设我们现在算出来了,我们一会儿再讲代码。

我先算一下限制好,我先算一下限制,我最终说了啊,0011100,当你往还是零的东西上放皇后当然可以在这放,我当然可以在这放,我当然可以在这放,我每个零我都试一遍,例子我们假设在这个位置上点了一个一。

你的列限值变成什么,那我问你,你的左limit变成什么,一位的是左边的变成啥,现在的左limit是0001,左斜线的影响影响到什么,这是一我们标记一下,我们把放一的位置给它画一下,这是我放一的位置。

这也是我放一的位置,那你第二行,你整体的左斜线限制应该是谁,二行整体的左左斜线限制应该是谁,这个一左移一位,这放不了,而最初这个e往左移,应该再往左移,这个位置放不了,是指单纯说你的左斜线限制。

听懂啥意思吧,我我的左斜线,我的左斜线限制来自于我上面所有皇后的左斜线限制,没错吧,我第一行的皇后,我的左斜线限制会一直左移,我当当前的皇后,我也要一直左移,让我的下一行知道这件事情怎么生京城呢。

上面的上面的这个左limit,先在这个位置上加一个皇后,然后得到的这个数统一往左移一位,来打一,同样道理,那你说你的右斜线是谁呢,右斜线的线是谁呢,下一行这个一它往右移移到这儿,再往右一。

应该这个位置是我的右斜线限制是吧,这个一点完之后,我的右先限制下一行是这个位置,是我的右先限制对吧,怎么得到呢,你先在这个位置上点一个皇后,然后把这个数整体右移一位,就成功的加工好了。

你此时的列限制左限制右限制第三行的时候,周而复始呗,每一次点了皇后都在列上加个状态,每一次点了皇后都用有限单几次左移,单次佐伊处理出这一步的左limit,每一次点完皇后都在一。

现在又一处理完当前的又limit,你就这三个变量往下玩下去不就搞定了吗,听不懂同学打一,对于你来讲,你来讲这三个变量永远是独立的,这三个变量永远是独立的,那你说啊,你说好,我假设嗯。

我们下面我们下面再接再再再举个例,上面限制完了之后是吧,我假设在这个地方点了皇后,在这个地方点了皇后,列我的列limit处理好了正确的左limit处理好了,正确的又limit也处理好了,正确的限制市场。

同样道理,下回来的时候,你先把列左limit,右limit全和在一起,一这个位置是一列上这个位置是一对吧,只有俩一混在一起,还是一四位,第四位是零啊,或者说这个三三列上是零,三列上是零点了。

皇后活下来一,下面呢,这个五位上是零,六位上是有限制的,非常没限制,你看你下面迅速知道,我要在这三个零中选择放皇后的位置,再处理完列,因为他左来为他,右limit,继续往下传,肯定快。

为什么我根本就没有遍历数组诶,我就是用位运算直接把胃取出来,点皇后的而已,大逻辑,听朋友同学打个一啊,没关系,不懂的话,我们看扣的,没有讲这个数是啥用对吧,你放心啊,有给你讲的时候啊。

你放心,有给你讲的时候好,我们现在来看这个扣的,就这么说的,咋说的看啊,这是一个n皇后问题的第二种实现,我把这个limit给改成什么呢,叫改个名字,因为我们拿这个就叫limit吧。

这个这个这个数字一开始不知道干嘛用的,第一句是啥呀,就说你是如果你是问题,告诉你这个limit啊,他就后面有八个一,左边都是零是吧,最后有八个一,位置都是零,那如果我是九皇后问题呢。

那那就是limit最后九个是一,如果我是13皇后问题呢,那这个limit就变成最后有13个一,其他都是零表达,就这一句,说你是32皇后,问题是这意味着你32个位上都是一,这个数字是谁,是-1,这个数字。

-1是32个位上都是一这个东西这个状态,所以说如果你是32皇后问题,请你你就让limit等于-1这个状态,但实际上32问题我们用这个代码是算不完的啊,如果你n是一个具体的不是32的值,比如说八皇后问题。

为什么是这个值向左移八位之后再减一是啥,一向左移八位,那后面就是八个零,减一诶,正好把这个一拆开,它减了一之后,后面是八个一,前面都是零,你就这么写,如果你是32皇后问题,刚才说的那个变量啊。

就是刚才那个不知道干嘛用的那个变量怎么设置,它就是32个一,如果你不是30皇后问题,那就一向左移动,30之后再减一,就把我们的limit搞到手了,怎么处理的,听懂的同学打一,好。

那么接下来就要跑这个递归了,什么意思呢,我们来解释一下,limit,他其实划定了问题的规模,limit其实是在划定问题的规模,我怎么知道我怎么知道他是几皇后。

问题就根据limit最右侧有多少个一来决定这个limit是永远不变的,这个limit这个变量是永远不变的,固定它固定下来想象的吧,你第一个参数是个固定变量,对它是固定变量,如果32,如果是32。

33换后问题它永远后面是13个一,前面都是零,它其实划定了问题的规模,好的这个变量就是我们列的限制限制,位置表示不能放皇后,从位置表示可以放皇后,列的限制,左斜线的限制,右斜线的限制,那主函数怎么理解。

就是我给你一个问题的规模,一开始的时候你列的限制没有左斜线的限制,也没有右斜线的限制也没有的情况下,你告诉我有多少种合法的摆法解递归含义以及主函数为什么这么掉,同学打个一,接下来我们就开始了位运算。

代码是有点难理解的好,然后我们看上来,限制如果等于limit,有意思了,什么意思啊,说你是九皇后问题,你的limit是什么,永远不变的,这后面是九个一,都是零,你的列限制是啥呀。

你在具体某一列上点了一个这个,比如说你一开始列限制上全是零,对不对,这后面也是九个零,哥们啊,八八皇后问题是吧啊八皇后问题啊,比如问你拿举例而已嘛,你是8号问题,你的limit永远不变。

它后面是八个一是永远不变的,随着往列上,我们随着往列上点皇后对吧,这个位置我们点了皇后,看下一列上还能在哪个列上点皇后,在某一个时刻,我发现所有的列上都点满皇后了,并且跟limit一样,八个皇后齐活。

哪一部我们发现诶我的所有列上已经都像艾特那样点满皇后了,表示我每一步摆放都合理,而且最终撞到到了我规定好的一个状态,反为一种有效的听众朋友打一,前面是四个零。

前面前面不是四个零,前面是一堆零,前面是一堆零,啊base case,然后接下来看看代码很短,啊你的列限制或上对角线限制,再或上右对角线限制是啥啊,是不是代表总限制,我们举个例子。

比如说啊你的列限制是00010000,左对角线限制是00100000,你的右对角线限制是00001000或上是啥行限制,啊那我现在想问他取反是啥,取反的结果。

一应该是唯一的位置是我可以摆皇后的位置为零的是我不能摆的,但是这个之前可都是零,你这之前也都是零,你这之前也都是零,所以它取反是后面这些一的状态是有效的,但前面这一大坨灵全变成一了。

说我们把列或成左或向右之后的状态,再取一个反左边为零的那一坨零全变成一了,而右边实际需要的部分是对的,什么需要的部分是什么意思呢,唯一的是可是我可以摆皇后的位置为理,零的是我不能摆皇后的位置。

听懂同学打一,所以了,所以我们下一步处理啊,我们就把它整体啊,再取个反是吧,把它整体给它取个反,他就说是不是左侧的驼铃是干扰的东西是吧,是干扰的东西,但是右侧有效的是我要用的,右侧呢是右侧是有效的。

右侧里面的每个一,可以尝试的位置是吧,可以尝试百皇后的位置,可尝试,怎么把左侧一坨零干扰给它忽略呢,和limit一语,你不就抹掉了吗。

雷姆是啥,如果你是八皇后,问题live永永远远是前面一坨零,最后八个全是一,这个取反的状态和limit一语,它左侧直接变成零了,这正是你,这正好是你要要的,同样打一。

你会你会你会觉得啊这左左边那坨是怎么出现的,取反的时候,那时候可是所有状态都取反对吧,这个玩意儿跟第一个或第二个或第三个或出来的这个玩意儿,或出来或出来的这个玩意儿,它左侧可全是零啊。

你在把这个数整体取反,那就左侧这一大坨零变成了一大坨一嘛,右侧也是取反的,对不对,这一大坨灵就变成一了,你怎么把它抹掉呢,和limit与有一个点,我为什么需要雨,是这样的。

你比如说我前某个皇后点在了一的位置,这是第零,这是第零列,是第一列至第二列对吧,我左对角线制我会来到这儿,我在左对角线限制我会来到这儿,我在左对角线限制它其实是一处去了,不再有限制了。

左侧怎么样标记不再有限制的东西切调呢,因为它已经移出棋盘了,对不对,也可以用limit截掉的方式,让以后左移的这个一抹掉,因为你以后确实没限制了它左对角线已经出棋盘了,以后的行不再有限制了。

所以这是那他为什么要截掉最左边那坨一,他怕干扰到明白同学打个一,右侧干扰是不会的,右侧的移出去了,它就移出去了嘛,你又移出去就没了,对不对,但左侧你是需要把它截掉的,好的啊,那你说这个变量是啥变量。

它就变成了所有可以选择皇后的位置都在post上,就这个变量对不对,就可以选择的位置,我可以选可以放皇后的位置,在这个变量上了,这个变量它它经过这样一系列的调整之后,它非常的规整对吧。

说limit无效的那左左边那一坨一我已经给截掉了,全是零,不会干扰我的总限制,取反之后是我每一个一都是我可以放皇后的位置,好的解干嘛了,那你最后你发现啊,经过所有的限制之后,我在我当前行状态是这样的。

后八个一假设只有只有八倍有效啊,这是011000,我接下来是不是尝试每一个一啊,是每一个一怎么写呢,四不断提取出最右侧的依赖,基础班讲过,还记得同学打个一,这同学不要紧啊,新来的是吧,有同学已经发了。

我怎么把一个数字,这左边都是零啊,怎么把所有的一都尝试一遍,尝试的第一个状态是这样的,这是第二个状态,是这样的,第三个状态是这样的,你这三个一,你每一个给我试一遍,怎么做呢。

说回怎么依次提取出最右侧的依赖,数字与上自己取反加一的结果是我给你随便举个例子,比如说某个数,怎么提取出最右侧的依赖,就是最终你怎么给它处理成这个样子,怎么变到他每次提取出一个依赖,先取反取反是谁。

再加1+1是谁,这后面这一大坨一,我没这个一了,袁术语一下,这个位置的一保留了,这个数字与上自己取反加一的结果就是把最右侧的一提取出来的代码,听懂,他打一,尤其是之前没来的同学,看基础班是吧。

好那么所以接下来干啥,可以放皇后的位置,我已经搞好了,接下来,这是,取出post中右侧的一来,剩下位置都是零,一个数与上自己取版加一的结果就是我的most right one,你看这个变量名多直白是吧。

最右侧的一哈哈,最右侧most right man,你得到这个最后的一干嘛呢,如果我们不管最后这一坨,你看这个while循环是怎么转的,我这个最右侧的一,我让原始的数减掉它之后。

下一回再提取出最右侧的依赖,然后再减到这个数之后,再提取最右侧的依赖,其实这个循环就是你post中有多少个e全给你尝试了一遍,底下这一行while循环怎么跳的,看懂同学打一。

每次提取出最右侧的一都拿元素减一下,再去试下个最右侧的一,再拿元素减一下,再去试下一个最右侧的一,可以吧,这个这个简也可以用位运算代替,那我们为了简单,为了让你好理解啊,就直接这么写了。

好那么我们尝试的每一个最右侧的一干啥呢,唉你现在尝试的这个最右侧的一是不是你放皇后的位置,limit该是什么还是什么,永远不变,一行列的限制,就是原来列在乎过上。

此时我点的皇后的位置是不是接下来的皇后的限制列限制,对不对,原来来的列再算上,我此时放皇后的限制往下传和不合理,因为你确实在这个位置上放了皇后嘛,好再看你下这一行的左斜线的限制是什么。

原来左现在的限制或上你当前放的皇后之后,整体左移是不是是接下来的递归里面做斜线的限制,是你之前得到的右对角线的限制,或上一个,此时你放皇后的位置,你们在整体右移是不是接下过程的右斜线的限制。

ok递归去吧,所有放皇后的可能性,得到的方法数全给他累加到我最终的结果中去,返回看,打一,有同学已经关心复杂度了,我告诉你复杂度是多少啊,n皇后问题,你在第零行要集中选择,是吧,你在第一行有几种选择。

你在第二行有几种选择,n种是吧,啊这就是最优施法,没有别的,只是加速了常数时间,就算依然这么复杂,只是加速了常数时间啊,只是加速了常数时间啊,没错啊,依然这么复杂,来我们通过便利才能够搞定的事情。

现在我们直接把有效位置用或运算加工出来了是吧,但实际上他大思路依然是没有变化的,只是用更加精细的方式替代了这个题,真的很难是吧,放心像这种难题,你们面试其中不会出现的,只是因为它这太经典了。

所以老总的总所有的面试官,有的面试官总喜欢问一些经典的问题,所以我给你讲了,而且可以帮助你学习一大票位运算的东西是所以我就给你讲了,但实际上面试中出现这样难难的题目不多见,tsp问题啊。

这种问题都不多见的,几乎都不会考树上这样的这样的东西,研究起来呢有意义,但是工程上他这是就是最优施法了啊,没有更好的了啊,没有你们自己去网上找帖子,随便搜了,翻烂了也不会比这个更好的。

这个微运算用来优化长时间,真的相当秀了啊啊我自己写的,之前我看过一个人知道他思路之后,自己做的优化,他那个原始写的还是有点复杂的,那那那比如说哎老师你这个你这个函数base case全吗。

这些皇后我我后续的过程都是失败了,是个什么过程,啥意思,就是这样的啊,比如说比如说你13皇后问题,结果你吃到第七部上面皇后没摆好,导致你第七部的时候,你所有的东西都已经不能再摆皇后了,会发生什么情况啊。

这种情况就是你上面的皇后没摆好,导致你第七列的时候,你一从零列到12列,你没有办法摆皇后,这个马会不会有问题,不会有问题啊,我不会中这个,因为我没有摆完所有的皇后,这个东西不会中,如果是像我们刚才说的。

在第七行的时候,上面皇后的限制总限制已经让你每一个列都没摆皇后了,那么你这个while循环,所有可以摆放皇后的位置就一定是零,你这个while循环其实没我进去就直接出来了,result等于零返回。

我要打一啊,如果在中途的某一步我已经摆不了皇后了,这个代码不会出问题,在中拖到某一步,我已经摆不了皇后了,你这个第一个if没中,但是你你你既然没有办法摆皇后,那你这个pose也就是零的状态。

你这个里面不不会执行它,直接判断过后等于零,表示你没有办法尝试皇后,直接把这个零的方法数给你返回了,那不就是你要的吗,所以这个不会有问题啊,有有的同学会说,哎老师你背k头上没写,全是写全的啊。

难理解的地方就在于我皇后摆在哪儿,根本就就只只是由这三个限制来描述。

懂啥意思吧啊就我皇后摆在哪儿,这件这件事情它是由三个限制来描述的,就他说我并不严格区分哪一行到哪一行并不区,我只是看我之前得到的限制来指导我此时该在哪个列上摆皇后,所以他可能我比较抽象,为运算的替代。

基本上都是这么抽象的,好这个,记一下有多少同学懵掉的同学打个二,同学是哪里没懂,挺多同学的是吧,好那有同学问了。

我就回答一下,能讲一下那个减法吗,可以啊,说这个吧,八皇后问题,你第一回提取出来的most one是这个,关于我想在这个位置上放皇后对吧,所以你看这个位置放皇后,这个位置放到皇后和之前行的限制和在一起。

就是下一行的限制,这个位置跟左对角线和在一起往左移,这个位置跟右端对要一起往右移,就是下面的限制,这个是这个是ok的对吧,减是啥意思,你看我原来这个数值是我要都要试皇后的,我把它剪完之后,找这个。

再去提取出最右侧的一,于是在这个位置放皇后,然后我再把它剪完之后,就变成了,去除最右侧的一说,我为什么每次要减,因为每次剪完之后,你提提取出最右侧的一,他就会把这个一给忽略了嘛,你看你剪完之后。

这个位置已经变零了,你再把这你在这个剩下的数里面提取出最右侧的一,你每次试的一能不重啊,打二同学,你现在理解了吗,挺多同学没懂的是吧,那你,用e或你可以用异或,也可以用减对异或啊。

因为这个数你e或上这个一之后,他也是得到这个状态啊,也可以用异或,也可以用减都行,我同学打了二,还确实还想给你们操,这个题确实限制很多,这我我一时也想不到更加好的讲法了啊,因为确实挺抽象的,好啊。

那那那就那就那就那就也对啊,再讲也就跟回放一样了,那就辛苦,现在打二同学去去摸一下回放好吧,嗯,那么我们现在就来讲了,我们今天就是这一周的重头戏啊,哈哈哈哈哈,挺多同学打了二的,就是心里挺不好受。

其实这个题也确实难啊,这个题可能自己要啃啃一段时间才会啊,我指望,记问之学是吧。

他尽量给你讲明白啊,保证你看视频不会有问题,哎我们来总结一下,就是这个是一件事儿,告诉你怎么尝试一件事儿,就是哲学问题,根我根本没有任何方法论能够告诉你怎么尝试一件事情,你想把这个事说。

老师你告诉我怎么尝试一件事情,这这这这个问题太深刻了是吧,但是在面试中怎么尝试一件事,o啊啊这个是有经验的啊,虽然没有方法论,但有足够多的经验,有经验,但没有方法论,那怎么判断一个尝试就是最优解呢。

尝试这件事情只能拼天赋吗,不都不是,那么下面我们就来进入到暴力递归到动态规划的套路故事的一道题目,人人都理解啊,粗略问题哦,分布那些数列是啥,前几项,112,八一直往下写好,这大家都知道对吧。

我要求菲波那切数列第n项,你怎么求公式都已经告诉你了呀,fn,f n减一加f减二,是不是可以把它写成一个暴力递归,可以,这样一个代码,这个题好,我给你补一下,因为它足够具有启发性,零吧,就写f。

刚才那个方法是啥,非常简单,我要求飞过那些数列第n项,如果第一,那你要求菲波那切数列第一项他是谁啊,那就是第一嘛对吧,如果你要求菲利普那些数列第二项,那你应该返回谁啊,也是一对吧,因为前两项是一一。

但是你剩下的东西如剩下的东西它就是f函数的n减一,加上f函数的n减二,暴力过程,这个暴力过程人人都知道它可以优化,因为这个t实在是太正常太太频繁了对吧,我非帮大家说,你要求第n项,我就给你从第一项开始。

第一次写到第n项吗,反正你每一项都是前两项相加,这个东西的道理是什么,我就给你展示暴力递归它为什么暴力,是它有大量的重复计算,你想求斐波那契数列第七项,你一定得告诉我。

菲波那切数列第六项和菲波那切数列第五项要强求非凡那些数的,第六项呢,你一定要告诉我想求一定要求出分那些第五项和非凡那些数列第四项,而你说除了第五项呢,你一定要告诉我求职非凡第四项和非凡全出了第三项。

你没发现这玩意儿是个重复解吗,啊我在这个递归里面,我已经求过费,帮那些数列第五项的值了,我再次掉入到一个同样状态的递归中,我为什么不直接拿纸呢,方法为什么,暴力原因是有大量的重复计算过程在浪费你的时间。

所以我们想你不就是从一状态到2f一状态,f2 状态,f3 状态依次推就能推到f7 状态,于是假设你搞一个数组,你把菲波那切数列第一项记下来,第二项记下来,第三项记下来,一直往下记。

你再用一个缓存结构来代替这种暴力计算结构而已,听懂他打一,暴力过程一定是因为有重复计算v的,那我们来看一下哦,举一个例子来说明一下,我们想干嘛,这意思,题读一下,把这个题读一下,然后我们就开始做这个题。

前年阿里的原题,休息两分钟继续,好好啊,那些数列问题有一个特别牛逼的优化,它能够把b勾n的问题优化成b勾lg的解法训练讲,而且呃要讲要讲那个跳楼梯问题,什么母牛问题,什么什么啊。

兔子生兔子问题全是一个问题啊,一一系列这样东西都可以被优化成log n的解法,这个我们是一个专题啊,已经备好课了之后会开这个啊,好,我们解释一下四个参数,n m k p哈哈来看一下,开始在m位置上。

最后要去p的位置,一共有n n个格子,比如说我给你n等于七,三然后可能嗯跳两步跳三步,我想想k等于三,要一共要跳三步,请你最终来到跳一步,跳两步,跳三步,跳,跳两步跳三步。

比如说你最终我想让你来到四位置,啥n等于七代表一共有七个位置,不变的是吧,就这么七个位置,然后有一个有一个有一个机器人,他一开始在三位置上,我要去四位置目标,一定要走够三步,怎么走。

如果这个小人儿他一位置上,它下一步只能迈向二位置,没有这个展示是吧,那我们就假设我们最终从三位置要来到二位置上,来到二倍以上,就规则走的规则,老人他已经来到一位置了,他下一步必须走向二。

那就是如果这个小人他来到七位置了,他下一步必须走向六,做一个小人,他来到一个中间位置,他下一回既可以往左走,也可以往右走,问你有多少种方法让你最终走到二位置上去,所以我们看第一种从三走到二,第一步。

然后二再卖回三,第二步,从三再走向二,第一种方法来,八从三走向二,然后从二走向一,从一回到二,第二啊,那么第三就我不往二脉了是吧,我现在开始不往二卖了,因为已经穷举过了,从三走向二,走向四,从四走回三。

从三走向二,好像就这三种方法是吧好,那就返回三种方法,k的步数很多mp给你,因为你部署很多的时候,这个方法书可能就不止三种三种了对吧,就是路径不一样,就算一种方法问你最终返回多少方法,听懂这个题。

一同学打个一,老师我们写了一个尝试就尝试,我们来想一下,就这个怼一个尝试啊,就是因为总得给你讲点什么,然后才能开始总结嘛,来啥意思,就是这个尝试你别看着很多啊,其实并不复杂啊,一个固定参数。

这个n它是永远不变的,它是一个固定参数,就表示位置的集合,从一到n,位置是从一到n,它是个固定参数,好的指的是什么,卡让它指的是当前来到的位置,卡特来到的位置,看着它,它是一个可变参数。

这个四指的是什么,还剩多少步没有走,所以可变参数还剩多少步没有走,所以它是个可变参数,这个是什么呢,最终的目标是p,我永远是盯着p位置想去他那儿,最终或者说想最终来到p位置上,不返回值是一个整形。

代表啥意思,代表你一共有n个位置,你最终要到p那去,这都是不变的,但是变的你当前在current位置上,你还有rest不可以去移动,最终你来到p位置的方法数是多少种,请返回,这样的话我们主函数怎么调呢。

上面上来洗了一大堆,洗了一大堆无效的参数,比如说位置不过两个怎么办呀,比如说那个卖的步数不到一步怎么办呀,你不用管这个,这都是无效参数,核心方法就是这个目前我最开始的时候是从m位置出发的。

还是下k不可以走,我一共有n个位置,我的目标是p,如果你解了这个递归含义,你就知道主函数就是应该这么调木,但理解没有问题,同学打个一,确保自己听懂了,没懂同学就打二,没有懂同学就打二。

不懂我就给你举个例子好吧,啥意思呢,来,我们想这么干,23456这六个位置对吧,然后假设初始的时候在m位置一定要走三步,请问你最终来到四位置的方法是有多少种,我们会怎么调这个函数这么调的,共有六个位置。

这个参数永远不变,只是从三位置开始走的,你还剩三步可以移动,你的目标是四位置,主函数就要它,这是不是我们的主问题啊,这那主问题啊对吧,我们再强调一点,第一个参数和最后一个参数是永远不变的。

这个表示你的规模是多少,就是你在哪些位置上去走,这个代表你最终的目标是什么,永远是不变的,可是什么就是你当前来到什么位置,你还有哪些路可以走,那你怎么去做这个可能性呢,我们说如果你是中间位置。

你可以往左迈,你也可以往右迈嘛,如果你往左卖了,它就变成了f还是六个位置,你往左就来到二位置了,你还有几步可以走呢,你还有两步可以走,你最终想去四,请问有多少方法,如果你又走呢,你往右走呢。

就是你还有六个,你一共有六个位置不变的,你往右走就来到四位置了,你也剩两步可以走,因为你卖了嘛对吧,你卖了吗,你往右走了一步嘛,所以你还剩两步可以走,你永远盯着是四位置走这个这个递归的结果。

再加这个递归的结果,应该就是你总的结果,一。

就刚才打二同学,你现在有没有理解我想干啥,就是一个这样的一个递归是吧,这个递归就是你当前来到哪,你还剩多少步可以走,你最终能来到p的方法数有多少种,好那我们来看一下这个函数,这是我们的一个暴力过程。

他怎么写的,来看,我还剩零不可以走了,你不能再移动了,哎不能移动的情况下,如果你此时来到的正好是p位置,你找到一种方法,这种方法叫你之前做过的那个决定,还有零不可以走,你你你没不可以走了。

你你说如果当前你没有来到p位置,零种方法,这个领带之前你做过的决定,此时不对头啊,那我们就继续,然后啥,然后rise当然是不等于零啊,有步数可以走啊啊啊,你还有步数走的话。

但是你已经来到一位置了啊的方法输出多少啊,我没有决定你不能去选择,你只能卖到二位之上,然后步数减一步,问你后续有多少种方法,因为你没得选,你已经来到一位置了,你是不能再往左走的,base case。

到n位置了,你也没有得选,你只能来到n减一位置,你还有rise的减一步可以走,后续有多种方法,但是你如果既不在音位置,也不在n位置,那好爽,你既可以往右走,还剩x减一步,方法数累加,你也可以往左走。

还剩rs减一步,方法数两个累加起来总方法数,看懂同学打一,你把注释都去了之后就四行吧,我加了好多注释理解吧。

啊啊有意思了,兴奋他有没有重复计算,列一下嘛,来我们原始参数是n卡,还剩rest不,最终的目标是p那我问你,一直是不是只和你这个可变参数有关,就不传入不同的可变参数会得到不同的返回值。

但是跟和p是无关的,因为这俩参数永远不变,你你内部的逻辑n跟p值作为一个限制条件在使用,你在任何时候,比如说你你当前来到五位置,三步要走一定是一样的,听懂同学打一,就是我不管你是怎么到的五位置。

只要你还剩三步,返回值一定是一样的,那我们现在这样,我们把f用什么来代替,我们就用两个状态来就行了,一个就是我们的current,一个就是我们的来代替。

因为我们我们说了n跟p根本不决定这个返回值的返回结果,对不对,我们看会不会有重复计算,比如说,我一开始在三位置,我想去,我有四步可以走,一开始调什么一开,当然你在三位置上,你还有四步可以走。

啊你要是往左走了,你来到二位置,你还有三步可以走,你如果往走了,你来到四位置,你还有三步可以走,你如果这要不再往左走了,你来到一位置,你还有两步可以走,你要往这儿走了,你还有你来到二,再往右迈。

你回到三位置,你还有两步可以走,对不对,好,他怎么展开你这个位置,你在四位置,你来到左位置,我来到三位置,还有两步可以走,我来五位置,还有两步可以走,诶你没发现有重复结果吗,结果这就意味着。

能做出一个缓存,我我之前算过三二这个状态,我下你再遇到他,我就不正在递归展开了,我直接从缓存里面拿值是不是就够了,听懂同学打一,嗯可以很轻易地改出一种优化,什么优化呢。

这样来我们把上面这个代码拷贝一下。

我拷贝一下,啊这都去掉是吧,什么玩意儿,第一叫v字三,这个叫好吧,沃克三不要忘了改名,这里面都叫work 3,我要开始做缓存了,我怎么做呢,他有这个方法了是吗,他愿意他一诶,怎么v的四有哦,这这这啊。

好哎我写了多少个呀啊,写了这么多个,嗯喂的十,嗯,或者我们叫with catch啊,就是缓存缓存方法,哈哈想怎么改呢,加缓存什么意思来看啊,一写就知道了,我们知道,把锁current和rest组合。

结果,加入到缓存里,我准备一张表,这张表我们的名字叫dp,哎我问你,current范围是从哪到哪看current是一个位置,它既然是位置,他只可能是一到n中的一个,n加一,零位置我永远不用好不好。

一到n我就把current的所有情况枚举了,好是什么,剩余的部署它有能超过k吗,怎么可能你一开始剩k步,你每次走的时候,他剩余步数一定会减小的,所以我准备k加一。

我知道这张dp表可以把底下这个暴力递归过程,所有的返回值装下,听,求所有的current对rise的组合对吧,你看变化范围是从哪到哪,一到n我给你准备零到n空间绝对够用,是从哪到哪。

零到k我给你准备k加一,正好是零到k绝对够用,你不就在这张表中,你就把任意的current跟rise的所有可能的变化全部都能不放下嘛,大二的同学是哪里不懂,现在懂了没懂了懂了,下面我就想办法用这张表好。

我先给他设置一下啥意思来看,好我们把它行肉是小于等于n的,这张表我们把它column从零开始,column是小于等于k的k加,当然这个k要大写,把所有的值设成-1。

周一就表示目前所有的参数组合我都还没算过呢,这个表示你目前所有参数组合,这两个for循环把dt所有东西都过了一遍对吧,你目前所有参数组合你都没有断过,我就给你一个-1状态,算过的话。

你的方法数是不可能小于零的,所以我给你开始有个状态,就是-1表示所有的组合的方法我都没有算过好的,然后我让你这个work开始朱晚,永远这个dp这个东西是共享的,所有子过程大过程全共享,我让他带着玩儿。

啊我怎么带着玩儿呢,我先这样看来来啊,如果你不是让我算这个参数组合吗,我给你这么写,第一批卡润和rest这个参数组合它是-1,你说啥意思,这参数组合是我第一次遇到的过程,我遇到这个参数组合的过程啊。

我没算过,我就继续去算,我就可以展开了,但如果我不是-1,说明啥不是不一,说明你这个参数组合你是之前算过的干嘛,你直接给我拿值,你别给我暴力展开,请你把我我缓存里面的东西直接提走,等于-1的时候。

请你把方法数直接提走好,如果你这个东西是-1呢,就继续,我就去暴力递归,但是注意在这个过程中,你用缓存,你在当时算完的时候,你就得加缓存,啥意思,加来很简单的几行就能改出来,所有的过程都dp玩对吧。

所有的过程都在这个dp玩,没问题吧,好接下来看啊,一开始等于零,然后看如果rest,这样,咱不不要这个变量,你rise等于零的时候,你是不是可以return了,唉return的时候你别急,之前加缓存。

你在return,因为你是吸算出来一个结果,所以你加缓存,你在return,所以这个current rest等于这个返回值,再把你正式的结果返回,都这么干,底下干就是我我我每一次啊,先加缓存。

我都让他先加缓存,哈,先加缓存,大家想一下,我每一次去暴力递归的过程中,我不管你是什么状态,你在返回之前都加过缓存对吧,我找一个过程,我进来之后,我先查你缓存有没有算过,如果算过,你直接给我返回。

我就可以,你省去很多重复计算的过程,听懂同学打一,好啊,我知道啥意思了,这吧对吧,啊这个就是动态规划,太贵花,递归过程中有重复计算,我给你加缓存,下回你遇到同样一个过程,我直接给你解,这就是动态规划。

它还有一个名,它只是动态规划中最糙的这种动态规划叫记忆化搜索,听懂同学打一,好我们来想一下这方法,它是计划搜索下的动态规划,我们但没关心状态的依赖,没有我们我不关心任何依赖关系。

就是你非常傻的一个啥缓存,我遇到重复的解,你拿缓存里的东西,我这个过程我没算过,我就给你去算,他已经动态规划了,那么如果我们把整个这张dp表,这张dp表从简单状态到复杂状态给它列出来。

就是经典的动态规划,什么意思,大家来想,原来我们是不关心,只要我们保证我们缓存够用就行了,唉那我问你,其实你你连这个current呢跟rise这样一个这样一个规模,你都不需要去管。

其实你你用c表能不能行啊,哎你c表行不行啊,什么叫用哈希表,我举个例子,比如说某一个参数组合,我都把它变成string的形式,它的它的最后的返回值叫整形,比如说我遇到一个参数组合current。

你19还剩100步的时候,我怎么记录这个结果,你就记住一个字符串,这个字符串叫19 19,下划线100,发现100这个string就代表这个过程,你把这个结果放到这个哈希表里去,是不是也能做缓存啊。

缓存的结构有很多,我们这种方式已经算是最精细的方式了,听众同学打一,计划搜索这个过程中,其实你你其实严格来讲你都不用去关心参数的参数,它的变化范围我就遇到我就我又遇到我就拿值就完事儿了,对不对。

好点的动态规划就是我们要区分出这是一张什么表来,我们来试一下,这是一张二维表音,有两个可变参数,所有的组合我都要去求,所以所以,把current我们来举个具体的例子,比如说一七这些位置对吧。

n位置你一开始m停留在m停留在二位置,你要走,假设你要五步,你最终你最终想来到的目标是在哪儿呢,假设是三位置这么一个问题好,我们来分析一下,如果我们current做一个行,它的变化范围是多少,1~7。

对不对,17对不对,剩余的步数呢啊,不只会比五小或者等于五,不会比五大对吧,所以剩余的不是05啊,问我要想求解的,如果我单独把零行补出来,但我所有的返回值都能够被这张表装下。

好现在来看这张表该怎么去计算呢。

我去算出来怎么算呢,看我的,看我的暴力递归过程啊,它等于零的时候,它等于p的情况下,它返回值是一,它返回值都是零,rest等于零的时候哦。

等于零的时候这个没有零啊,所以这一行划掉,这还画个叉。

零的时候,等于p的情况下它是一,否则它是零。

那p是多少呢,所以只有这个位置是一,剩下位置都是零。

好我们再看这张表怎么推,你一的时候你依赖什么,你当过程叫car and rest,好,我们不妨设,的时候,current等于一的时候,我永远去依赖2-1的值。

一的时候甭管是什么位置,我都去依赖谁,二一的值哦,我依赖他啊,我也依赖我依赖他,所以这个格子我就依赖他,发现你在第一行的所有值,你在求解的时候,它都依赖自己左下角的值拷贝上去就行了。

我们再看这个看的等于n的时候,y n减一rs减一的值等于n的时候。

比如这个位置我永远依赖n减一rest减一的值哦,这什么位置我依赖这个,甭管什么位置,我依赖这个,甭管什么位置,我依赖这个,最后一行任何一个位置的值,它永远去依赖自己左上角的值拷贝就行了。

任何一普遍位置都依赖cr的加一。

rise的减一跟cr的减一,rise的减一啥意思,任何一个普遍位置都依赖我。

一rise的减一,那是哪儿呢,减一哦,依赖这儿,rst减cd减一,rest减一一,在这儿我就知道任何普遍位置是把右下,是把左下角和左上角的值累加起来,得到中间的格子,就听懂同学打一。

啊我在你改动态规划的过程已经不需要原题意了,就看的暴力递归足以改出,算了听众同学打一,有一个同学他写了一个二维可变参数的递归啊,其他这个东西怎么写就足以搞出动态规划了,都不用管原题意是什么,听不听懂。

位置怎么填啊,这,我就依赖我左下角的值零,这格子左下左上角的值加左下角的值一,这格子左上角的值加左下角的值零,这格子左上角的值加左下角的值一,这格子零这格子零,这格子只要左上角的值零,继续。

这格子只要我左下角的值一,这格子左上角的值加左左下角的值雷,这格子左上那个值加左下角的值二,这个格子左之间左下角的值零,这是格子左上角的之间,左下角的值一,这个格子零,这个格子左上角的是0303010。

接下来306,零四,最后一行零九,14,推完了不就依赖那些格子,你一直往下算就行了吗,好主函数要什么状态啊。

mk是谁啊,听我在打一,方法论了,啊不用想什么转移方程怎么憋,什么让你去写暴力递归,因为它跟自然智慧最接近啊,五啊是吧,4+15啊,还有写错的吗,让你从暴力递归开始憋,唉我们想象一下,刚才我们讲的时候。

每一个机器人可以往左走,可以往左右走,你分析的时候自不自然在保商的博弈问题,唉b他是后手,他的过程是对手扔给他的,这种分析自不自然智慧诶,他是先分手,他当然会在左选择跟右选择中选择对自己最好的。

特接近于自然智慧,我告诉你,你暴力递归的分成抽象出来就是动态规划的转移方程,听懂同学打一,还规划,注意我说的是任何一个动态规划都是有暴力尝试的,那个尝试的种子改过来的。

为什么老你你你们的老师不给你们这么讲,因为麻烦啊,你的麻烦是讲的麻烦,开了一个天窗,只要我我们可变参数是有限几个,它是三个可变参数,它就是一张三维表,它是两个可变参,它是将二维表,它是一个可研参数。

它是这个一维表,只要我能够试出有用参数代表的一个暴力递归,我就能改成动态规划,听不懂他,是很久了是吧,接下来明天的课,大家整得好好的,所有的尝试会让你体会得非常的深啊,明天继续讨论,打个分,满分十分嗯。

有的同学问了,不是所有暴力递归都能改成动态规划的,是所动态规划都来自于某个奥利递归,听懂之后打个一,我的动态规暴力递归都可以搞成动态规划的,是所有的动态规划一定来自于一个暴力递归。

而这是跟我们自然智慧特别贴合的,你知道该怎么去拆,起码它比直接让你憋动态转移方程好吧,哦有些暴力递归,太规划的原因是它没有足够多的重复过程。

啥意思,来我们来举个例子啊,你可以改,只是这种改法没必要,举个例子,如果我说有一个函数f它有两个可变参数,但是我告诉你过程中撞不上重复行为一后面无限的递归,这这也无限的递归。

你这个可变参数a跟可变参数b就没有撞,就没有重复的组合的时候,你能不能依然把它改成缓存去做一张表,但有没有必要,为什么必要,你本来所有的过程都是新的,你缓什么缓呢,理解这意思吧,听了同学打个一。

你你用不用远远可以改成缓存法,但是有些暴力递归,你撞不上这个重复解,你改它干什么,嗯,什么时候知道要用动态规划,这这这这不是给你给你给你列了吗是吧,来看,尝试模型。

你感觉这某种常人模型能拿下他的动态规划,这送常人这四种尝试模型拿不下,大概率就太会画了,学术上再把一个这正常的问题,有可能是多种方法都能够把这个问题解的,不是说某个问题属于某个解法。

而是哪个节解法可以解决这些题,懂这意思吧,就这个关系是什么呀,这样的谁告诉你动态规划的题就不能用其他题解了,一开放出来的一个问题对吧,我有些问,有些问题可以用动态规划解,也可以用别的方法解。

这个时候要看刚才想想,我们刚才给你讲的,怎么尝试一件事情,是个哲学问题,我问你怎么解一个题,是不是哲学问题啊,问题嘛对吧,你只能说唉我我我善于用动态规划,我熟悉了很多经验。

这道题我感觉它跟哪个公开规划比较像,我去找他要累的问题,说唉我碰到背包,我就去想动态规划,这可以,但是你的问题太宽了,怎么知道任何一道题定位它是不是动态规划,没有人能告诉你。

这个不不不不是是说不是说我水平不够理解吧,不是说我水平不够,而且没有啊,就是没有啊,太抽象了对吧,你看哪些题目,老师你告诉我,他就是动态规划解的经验上哪一类,哪一类,哪一类是从左往右的尝试模型。

范围上的尝试模型,一个样本做行业,一个样本做令的对应模型,分支线接的限制模型对吧,这程度了,但他没有,而且也没有老师能告诉你啊,一看就知道那是哪个哪个基础知识解答,那是神仙是吧啊,这只有到是吧啊。

我们明天会继续讲啊,我明天会继续讲这些,开了一个门是吧,打开一个窗窗子,就是他就是在把,和这件事情给他玩成结构化的理解这个话的同学打个一,仓参数组合完成一个结构化的缓存,这就是,讲了两种。

一个是从左往右的模型,一个是范围上尝试的模型,当然我们也会明天也会继续讲,我们会把我们暴力过程中没有改成动态规划的全给你改了,让你去深刻课的体会这个从递归到动态规划的一整条轨迹,好谢谢大家啊。

没打分同学打个分,然后我们明天继续啊。

系列 2:P72:左神算法-暴力递归到动态规划3 - Java视频学堂 - BV1Hy4y1t7Bo

喂,来了来了来了,大家好啊,我接着昨天讲是吧。

我昨天是不是嗯改了一个动态规划是吧。

这个,嗯就是那个机器人运动问题是吧,那个机器人运动问题,那个表的结构我画了,角就表的结构我画了,但是这个代码没写是吧,我们昨天是昨天是只讲的那个表的结构。

但是它具体代码没写,我就说昨天说的是,如果这个地方是current是吧,这个地方是rest,先把最后第第第零列填好是吧,然后从第零列开始依次往下推推到最后一列,这个代码我我我我就不展示了。

因为昨天按道理来说应该讲一下是吧,但实际上他这个表的结构已经非常的清晰了是吧,你自己去填好就行了,我们讲一个新的题呢,那要看一下有什么弹幕,还有同学应该是问之前的一个全排列的问题,为什么在你死你。

你在你在调用递归之前交换了之后,再调用递归之后再交换,它还能保证是原来的ig换回来是这意思吧,因为你每一次在调递归的时候都会换回来,所以你看上去是你掉了一个子过程,回到你之后你再换。

你为什么可以保证i跟g位置是相互之间还原的,因为你的子过程全还原了,所以轮到你的时候你也还原,能不能够正确还原完毕,这个小龙同学懂了吧,嗯好让我们来继续看这个今天要今天讲的,我们今天讲的内容。

然后我们还有一个任务,就是把昨天讲过的那些场暴力尝试重新改成动态规划,是这意思吧,嗯啊昨天我们讲了一个啥概念啊,就是我们说这个任何一个暴力尝试,只要你发现它有重复计算的过程。

然后呢你就把它的可变参数变成一种结构化的描述,做啥缓存,它其实就是动态规划了是吧,那么你这个这个从在这个啥缓存的基础上,如果你再把这个表的结构划分精细的话,它就是我们正常的动态规划。

我们昨天讲的以以以那个机器人问题出发,只是介绍了这样的一个概念,那是不是每一次都这样呢,是每一次每一个动态规划都可以这么干啊,所以它是一个套路问题好,那么我们来,啊我们再来想想,再来看一个什么题啊。

对背包问题,比如说我们昨天讲的,现在临时开始改背包问题啊,昨天我们讲了背包问题,只讲了暴力尝试是吧,还没有改动态规划,我们来看一下背包问题,你看这个背包问题,你可以改这个方法,对这个暴力递归也可以改。

底下这个暴力递归啊,你改哪个都行,那我们来分析一下底下这个因为底下这个足够经典是吧,你看底下这个暴力递归它就两个可变参数,这个可变参数的范围是啥呀,就是货物的数量,如果是n的话。

这个index它是指的是具体某1号货物,所以它的index它的范围是零到n减一对吧,那我们的rest是什么呢,你的bag有多大,它的剩余空间数量是不可能多于这个背包容量的是吧。

所以我们的那个背包问题呢就可以很轻,就它就可以改成二维表结构的动态规划,因为我们那那我们先关心一个问题,这个问题就是说我们背包问题在我们调用的过程中,它会不会出现大量的重复行为。

注意我们为什么一定要确定这一点,他决定了你有没有必要去改动态规划,如果你发现你你调用的这个递归过程,它这个每一次这这个这两个参数组合都是新的,那你其实就没有必要去改动它规划是吧。

如果你发现你有大量的重复问题,其实你有必要去改动态规划,因为你有重复问题的话,你改成这种动态规划,就意味着以后再遇到重复的计算,你就不是暴力展开了,你直接从缓存里面拿数据了,这是我们昨天讲过的内容是吧。

哦我问一下今天有多少同学是刚来的,昨天的课没听过,刚来的同学打个二,这咋整是吧,唉呀这个,这个那那那我没办法没没没办法重复讲是吧,那你那麻烦这些同学就是把昨天的课看一下,好吧啊好啊。

那么我们来看现在来直接就直接顺着昨天的思路来讲是吧,直接顺着昨天的思路来讲,那我们看这个index和这个rest都是多大,我们不妨举一个例子,举个例子看看有没有重复解什么例子呢,就这这个这个呃。

比如说这个这个货物啊,一个是它的index,一个是它的剩余空间是吧,那我们假设有一些货物啊,第一个货物它重量是二,第二货物重量是一,第三个货物重量是三,下货物重量是五,在下货物呢重量是假设是四吧。

这是重量的货物的数组,同样它肯定有一个价值的数组是吧,价值数组,那价值分别是a b c d e可以吧啊好我们看一下它会不会有重复解,你怎么看会不会有重复解,就是你一开始调用的时候。

肯定是从0号货物开始选择是吧,我们把固定参数省掉。

只写可变参数的表达,那么你一开始肯定是0号货物的情况下,它有它的剩余空间是多少,假设你假设你一开始给我一个总空间,比如说是20,总空间是20的大小,0号货物他剩了多少空间呢,他一开始剩20个空间。

因为你从0号货物开始选,他还没有选择,对不对,那我就看你随着你调用的过程中,这两个参数会不会出现重复解,很明显会,比如说我我我没有,我没有选这个货物,也没有选这个货物,我选了这个货物,我问你。

你剩下的过程是啥,就是你经过某一个决策之后,你会遇到一个子过程,这个子过程是我从3号货物开始选择,我之前选的是不要零,不要一,要了二,所以还剩17的空间,这是不是重复减,怎么重复了,它等不等同于你。

你要了二,要了一没要三的后续过程是不是一样的对吧,你看你如果要之前要了二,要了一,但是没要三,我问你,你接下来的过程是啥,你还是从3号货物开始,剩余空间数量是17,那么也就是说。

我们单独的用这个参数和第一个参数和第二个参数的组合,其实是会有重复解出现的,那就意味着我们动态规划搞起来有必要,因为你可以把很多重复解利用缓存的方式,以后不重复球,听懂同学打一,好啊,那么那么好。

那我们现在你当然可以,你你任何暴力递归过程,你都可以把可变参数做成啥缓存的形式对吧,你任何的时候都可以把这个可变参数做成啥缓存的形式,这个昨天我们也是讲过的,所以我们这里就不多废话了,我们直接看。

如果我们想把它变成经典的动态规划的样子,你应该怎么变呢,那就看我两个可变参数变化范围都整理清楚之后,它不就是一张二维表吗,什么意思呢,就是说我这个index是不是从零到n减一的。

实际上这个index的变化它是有可能到终止位置的,所以我就姑且默认这个index可以是零到n的,好举个例子,比如说就这个数组啊,我们现在改改,开始改动态规划了啊,开始改动态规划了。

假设这个就是我们这个货物数组,这是重量,这边是价值,我们为什么价值上都用这些东西代替呢,因为我们的递归过程里面,价值没有体现在可变参数上,所以我们只注意改动态规划的时候,你暴力递归写好了它。

它这个结构改制的方式只和你已经写出来的动态规划有关,和原始题已经没有关系了,解耦了对吧,昨天我们昨天我们也讲过这个内容是吧,就是说你一旦改出暴力递归啊,以后,你就根本不用管原始的含义了。

你就看着你的暴力递归就能改成动态规划好,那么我们先来想一下这个东西怎么改,首先我的货物呢下标是0~4,如果我们再给他补一个终止位置的话,我们为什么要补这个中指位置。

其实也是因为我们暴力递归中需要这个中指位置,你看我们这个这个递归中index是能够到终止位置的,对不对,所以既然他需要我们就补一个无所谓嘛。

也就多一个位置嘛,所以我们就想如果我们index做列的话,012345对吧,012345,那么这个就是假设就是我的index的变化,它不可能超过0~5的范围,因为它是数组中一个具体的位置。

即便我把中值位置也补上去,它也不会超过对吧好,那么我们这个列是什么呢,当然是我们的剩余空间rest,剩余空间rest,如果我们给给的初始空间bag等于20的话,初始空间bag等于20的话。

那么我们这个剩余空间它它的范围是什么,从0~20,既不可能小于零,也不可能大于20,好那么做出这张二位表之后,毫无疑问我所有的递归过程,这张二维表都一定能装下,这也是我们昨天讲的内容,是这意思吧。

好那么我们把这张表的结构分析清楚之后,我们来想一下你需要怎么填这张表。

首先我们看你主函数啊,你要的是什么位置,零八个位置的值,就是它它它在递归里面,他要的是零八个位置的返回值,那对应在这张表上。

其实你最终要什么位置的值,零bag,也就是说我最终把这张表填好了之后,我是要右上角的值,把这张表的右上角的值给用户返回就可以了,那么这是也就是说这个是我们最终想要求的位置,那我们初始位置有哪些呢。

还是看递归,首先rs小于零的时候,认为是无效解。

那你就可以认为什么整个这张表中如果rest小于零,也就是这个矩阵,整个左侧的海洋都认为是无效的对吧,这张表中整个左侧的区域都认为是一个无效区域。

好继续看,如果index等于终止位置的时候,不管我rise等于什么,请都返回零。

是这意思吧,说明啥,说明你最后一行,当我的index等于五的时候,不管rest等于什么,都等于零,好你看我们只通过b4 ,只通过递归函数,就知道这张表中哪些是初始位置,哪些是我最终要求的位置。

你通过这个结构,你就你就知道我一定是从最后一行推出倒数第二行,倒数第二行推倒数第三行,一直往上推,推到最上一行,最右的位置是我要返回的值,听懂同学打一,好所以我们就改一下这个我们就改一下。

现场改一下这个暴力递归好吧,我们哎其实底下就是啊,你看我是怎么改的啊,其实底下就是dp位啊,就是他说的是什么意思,我看你看啊高度对应的这个dp位啊。

其实就是把上面的这个暴力递归过程转化成动态规划的写法了,如果你可以一眼看出来重复解,你不用像我刚才那样分析对吧,如果你看不出来重复解,你最好还是列一下好吧啊,那个这个dp v怎么求呢,我们来看一下。

首先你看我准备了一张dp表行呢就是我index的表达,那么index我们说我们要补一个n位置,所以它的下标是从哪到index是从哪到哪,零到n那我就准备n加一行,n加一行,准备完了之后。

你不就下标就是零到n都全了吗,对吧,还有我们的rest是什么呀,我们rest是零到bag,rest是零到bag,所以准备多大的表列数。

准备bag加一,你准备bag加一,就相当于你的列零到bag都全了,对不对,但是这里面有一个过程,就是说我们先填一下什么,当我的index,当我的index等于中值位置的时候。

那就相当于dp到d p n行的任何位置其实都是等于零的,但是在java中,本来你初始化的时候它默认就都是零,所以你就不用再单独设置,说我n行所有位置都是零了,它本来初始化的时候就都是零啊。

所以看似你什么看似你没有填最后一行,实际上你填好了,它初始化的时候就帮你填好了,所以你看底下是怎么改的,接下来的过程是行,我从n减一行开始,因为n行我已经填完了。

n行我已经填完了嘛,这一行我已经填完了,对不对,所以接下来从n减2n减一行开始填,n减二行开始填,n减三行开始填,一直填到第零行。

怎么体现的呢,那就是我的这个index的变化,你看是怎么变化的,index从n减一行开始,每一次index减减,index大于等于零的情况下一直往上走,是这意思吧,所以第一个for循环其实就规定好了。

说什么其实就规定好了,说我从下面的行往上面的行依次填,那么第二个for循环是什么呢,第二个方循环是啥,第二个放循环是我的剩余空间从一开始一直填到bag,是这意思吧,我的剩余空间从一开始一直填到bug。

也就是说对于每一行来说,对于每一行来说,我是从右往从左往右填好每一行,下一行再是从左往右填好每一行,再下一行再是从左往右填好每一行对吧。

没错吧,好昨天的没有,昨天我们应该是把原来的递归改过的,所以我们现在就按照现在这个版本,现在这个版本来改动的规划,那你既然rise是小于零的情况下才是无效解,那么我现在改一下rise就从零开始好吧。

让你让你让你理解好,rest从零开始是有必要填的,为什么为什么rest小于-1小于零不需要填呢,我们base case里面已经规定了,因为rx小于零的情况下,这个-1它代表无效解,我们是不需要管的。

是这意思吧,所以这两个for循环如果你能够顺利填完的话,我们现在还不知道怎么填,假设这个蓝色部分还没有,假设这个蓝色部分还没有对吧,就假设它没有,我们只要把这两个放循环填好,最后返回谁啊。

你主你在原始暴力递归中,你需要的是零bag这个状态你最终返回数组的零bag状态就行了吗,接下来怎么填,告诉你递归函数怎么调,动态规划怎么填,什么意思,copy进来,就copy下来。

我rise小于零的时候,我已经处理了这两个,这两个for循环中不会有rise小于零的时候,index等于中值位的时候,我已经处理了这一行呢,在这一行处理了对吧,它默认的情况下帮我n行填好了。

所以你你下面的行为,他是不是就是正常位置怎么去做决策过程的行为是吧。

好你如果不知道怎么改。

你就把他们彻底copy进来就行了,然后你再改,那怎么改呢,你的目标是什么,你的目标是在任何一这,这这个只是原始的,它的暴力过程,我们想办法把它拆成动态规划,怎么拆,你for循环的index位置。

定了rst的位置也定了,其实你就是在这两个for循环里,你想办法把此时的dp index rest位置,它等于什么,你搞定,你想办法把此时的dp index rise是什么搞定。

你周而复始地跑这个矿循环,最后返回零bag不就结束了吗,这个这个底下这个代码只是我现在要提醒你说他原来的决策过程如此,其实你现在就想做这样一个工作,每一个index rest到底等于啥。

如果我能搞定他就搞定了,听懂他在打一,好那我们现在开始改嘛,可能性一是啥,我们把它还原出来,是你看,可能性一他掉了,我们此时递归过程里的这俩参数,你既然已经分析好位置依赖了,我问你。

你是不是可以直接拿了,对不对,你虽然暴力递归中的可能性,一是等于这个暴力递归里面这俩参数的组合,我们可是从底层往上层填的,我问你,你来到任何一个dp index rest的位置的时候。

你有没有dp的index加rx位置的值有,你原来是用暴力递归去掉的,你现在在dt表中直接拿o不ok啊,我超级ok啊,那就直接拿呗,第一行改好了,第二行,先让它等于-1和暴力机构中保持一样,然后这样。

然后p2 奈克斯特等于什么也拿递归做代替它应该是什么,是这个,是这意思吧,好那我问你,我是我,我如果rest减这个东西,它是一个一个小于零的值,它是不是无效啊,所以你在用dp值的时候。

你必须保证这个蓝色部分不越界,对不对,index加一是肯定不会越界的,因为你index是从n减一开始往上推的,那这个位置如果越界的话,是不是代表p2 next的无效啊,所以你怎么写,你这么写。

看一下我们是不是对应的,你原来是p2 next的过程,如果是一个无效解啊,如果是有效解,它不等于-1就是有效,如果你后面的后续过程就这个后续过程它是一个有效解,p2 就等于爱好货物的价值加上p2 的。

那你不就相当于是如果你这个位置没越界,那p2 就等于v的index加上一个有效的后续吗,然后你就干嘛,你就知道你这个位置怎么填了吗,他怎么填呀,p1 p2 取最大值,上面的改法。

上面的这种改法和暴力递归过程的求解,一码事儿,看懂同学打一,所以你体会一下我们刚才说的那句话,昨天说的是怎么说的,所谓的动态规划转移方程,它其实就是你决策过程中的那个决策。

你暴力尝试过程中是怎么组织你的决策的,他就是把它就是动态规划中的状态转移,听到同学打一,如果你作为一个老手,你可以直接写出动态转移的方法,那就说明你已经相当熟悉了,你就去直接写状态转移的解。

如果你是一个新手,你就从暴力递归开始,一步一步非常顺利的改造动态规划对吧好,所以你已经改完了,当然要把原始的去掉,来我们来跑一下是吧,这个有有dp位置,我刚改掉吗是吧,是不是啊,对不对啊。

原始的暴力递归过程算的跟dp我们刚改成那个版本等效吗是吧,溜不溜是吧,你说我我我当我写出暴力递归过程之后,我为什么可以很顺利地改出来,原因就在于我我我暴力递归的决策过程,就是我的动作,就是我的状态转移。

为什么给你推荐暴力递归的写法,因为它特别贴近于你的自然智慧,你直接把它做抽象化的状态转移,你很可能是列列不清楚的理解吧,很可能是列不清楚的,rise可以从右向左吗,可以啊,在这里面我只是想高度还原。

说跟原来暴力递归过程同样的顺序,所以我这么写的,你当然可以自己改是吧,看一下啊,啊这个这个你你就是你临时申请变量跟你提前申请好都行是吧,这只是一些小的实现细节。

你把p一跟你把p一跟p2 彻底夹到外头行不行,彻底夹在这两个方循环外头行不行,可以对此无所谓好我们就很顺利地改出了这个这个呃背包问题好,我们再改一个,我们再改一个,还是昨天那个昨天有一个讲的尝试过程。

但是没有改,就是我们这个字符串转化问题,你现在没有听过那道题的同学不要紧,没有听过那个同学的同学不要紧,我们说了,改法和你原始提议是没关系的,张三写了一个process方法,他的暴力过程已经决定好了。

李四根本不知道原题意,只根据他的暴力过程就可以感受动态规划,原始题已经解耦了,对吧,所以我们现在假设我们就看只能看到这个process过程,我们要怎么改,底下当然已经有写好了的,不用管,我们现场改好吧。

为了让你熟悉,你不用管原始t1 ,我就看这个暴力递归过程,我就能够感受他们的规划,这绝这绝非一两个体,所有的动态规划都可以这么干,好怎么改,首先你分析这个这个过程是非常简单的过程,为什么这么说。

他只有一个可变参数啊,它就是一张一维表啊对吧,他是这只有以可变参数,它就是一张一为表啊,这个这个很明显是非常好改的,你我们昨天分析的时候,虽然分析了一大通,但是在真正改动态规划的时候。

你的暴力尝试一旦出现了出来了,暴力递归啊,动态规划就出来了,好现在直接改怎么改,这为了区分一下,我们就写个dp v2 好吧,这个就是我们的dp位置二,我们要改它,我们只看上面的暴力过程怎么改。

那么我们先看一下主函数要谁,主函数要这个这个零位置的值是吧,i的取值是什么,ai可以取得中值位置,所以dp v z2 我就给他删掉,啥都没写呢,要怎么改呢,你的这个暴力递归过程符合什么样的过滤条件。

拷贝进来,对吧,这个是string啊,那就s,好为了方便起见,我把这个s给它转成呃字符类型数组的形式好吧,然后它的长度是,那么我准备dt表准备多大呢,暴力递归过程中,index取值是零到n的。

所以我就准备一张表,他下标是0~0到n的对吧,所以准备这么大一张表,那么我看暴力递归过程中,我是需要零状态的好,最后返回dp 0,嘿嘿返回dp 0中间啊,我就把这个dp处理好之后就ok了对吧。

dt怎么生成,dp怎么生成了,在n的时候它是等于一的,直接写,没毛病吧,跟原始题是什么,根本不根本没关系,你包容内鬼写出来就直接改嘛,好接下来我们想一下,我们看这个process是怎么依赖它的子状态的。

我们发现process它来到i位置的时候,它依赖的是或者i加一位置的返回值,或者a加二位置的返回值,这个也是i加,意味着返回值或者a加二位置返回值,最后的子过程也是a加e味着返回值妥了。

也就是说我在这张dp表中,任何一个i位置的值,我只依赖它i加一位的值或i加二位置的值,那么如果我要填好整张表的话,你n位置的值已经告诉你了,是一你最重要的是零位置的值是什么,给用户返回,毫无疑问。

这张表从右往左填,听懂同学打一,好那既然知道这个我就改嘛对吧。

我就改嘛,怎么改啊写嘛,你n位置,你n位置已经填好了,接下来i从n减一开始a大于等于零,a减减是这意思吧,a大于等于零,n减减是这意思吧,好那也就是说我们在这个for循环中。

我们的目标就是把dp i位置的值想办法给它生成好,如果我每一步都能够正确生成好整个问题解了,那你每一步的过程和你具体process里面调用一个image的返回值,是不是一码事儿,一码事,对不对,怎么办。

拷贝进来,直接拷贝进来,我就想办法怎么改对吧,原来是暴力递归的过程,我现在把那一行一行改成动态文化的表达,所有return的位置,所有return的位置,它就是我去设置dpi的时刻。

所有return的位置它就是我去设置dpi的时刻,听到他在打一,你在这个你看你方循环a等于n减一的时候,那么你你是单独在之前把dtn的值已经设置好了,所以这一行干嘛不要了,i等于终止位置的时候。

是你已经提前填好了的东西不要了,那么接下来他的如果spring i等于零,就return 0,那不就是相当于spring i等于零的时候,d t i的值等于1=0吗,对吧,你是return 0,直接减。

直接往上加,可以吧,然后当我string i等于一的时候,rest等于dp i加一的值好先让dpi等于他,怎么替换它,它不就已经变成dt表中的东西了吗,非常傻白甜啊,这这有什么难度对吧。

如果i加一位置呢,小于死就烂死,dp,加等于dpi加二的值,是这意思吧,改完了,接下来,二的时候result等于他好,先让dp等于他,然后你后面的过程就是dti加一,接下来这个条件一直放在这儿是吧。

然后你dp加等于,dpi加,行了改完了,来跑一下,也也也有可能会失败对吧,谁能保证你失败了,咱再看吗,原来的member方法是暴力过程,现在直接把dp我们刚才改的dp v2 传进去是吧。

啊这个看懂同学打一是吧,哈哈,有什么问题是吧,傻不傻白甜,简不简单,还什么狗屁动态规划是吧,动态规划就是这么简单,你把你把尝试过程想清楚,它,再把它替换成,再把它替换成结构化的缓存结构。

这玩意就是动态规划有什么难度是吧,好关键就是你的尝试过程,最关键的就是你的尝试过程好吧,那么,还有一个题,昨天讲过的,继续把它改动,大规划,我们给你奠定足够多的概念之后,就是这种足够多的这个信心之后。

我们再进行下面的内容,不然你感总感觉虚虚的,对不对,来昨天那个大家哦,大家看一下,这个f函这个这个这两个函数比较特殊,我告诉你这个f函数它底层递归调用了s函数,这个s函数它底层递归调用f函数。

两个东西互相嵌套,你不用管原始提议,你不用管原始t1 ,就单纯看这两个递归行为,想想怎么改,我们两分钟之后继续啊,我去抽根烟,请看一下啊,不用管原始提议,假设就是张三写了两个递归方法互相嵌套。

你现在作为李四,你怎么改他,快看看啊,动态规划最难熬的就是转移方程,要这么说,动态规划最难熬的就是想尝试过程,你为什么憋不出来状态转移方程,因为你对尝试没感觉,怎么可能别出来,状态转移方程。

状态转移方程是对尝试过程的再一步抽象化的表达,其实一码事,但是如果你没有前面的这个尝试过程的感觉,你怎么去憋出这个状态转移方程来,就是一句特别俗的话,没学会走,你怎么会跑,老师给你讲的时候,为了图省事。

直接告诉你,想清楚状态转移就行了,状态转移是个啥都没讲,就是你尝试的过程,你们尝试过程想清楚,转载转移就出来了,不是说不写状态转移,我们课上怎么可能会教你不写状态转移的方法。

后面的题会涉及到为什么我要写,最后我要写这个状态转移,因为有可能存在进一步优化的空间,但是你什么都没有,你递归感觉建立不起来,你怎么写这个状态转移,你有那个能耐吗,没有那个能耐。

就从一步一步从尝试开始稳扎稳打,你总能写出来,好好看昨天的课,还有就是,老师好像不好确定是否存在重复子问题,能不能一眼看出来,没有的话,能否也能动态规划,如果没有重复子问题,没有必要改动态规划。

我们动态规划就是为了空间换时间,你为什么要改动态规划,是因为有大量的重复解出现,你不想每次都暴力去做,所以替换替换成结构化的缓存数据以后,遇到同样的子问题的时候,直接拿答案,这就是动态规划的实质。

然后小方同学说dt 0位置没太明白,是最后的最后的总结果嘛,对dp是什么,不要把它想得太高端,dp就是暴力递归过程,想办法把所有的返回值放在一张表里,就是dp主问题,主问题要求你拿零状态的时候的答案。

你就返回dp 0,都听明白,同学打一,是否存在重复子问题,能不能一眼看出来,如果你有经验,你可以一眼看出来,如果你没有经验,你就列一下,对不对,啊真的都这么多,这么多年都是为了这都是为了啊。

好多人临时过来上课,给我憋的是吧,你看每一步一步都解耦掉了是吧,想要了解盖洛的,我们好好看,之前的课我们都是非常成体系的,讲完了是吧啊,好那我们讲我们现在看就这两个方法,昨天讲过的一个题。

你不用管原始第一,这是所有的解win一方法,我们假设我们都不知道说的是什么,我们都不知道他说的是什么,怎么改出和问一方法对等的动态规划来,腿改怎么改呢,我们来分析一下,首先win一过程中f需要什么状态。

0n减一状态,如果数组的长度是n的话,主问题里面需要的是f0 n减一状态,他还需要s这个函数的0n减一状态,没错吧,那我看f这个f是啥意思呢,我们会发现当你f调用的时候啊,l跟r是啥。

他底下s的调用的时候,l是加1r的状态,而我们第二个参数呢是s这个递归函数中l r减一的这个状态,那也就是说规模在缩小,对不对,他不可能往外头去,对不对,啥意思,我这是还要到r我依赖的子状态。

甭管你是依赖自己的f还是依赖外头的一个s,你的范围要么是l l加一到r,要么是什么,l,到l减一规模都在缩小对吧,原始的大规模是l到r我需要它内部的l加r这个状态,或者l到r减一这个状态规模在缩小。

对不对,再看s函数是不是s当我我也改成l r,你会发现s函数中它虽然掉的是f这个状态,但是它的规模也是缩小的,而而且也是缩成,要我要拿l加r,要拿l减2-1这个这两个东西好,我们昨天输了。

你发现l跟r每次都缩小范围上的尝试,所以l跟r是什么,是数组的某一个范围对吧,是数组是数组r v中的l到r的一个范围上的一个尝试,是这意思吧,是数组l的r的,你看你为什么可以这么说。

l r数组l位置的值加上一个l啊,l加r的状态或者数组rv的值加上一个l r键,也就是说你l r是干嘛用的,你的l r其实是在数组中要拿直的,那其实l和r就对应的数组中从l到r位置的这么一个范围。

而且你l等于r的时候是啥,就是这个范围上只有一个数的时候,这个l等于r时候代表啥,也是数字上只有一个数的时候,对不对啊,范围上的尝试,l的变化范围是啥,数组中零到n减一吗,范围上是啥。

也是数组中零到n减一吗,所以如果我们把f函数做成表的话,正方形表因为l也是零到n减一范围,而也是零到n减一范围,s也是一样,正方形表如果我们把f认为是一张表,s认为是一张表,就是两张正方形表。

听同学打一,好那我们就写,我们举个例子写怎么写,数组给你给你举个例子,就这个例子,f表,s表,画好格子,注意听,接下来因为你l到r它表示的是数组中的一个有效的范围,所以任何l大于r的时候。

不可能说明这两张正方形表中左下半区没用,听着他打一,任何一个范围上的尝试一定是这样的,任何一个范围上的尝试一定是这样的,然后怎么看看着他的暴力递归啊。

我们怎么说呢,f中如果l l等于r的时候,就return rl的值。

你会不会填l等于r是哪条线,这条线,对不对啊,好l等于r的时候就等于什么呢,就返回r rl位置的值,所以00问题的解释什么啊,瑞零位置的值111的解是什么,二位一位是值,72~2的解是什么。

93~3是什么,100你不用管原始提议没关系,那么跟原始题没关系,只看暴力递归过程够了。

4l等于r的时候,他不就是return 0吗。

所以s表中,这么个事儿对不对。

主函数要什么,主函数要的是f0 n减一的状态的值,s0 到n减一状态的值,好标上。

所以我的我其实我的问题就是说你怎么把两张表都推完,能拿到两个星星位置的值,这个问题就搞定了,听我同学打一,好我们看一下,那这个东西怎么推呢。

不要看互相嵌套,你位置空间感建立好之后,你就看嘛,来看任何一个f l r的状态。

问好任何一个好,我们假设一个我们不妨设就是这个星星位置,我们看它是依赖什么,假设这个星星位置就是一个普遍位置。

我们看它依赖什么,它依赖的是l加r和l r减一的值,但是是在s表中的,是这意思吧。

那是啥意思,值l加r是谁,这是l l加r是这个位置,l r减一是谁,是这个位置,但他意外的是s表中的也就这俩位置,这个星星他意外的是这俩位置,而这个星星呢我们来看它也是s表中一个普遍位置。

它依赖的是f表中l加r和l r减一的两个值。

说说明啥,说明这个星星它依赖的是f表中叉号啊,不写插好这两个位置的值,就这两个对号啊,他是被这个星星依赖的自己,f表中就是他们他们就说我任何一个f表中的位置等同于在s点点,s表中做出对应点。

然后依赖这个对应点的左边一个位置跟下边一个位置,s表中的任何一个位置都在f表中做一个对应点,都依赖这个对应点的左边的位置跟下面这个位置好,那你怎么推啊,我问你,你能不能推出这个s点的位置可以退出。

为什么,因为它的对应点在这儿,而它左边跟下边的位置都是已经具备的了,都是有的值,你可以通过m表中这个一和这个七把s表的这个位置推出来,那这个位置的值能不能推出来,它依赖的是f表中的对应点。

这左边的值跟下面的位置有七跟九,你就能把这个问号也能推出来,那你能不能推出这个位置的值也可以,这个位置它其实就是对应点f表中左边位置跟下面的位置,你有了九个100,一定能够把这个问号推出来,同样道理。

你能不能把在f表中,你在f表中,你能不能把这个问号推出来,因为对应点是这个对号的位置,它左边跟下面都有,所以这个题是啥意思,就是你用f的这条对角线去推s的第二条,用s的对角线去推f的第二条。

再用f的第二条去推s的,第三条,再用s的第二条去推f的第三条,两个东西交替往上推,推出来了,听我同学打一,这和原始题有关系吗,这跟原始题一点关系都没有,对不对,你说你自己作为作为一个新手。

你怎么可能会想到这种转移方程,你憋到死,你也憋不出来,老老实实写尝试,那这道题尝试是什么,看昨天的视频好吧。

我们现场改,杀掉五影二方法,我们这个我们把问一方法先放在这,直接改无印二方法二位传进去,二方法,你不是不会吗,我给你擦掉,可以吧,我给你擦掉,现场改怎么改呢,来看主函数,主函数前面是什么过滤。

咱也什么过滤,接下来你依赖是f过程,s过程好,两张表,二位的长度记上,f规模是他,s表规模也是他,对吧,然后看哈哈哈哈哈哈,最终返回的是他好,我明白了,返回返回这个,f0 到n减一的状态。

s也是零到n减一的状态,就我是返回他的跟我的跟我上面这个过程保持一致,具体两个公式怎么求呢,我们来讲了,如果l等于r的时候是二rl值,好甜甜甜,你这么一干对角线的所有值就等于一次等于二位i的值。

相当于你把这条对角线填好了,听懂同学打一。

第二个for循环是s对角线全是零,但你在你在java中默认初始就都是零,所以就省掉了对吧,省掉的一个就是任何一个s i i位置都是零,本来它初始化的时候也都是零,好现在开始写,我怎么去填所有的对角线。

i等于从一开始i小于ni加加什么意思。

a等于a等于零时候的这条对角线我已经填完了,i等于一的时候,这条对角线我想依次填好,i等于二的时候,这对角线我想一次填好,最后一直到i等于三的时候,这条对角线,这就是我i的控制。

那你怎么填好呢,我一上来对角线的第一个点是谁行谁行,在零位置是谁列在i位置,对不对。

合不合理,我这个i一上来来到一的时候,我问你,你对角线的第一个位置是不是零一位置,来到二的时候,你对角线的第一个位置是不是零二位置,i3 的时候,你对角线是不是零三位置是吧。

所以每一个i开始的时候,他对角线的第一个位置都是0i位置,接下来干嘛往右下方出六吗,所以怎么写,请你小于n,并且column,请你小于n,都不越界,行跟列都不越界,我你中间干嘛。

你只要能够想办法把每一个dp肉column填好是什么就行了,那肉怎么变,肉加加column怎么变,column也加,加办法把这个结构中每一个位置都填好。

这事出来了,听不懂,同学打一。

小于a吧没错,但是是我利用这种方式,肉一开始等于零,column等于i,每次他俩同步加加,是不是永远肉小于column,自然就保证了对吧,只和我代码的结构有关,它就是一个coding问题吗。

好那我怎么想办法把具体的每一个肉call那么填好呢,递归函数拷过来吗,不对,怎么想办法把每一个rocm填好,dp rocm填好,你这么想l跟r对吧,为了方便我们就是l跟r,那你把肉替换成l可以。

column替换成r可以吧对吧,保持一致,所以这个l老于安,小圆每一步填l,然后l加加二也加加,想办法填好就行了,拷贝过来怎么拷贝的拷贝呗,有什么不知道怎么拷贝都拷贝过来,这个是f啊。

这是这是f这张表的逻辑,还得去填s这张表的逻辑是吧,还得去前s这张表的逻辑都拷贝过来,这张表一个return语句拷贝过来,这张表的return语句也拷贝过来,怎么改,你知不知道太简单了,你就你就改呗。

fl r直接把他弄过去,可是这里面你把调用递归的过程替换成s表,也一样,好了就这么简单,s这张表也一样,拷贝过来,不过你把这里面递归行为替换成f表。

妥了,好了来我们来搞一下,刚才打一,大家没有听过,昨天尝试的同学不要慌,接下来我们会讲新题的啊,我们会讲新题的,那就是全虚全影的,给你讲全的问题好吧,啊我们现在来讲,我们现在来,现在重新讲一些。

我们现在讲了一个什么东西啊,就是说你讲了这么一个东西,你对于一件事情形成一种暴力递归的写法,一个题,你得先去找到,有一个暴力递归的写法,就是你的尝试,然后你要去你要分析说它里面是有重复解的。

没有重复解的,没有必要改动态规划,有重复解的,你直接改动态规划,有就是有必要改成动态规划对吧,你分开这样一个步骤之后,自然你把所有的可变参数,把所有的可变参数,如果不讲求组织的形式,做啥缓存啊。

就是记忆化搜索的方法对吧,昨天也讲了,如果你不讲究,如果你不讲究组织,这个缓存,你是不讲究组织的,你就是遇到一个子问题,他如果之前没算过递归算,如果他已经算过了,你就直接从缓存里面拿,值不讲究组织的话。

就是记忆化搜索的方法,如果你再把这个计划搜索这个缓存结构做精细化组织,这是我们经典动态规划,这是我们的经典动态规划,对吧好,那么现在就有一个问题了,暴力递归的写法,记忆化搜索的解法。

时间复杂度是什么表现,经典动态规划又是什么样的,时间复杂度表现,这个我们不妨拿背包问题来讲,背这包问题是每个货物必要和不要都要递归展开的,下货物又是要和不要都要递归展开的。

再加货物又是要和不要都要递归展开的,如果你有n个货物暴力递归的写法,复杂度多少,每一次两层展开,每一次两层展开二叉树吗,你如果把它变成缓存结构,遇到同样的问题,就不再暴力展开,用缓存法呢。

表的结构是不是就是数组的长度是n,其次bag的大小啊,所以你的复杂都是什么,一个n乘以bug,这张表的大小就是你的复杂度吗,这是经典状态规划方式的时间复杂度,很轻易就证明是他每一个格子没有枚举行为。

只是依赖有限的两个位置过这一个位置对吧,那整张表一共有多少个格子,不就是你动态规划的时间复杂度吗,你这张表有多大呢,你的规模不就是n乘bag这么大吗,他可比他好好。

如果我的背包容量没有达到一个天文数字的话,恐怕这个方法是要比上面方法要好得多的对吧,计划搜索和经典动态规划有什么区别呢,告诉你,如果你的决策过程中无枚举行为是什么,叫无媒举行为,就是你任何一个状态啊。

它只依赖有限的若干个有限的子状态,计划搜索的复杂度和经典动态规划的复杂度没有区别,你们在比试过程中改出计划搜索的方法,可以不用再改经典动态规划了,为了省时间,但是如果你的表中有一个位置。

他有枚举行为的话,要去改这个经典动态规划,原因就是我们要讲的下一道题,因为它有可能当你写出经典动态规划的方案之后,能找到一个优化,把这个状态转移继续进行化简是得枚举行为是有存在这种变得更简洁。

省枚举行为的可能性呢,我们现在还没有提,来来让你认识到这一点,但是我要说的就是,如果你的暴力递归中算在具体状态的时候,你不是for循环在枚举,什么叫不是放循环的枚举。

比如说我们背包问题问题,你暴力递归中,我问你,你有你有for循环枚举吗,没有你就不依赖一个子状态,第二个有限的子状态不对,来看我们机器人问题,机器问题也是我这个任何一个状态,我只依赖这个状态。

这个状态只是指有限若干个子状态,对不对啊,没有没有枚举行为,比如说说我们的这个刚才那个这个字符串转化问题,这个process它就依赖有限几个子问题对吧,它没有枚举情怀,它没有放循环。

刚才我们这个改只改改变刚才那个问题,它也是f函数一类有限的两个s函数,这个函数也依赖优先,又依赖有限的几个这种行为的时候。

你没有必要最后再把这个计划搜索改成进来的规划了,因为我告诉你他俩时间复杂度是一样的区别,这就是经典动态规划,只是把结构化的东西做精细的划分了,从简单推到复杂,而计划搜索的方法不关心。

就是没算过这个过程我就去算,如果算过了,我就在缓存里面拿值,只是没有组织好,但他俩调用使用送子状态,所有的这个连子状态的规模大小全是一样大的,所以等效,今天的课其实已经把这些都已经扯过一遍了。

只是今天我又给你强化了一下,听懂同学打一,搜索比动态规划空间啊,呃你单独算用,你如果把单独把递归栈的东西放进去的话,这个空间是要多一些的啊,但都是一样的,好,再把一道题真正的给你打一遍。

这道题是一道新题啊,它可以给你揭示我们整个动态规划一个比较完整的优化路径啊,再强化一遍。

但是这是一个新题了,什么题,是这么回事,是这样,是这样一件事情,其实说我有一个数组,数组中每个位置的值一个货币的面值,这种货币呢他可能比较特殊,它有一个七块钱的硬币,比如说第一个七块钱的硬币。

一个三块钱的硬币,再下一个100块钱的个硬币,再下一个可能是52,这个硬币啊很怪,再往下,同位置的面值,七一位置的面值,三二位置的面值,100,三,位置面值52,然后我告诉你。

每种面值都可以使用任意一张,七你不要认为它只有一张,它有无穷多的七可以供你选择,三也是100,也是52也是好,为了简便起见,我们认为二位中都是正数且无重复值,都是正数且无重复值。

然后干嘛给你一个钱数叫目标,比如说不等于1000,你能够用的就是这四种电池,那你用这四种面值能有多少种方法把这个1000给搞出来啊,我提议同学打个一,这最小张数不是最小张数,是问你搞定的方法数。

这个52太怪了啊,不妨写50是吧,50好,那么怎么弄呢,心怎么搞一道题的尝试方法,我会给你讲透的,我们现在在熟悉什么,我为什么要把暴力递归过程,要做一整套的优化,理解这个意思吧,下午的课去重点讲。

遇到一道题目,你到底怎么猜这个尝试,现在不妨我就给你一种尝试,你就强去理解好不好吃,接受吧,接受我的说法,同学打个一到底一道题目该怎么去尝试,怎么猜,我们有原则,有有提醒,可以吧。

现在为了让你熟悉整个套路,我们现在都在讲套路,你先接受一种我的施法,那这这种释法是什么,这种视法是这样的,这个f函数这个二位是个固定参数,所以我在这个f函数中就不把它作为参数表里的东西了。

好吧猜i rest,啥意思,就是你可以自由使用阿瑞i及其往后所有的面值,每一种面值都可以使用任意张的情况下,怎么把rest这么多钱导出,就是怎么用尔瑞i到后面所有的面值。

每种面值可以使用任意一张搞定rise这么多钱有多少种方法,不是我递归的定义,返回方法数,如果我这么定义的话,我问你主函数怎么调,当然掉f1000 了啊,1000啥意思。

根据我们的含义是我可以自由使用阿瑞零级七,后面所有的面值怎么搞定,1000有多种方法,这不就是你想要的问题吗,你同学打一,就写。

你写你现场写,为了让你熟悉,啥都没有。

别给我扯淡是吧,什么都没有,我们现场写,整条思维轨迹啊,不是水,因为这个东西确实很重要,来看最终都是正数且无从负值,请你返回组成a m的方法,数啊等于空的时候,耳朵长度等于零的时候,或者m小于零的时候。

你开玩笑吧,你没有钱,你让我找什么钱,你让我找什么钱小于零,你让我找什么,返回零零种方法,注意是方法,对不对,我们定义了啥意思啊,可以自由使用array中index出发及其往后所有的货币面值。

每一种面值都可以使用任意一张,组成rest需要啊,组成rest,多少种方法,零出发钱书就是你要的好,怎么编呢,在某一步,剩余钱数居然是小于零的状态,看两种方法,合理吧,举个例子。

你第一张面值是100万的面值,但是你要搞定的钱就是1000,只能选择不要这100万,因为你如果要这100万干了,你后面要组成的钱,他娘的是个负数,后面肯定无效,没错吧,对吧。

但你如果rise的不小于零呢,你rest,大于等于零的值,它就不会离开,如果你rise大于等于零的值,如果你的货币已经来到了二位的终止位置,返回什么,max已经来到了r瑞的终止位置了,它代表什么。

你已经没有货币选择了,对不对,那你已经没有货币可以选择了,只有你,鱼的钱数也是是零的时候你可以搞定它,找到一种方法,这种方法叫什么也不要,你已经没有货币可以选择了,但你剩余的钱居然不是零。

死活都无法搞定他了,因为你没钱了,还打一,就特别符合自然智慧,不用去纠结状态转移是什么,我做什么抽象话呀,我只要带着脑子,我他娘的找过钱,我就能写,对不对,给你推荐这种方法,对你来说是最亲近的。

而且是最稳的。

好现在想一个普遍位置,我怎么去尝试啊,我们假设是十,这我要找的钱是以前唉我特别推荐大家在写递归的时候别抽象化,咱就具象化,你就就举具体的例子,把具体例子下怎么做决策的,想明白抽象化的你就想明白了。

但别觉得自己啊,我读书人坐而论道,我就跟你扯道的事儿,你你别扯那个蛋是吧,反夫俗子,咱就还原到最原始的东西来搞,扎扎实实的啊,我问你0号货币,你怎么选,就是使用零张十块钱的时候,先调用f1000 。

我问你f1000 ,你怎么去选这种决策,或者说第零种决策是我使用当前货币,当前货币是0号位置的货币,0号位置货币是谁,是十用零张十元,我就决定了我0号位置的货币就使用零章下面子问题是什么。

轮到1号货币及其往后的货币自由选择1000,继续给我去搞定第一重决策啊,一种决策,第一种决策是我就使用一张十元啊,那问题是以往后所有的货币自由选择,怎么搞定990,第二然后选择是我就使用两张十元。

后面呢过程是1号货币机,后面四条选择,你给我搞定980,我一直没举,什么时候枚举到我使用100张,一往后的货币自由选择给我搞定的钱数是零,能够去每局使用101张十元的时候吗,别是因为肯定是无效解。

听懂同学打一,你使用101张的时候,他就抄了,它就越界了,因为负数了,啊,有不懂同学打二,给我赶紧给我发困惑,你哪不懂,我怎么去做这个尝试是吗。

你都没有return,那就认为是当有货币什么位置的货币ara,位置的货币我怎么没举呢,我去没举,数从零章开始,这个变量就叫张枚举张数,这个张数它是不断加加的,但张数应该满足什么条件啊,数乘于此时的货币。

小于等于rest,看中同学,打一,接下来是什么问题呢,假设,方法数位置等于零,要返回这个位置,每一步方法术他就把,问题的每一种情况得到的方法数全垒加,接下来在阿瑞的index加一位置去自由选择。

还剩下多少钱啊,减去你使用的张数乘以当前货币数,已经搞定的钱数,注意,因为我在for循环中,我在for循环中,我举张数的时候,他一定不会超过这个rest,就意味着子问题中rest减后面的值b不小于零。

所以我知道我第一句base case是没用的,我不可能让它自己调用出rise的小于零的样子,我是在调的时候保证的,如果你没有办法在调的时候保证你就加刚才的if,在进入一个递归过程的时候保证。

如果你可以在调的时候保证你就可以省掉某些base case,你回来打一,这是我们最省的样子,超级少七分析暴力递归的过程中,肯定是每一步都和原始提议去,这期的你不利,你不利用原始提议,你怎么组织可能性。

可能性来自于具体的提议,对不对,好我们就有了这个方法了,就有了这个方法,我们想个办法把它改动态规划,问你,你这个动态规划当你写出来的时候,下面的过程啊和原始提议有关系吗,没关系了。

好现在改dp方法index从哪到哪,零到n,从哪到哪,下面的子过程在调用的过程中,食堂b后面的第二个参数一定比主问题的第二个参数只可能小,它不可能大或者相等对吧,如果你张数是零的话,就是相等的。

但是它不可能大,这张表结构化啊,对改记忆化搜索对吧,我们跟严格根据那个顺序一步一步改记忆化搜索优化成动态规划,往下走好吧,做任何步骤,下面with一方法我们改完了,下面我们来进行。

这是process一方法,直接改计划搜索,计划搜索怎么改,改,写一个最糙版本的,没有任何结构组织的记忆化搜索啊,是吧,就是m一啊,或者说v2 ,我们就是进化错误的方法,计划搜索怎么改呢,还把这个抄下来。

这个递归方法也抄下来。

但是它的函数名改个名叫pos 2,啊这也是process 2,那啥意思,分析的有没有重复解,分析刚才那个过程有没有重复解,怎么分析,我们来看一下,货币是十,第二货币是100,下面货币是50等等等等。

你要搞定的钱是1000,没有重复解释,非常显而易见的,为什么我们举个例子,比不说用了五张十块的,你用了一张50的下标零,下标一下标二,我们来看一下,如果在之前的决策中,你用了五张十啊,你用了50张啊。

就是还有就是五张十块的和一张50的100货币没用,你后续过程是什么,你后续过程实际上是从3号位置的货币自由做选择,你之前已经搞定多少钱了,50+1张50,后面过程是九九百九十九九百900。

如果你之前做的决策,零张呃,十十块钱,我用了五张,100块钱,我当时没有选50的,我用了一张,去过程中就是从3万货币开始搞定900块钱,是这意思吧,他何不它它是不是和我当时用零张十元的,用了零张50的。

用了一张100的,子问题是一个,你看你用了零张十块的,零张50的和一张100的,是不是依然是从3号货币自由做选择,搞定的钱数是900,重复行为,就有必要往下进行优化,听说他要打一,我觉得你说的很对。

我们会讲记忆化搜索计划,搜索和动态规划还是有区别的,你听我讲嘛对吧。

你听我讲嘛,这道题就是给你这个例子好。

那就有必要改,那我们就改,来看啊,缓存出来,这个缓存是最糙的缓存,感觉很好啊,记忆化搜索,因为你之前可能学过啊,你学的完全能够整合进我的套路里啊,这个你提的问题我会讲到的就是记忆化搜索。

动态规划是划分力度上的不同对吧,细度上的不同,如果某些问题并不需要那么大的细度,其实计划搜索的方法有可能会更好,没错这道题目和我们想要讲的这道题就是说明这个这个特性。

题目二二贴纸问题就是给你说明什么时候用计划搜索的方式,反而而比用精细动态规划的方式要好,这和我们整个教学体系想讲的东西是一致的啊,还就想说这一块儿好,我们继续,那么这张缓存表,缓存表啥意思,大家想一下。

我是不是这两个参数一旦确定,返回值就确定了,垂直只和这两个参数是什么有关,和尔瑞有关吗无关,为什么,因为二位从来就不会有变化,它是一个固定参数,所以返回值只和index跟rise有关。

比如说参数组合是index等于3=900的时候,你怎么把这个答案记在缓存里,在map中我们就生成一个key,这个ke 193划线900哎,我给他生成一个字符串行不行,这是最糙的缓存形式了,对不对。

和一个参数组合我都这么给转化成这样t的形式,把它的把它的返回值继承整形存到这个map里去,就带着这个缓存我去玩,这个map扔到里面去,map对所有的cos 2过程都可见,简便起见,我们我们也可以这么想。

生成这个key的过程,可能你还要去字符串转化,我想我们可以怎么样做这个map还可以这么做,我们就生成一个二维数组dp p和这个map它功能一样,也是缓存,那么这张缓存表它应该多大就够了。

x是从哪到哪零到n所以准备n加一个空间,是从哪到哪零到a所以准备加一的空间,你原来你可以转化成字符串的形式,你也可以用这样一种结构的东西来做缓存啊里的,所以为了简便起见,我们就稍微优化一步。

变成这样的缓存结构啊,是我阿瑞点lance加一一,这么大就可以把所有返回值就装下了,我缓存就想做这么大好,你就带这个dp玩,表它就是我的第一批表,讲到目前为止,理解没有问题的同学打个一。

的决策不会受到前面的影响吗,不会这为什么。

我想让你去分析重复解,那你你第一个是十,第二个是100,下一个是50,只用五张十块和一张50,你没有去选择货币,就是零位置,一位置二位置,你得到的后面过程是f39 900,这个过程没错吧。

这你前面做了这样的决策,你后面得到一个后效过程,它和你用张十块,一张100和零张50,后面得到的同样的,从3号货币自由做选择,后面钱数是900返回,只是不是一样的,我把你之前做什么决定。

只要是3号货币及其往后搞定900这件事儿,返回值一定是一样的,和你之前具体做的决定无关啊,打个一,啊,同学会问诶,那有些之前的决定会影响后面怎么办,那是什么情况,一定是你f中你选可变参数没选对。

我问你永远用在这个f中,可能第一个参数,第二个参数,第三个参数,第四个参数,我这个参数它永远是不变的,有变的永远是后面几个参数,把后面这些参数去做状态表达,它必然不会影响吗,你所谓为了前面的过程会影响。

你没找对,如果你可变参数的组合找对了,怎么可能会有后效性问题,n皇后,你这个参数组合是什么,n皇后问题是你要改变之前选的皇后的所有状况,那么你你如果你整个棋盘是你的猜参数的话,你上面点了皇后。

其实你的可变参数是整个棋盘,这个棋盘上面点的皇后数量是点点的,皇后的状态是变化的,你的参数组合就不能够把棋盘这个东西忽略掉,棋盘这东西的状况,它就是你的可变参数,所以他们强调的一点是什么。

你把可变参数及找全的情况下,他就是没有后效性的,你所谓有后效的问题,一定是把可变参数没找全,听懂同学打一,问题同学你理解了吗,大帅同学问的是吧,理解这意思吧,啊好啊,下面我们来继续改讲哪儿了啊。

给给讲到这个讲,那么我们一开始认为,如果你没有算过这个过程,它是一个缓存表嘛对吧,所以我们认为一开始,过程都没有计算的,那么就dp中所有的位置,-1它表示为什么都没有计算呢,人设置成-1好。

所以在缓存往下传之前,先在这个缓存表中把把这个算这种状态设置好,先先认为所有的状态都没有算呢,等于-1,然后带着他去玩儿哦,dp啥意思,这个地柜里,index和rest的参数组合,算过的是没算过的啊。

t p index,b等于-1,如果index跟rise这个参参数组合是算过的,看过的,那么index and rest,它的值一定大于-1,我写这个代码一上来没算过,如果index。

它的参数组合不等于-1过程,我之前算过,我直接给你值,十否则就是没算过没算过,我们就真的去这个process 2,后面一定要把这个dp给添上,这个dp是所有子过程都可见的,这个dp是所有过程都可见的好。

接下来怎么改,你用缓存的时候,如果你没有算过这个过程,那么你真的计算出来之后,你不要忘了先加到缓存里,再返回,你有用缓存的时候,那你往什么时候往这个缓存里面加的数据呢,当然是你初次计算时。

return的时刻是这意思吧,所以return语句的时候先让dp index rest,你要return的数据,我把你这个缓存里的东西返回,这就是你加缓存的时刻,道理他也一样,只要你要return。

你把在缓存里先把他的记录加上,返回原始,你本来应该返回的值好,我们记忆化搜索的方法方法,它根本就跟递归方法特别容易改出来,是就是你没算过,你就给我继续递归,但只不过返回之前把它放到缓存里。

你再走直接算过了,直接返回里面的值,它就已经是动态规划了,专业的就有个专门的名词叫自顶向下的动态规划,所谓的自顶向下的动态规划就是我就跟我递归的调用顺序一样,我递归会怎么依赖的。

我才懒得去组织他子问题的组织方式呢,这个问题对我来讲很简单,压根不存在组织什么事儿,就我没算过,我就算我算过了,我就直接拿值听懂,先打一,是啥意思,就是你之前选择的管。

我给你讲讲啥叫后效性好吧,要扯出去嘛,哎呀这个,他们还经常在帖子里面看到了这个东西啊,意思呢,就比如说所谓的有有后效性跟无后效性,实际上是因为他没有把可在那些帖子中。

他认为可变参数和原来的具体的数据的东西是分开的,就是啥意思呢,我给你我我来给你举个例子,假设在一个大的平面里,大的平面里面我要放广告牌儿啊啊放这个这个大的平面有一个面积,广告牌的面积都是210x2的。

假设这是一,这是二,摆放广告牌有多少种不同的摆法,在这个格子里面,这是一道超难的题,我们但有机会的话,再有机会的话,在进阶班里讲,我们先讲它的什么叫后效性,意思啊,这个啊这个他他这个他这个摆法有很多种。

一被撞到有效解跟无效姐啊,这就是啥意思啊,你整个是一个空白空间,我问你百1x2的广告牌有多少种摆法,那么毫无疑问你可以这么白,然后再加这么摆,然后再这么摆对吧,这都是1x2,这也是1x2,这也是1x2。

只是这个1x2是竖着摆的,这个1x2是横着摆好,也可以,中间的一块,你这么摆,然后问你剩下的空间中还有多少种摆法,我的天根据情况是不是非常的多呀,情况是不是非常的多呀,好那我问你。

如果你把广告牌这么竖着摆,两个摞在一块儿,是他的样子,作为你的可变参数啊,它适不适合,就想把两两个广告牌横着摆,把这块占据剩下的样子,摆的方法数是一样的,它一样一样,不都占据了一个4x4的区域吗。

只要你这个东西是占据好了,剩下的空间怎么摆广告牌完是同一件事情,所以就是如果你你认为整个空间不算做你的可变参数的话,有后效性问题,因为你整个状况只要有一点变化,后面的解肯定是不一样的。

但如果就把你的这个整个空间算作可变参数,虽然这个可变参数它不是一个整形,它是一个二维数组结构,但也是可变参数,就是你这个可变参数它是一个数组,它是一个矩阵结构,我整个矩阵作为我的可变参数。

这个矩阵是会变化的,状况是会变化的,我也把它算为可变参数的话,一个无互相性问题了,所以所为了有效有后效性跟无后效性什么意思,就是如果按照如果按照我的想法,你把所有可变参数的集合做a代表状态的组合的话。

任何都是无后效性的,在帖子这里面,所谓举的很多帖子里面看到的所谓的有后效性,实际上是,但他想把复杂的这种会变的结构和别的有效参数分开,然后他说哦,你在这个上面变是有有后效性的,那他们废话对吧。

你不把它算到可变参数里,它可不就有后效性吗,听懂同学打一是吧,你们是唉,我发现有些人是真的杠是吧,我可能你真的之前没明白是吧,这么干一个事儿是不是嗯,小龙同学,你理解没有啊。

你把一个明明会影响返回值的东西给它抽出,你说它不代表可变参数,这不就有后效性嘛,对不对,我们那题是啥,我们是把固定参数不要可变参数都看成组合,那可不就无后效性嘛,对不对,啊啊啊。

这就是这就是我一开始为什么跟你说,没听过动态规划是吧,太好了,我给你讲完之后,你明明白白的懂啥意思吧啊,好吧我们继续好,那么这个东西啥缓存啊,他就是个啥缓存,怎么我这个啥缓存方法,我们改完了。

我们怎么把它改成,对说白了就是这样可变参数选对了就是无后效性的,没错啊,过程改成经典动态规划呢,就跟我们刚才分析一样,我们把这个文,搜索的方法给它组织起来就是经典动态规划,而且我为什么要讲这道题。

我们将改出经典动态规划之后,好空间感,你才能继续做状态转移的进一步优化,如果你这种空间感都没有影响,很难的好,那我们先验一下这几个方法,比如说100,50和一和130块钱,看看两个返回值一不一样。

每一步扎实一点,给我讲,累了是吧,妹子一,啊都对的,所以下面我们要改位置三,然后要组成in,怎么写的,过滤是啥,我们的过滤就也是啥,精细的表,那么精细的表,dp表的结构,记忆化缓存的方,记忆化搜索的话。

已经告诉你多大了对吧,这是多大呢,零到n所以准备n加一的空间,现在给你干嘛建立套路感,不要觉得我在废话是吧,如果你们都很强,我才懒得扯这些呢是吧,唉呀,尤其你就知道你就服了,听完这道题你就服了。

为什么我要一步一步这么扎实,根据暴力递归,我们先设根据暴力递归,我们返回哪个值零em的值行先加上,所以说我们要返回dp 0,对吧,我们把dp生成好,结束了啊,先看哪些base case,等于n的时候。

rest如果等于零,就是一,否则就是零,啥意思,n的时候只有第零列上是一,剩下列都是零,的时候只有零列上它11剩下的dp,一开始一直到in,不好意思,全是零对吧,他告诉我们行,那就搞定了,继续看。

这位置是怎么依赖的,只有第零列上是一。

剩下位置都是零,是01m位置的,解好没问题。

一位置的解,我要的是他。

一个普遍位置,他子棍子问题的时候,我发现他都需要index加一行的值。

任何一个普遍位置真的要求值的话,它都需要底下行的值,行的值无关,所以一定可以通过最后一行套推出倒数第二行,倒数第二行推出倒数第三行,倒数第三行推倒数第四行,最终推到这,我们就知道了,顺序是从下往上。

具体每一行的时候从左往右听懂同学打一。

好继续,所以,他就是等于,啊n的n减一的时候是吧,因为dn行已经填好了,大于等于零,index减减,一行从左往右也行,从右往左也行。

因为每一个位置它都它都是不依赖自己本行的值的对吧,每个位置都不依赖自己本行的值,那你从右往左算有什么关系,你这个位置反正不依赖自己左边的位置,他直接在下面一行的位置对吧,你从右往左算也成。

从左往右算也行都行,但是为了我们还是从左往右吧好吧,从左往右比较比较顺序一点吧。

所以,从零开始rise的从零开始吗,我们来看一下,好像真从零开始对吧,我们递归函数里面没有规定,那就从零开始对吧,这里面可以从零开始,那就从零开始,可以rest小于等于a没问题吧,rest依次加加。

只要我们想办法把每一个dp index rest填好,写了对吧好,那怎么填呢,把递归函数超过来,哦抄过来干啥,来看with 10位置经过累加之后retur了。

位置不就相当于最后把dp index rest的东西改成位置吗,改好了,但是具体的时候你要把process替换成dp表的内容,所以dp表,搞成index加一位置的值累加,同时减去张数,什么什么。

这一坨玩意儿我不关心业务,所以就直接这么写,保证这不越界呢,我保证了,为什么我for循环里面保证这俩相乘小于rest小于等于,怎么好,这么改完之后,我们就改出第一版经典动态规划,但是很遗憾。

每个格子有枚举行为,那他也是动态规划,它和我们记忆化搜索的方法等效,下位子三,错了,直播吃屎是吧,听懂他要打一,结束了吗,告诉你,你没有枚举行为,你都不用改这个你上面的动态规划,它从顶向下的计划。

搜索动态规划,它本质上和你从简单状态推到复杂状态是一样的,是一啊,你这里面有枚举行,为了诶告诉你,请最好还是搞成这种从简单到复杂的样子,为什么,因有些题目是有可能把没举行为省掉的,具体的技巧预处理。

以数组的某些题斜率优化的某些题,四边形不不等式的某些题是不是都没听过呀,没关系,以后会讲这道题,一枚举行为就可以优化,怎么优化的,我给你讲清楚,那我们要具体一个格子的时候,它优化了啥。

来看这当前的货币,它的面值是三,当前的货币它面积是三,我我要找我要找,块钱我在求这个格子啊,真正二维表我都给它省略掉了,假设我现在在求一个具体的某一个格子,这个就在i在某一行,它它它上面的钱的面值是三。

这是面值理解吧,这个钱面值三,我在100,我要找的钱数是100元,100圆,我看具体这个格子是怎么枚举的。

是怎没举呢,还原到一个就是你你就只能举一个具体的例子就行了,这个例子不是什么无所谓理解吧,我这里面只是用当前面值是什么,用100来举例,你自己分析别的问题的时候,你也别抽象话,你就去像话。

你随便给个例子去分析这个这个枚举行为是怎么枚举的,那比现在我看我来到index i位置。

我我找的钱好具体化,我们现在来到我们现在比如说来到地10号货币是吧,这是第10号货币,它是三块钱好,我们看11 百这个位置依赖什么什么。

你就看它子函数怎么调嘛,它依赖下面的值好。

没问题啊,第第11行的值好没问题,他依赖第11行中的哪些值。

取决于你的张数了,如张数是零的话,rest减去零张三元,rise减去零张三元。

这个格子我就依赖这下他自己直接对应的下面这个格子a的值嗯。

拿格子他还会去累加什么张张数为一的时候,他下面这一行rest减去一张,一张三元。

他依赖哪个格子,一张三元减完之后,他依赖下面那个格子100,这是啥97对吧,所以他第1y97 列的这个格子。

b拿格子,他还依赖张三元rs的减去两张三元。

再下一行是这意思吧,它还依赖rise减去两张三元,所以是94这个位置飞哦,我知道了一个格子,它意外的格子是自己具体的面值,决定了它下一行间隔多少,ab往左一直搞,只要没越界都累,加起来就是问号的答案。

听懂一打一,踢到这一步你注意看啊,问号的吧,求解顺序是啥顺序,厂里,从左往右的顺序啊,行里从头往右的顺序,我问你,你几十行的97位置的这个星星啊,是比问号提前算的,是,相信当时自己在算的时候。

他把哪些值累加了呢,非及其左边所有东西都累加了,你此时求问号的时候,你要把ab后面所有东西加再累加一遍吗,你为什么不拿a直接累加星号得到问号,因为被你省掉了,停滚快打一,二,为什么一步一步非常扎实的。

算了吧,老二没懂是吧,好那啊,没懂没懂,我们就单独列一下这个星号依赖什么,我们看一下这个星号依赖什么,这个星号是哪个位置,这个星号是19 17位置一是啥,10号货币了,你给我搞定97块钱好。

依然有一种选择,你用零张三元位置,11号货币及其网下的货币自由选择,帮你搞定97,为什么还是97,因为你用了零张吗,你用了就张三元吗,这个新号是不是依赖这个b你这个而且还依赖什么,你还依赖一张三元啊。

我们现在单独在说19 17这个状态依赖什么对吧,19 17这个月他11000张三元的情况下,后面的货币帮你搞定的钱数是什么,是不是94啊,那你97还依赖什么两张三元诶,你发没发这个星号,在当时求的时候。

他已经把b及其后面所有的东西累加过一遍了,在求问号的时候,你还有必要把b及其c都累加一遍,然后再累加上a吗,没必要了,你为什么不把a直接累加上新号得到问号,那同样你这个97在算的时候。

你有什么必要累加一变呢,你这你为什么不把94这个型号累加上b就得到你呢,同样到了你90的时候,为什么要累加一遍呢,你为什么不把91号跟这个c类加到一起,我得到一个结论,你算任何位置的时候。

都只用你左边的一个位置和你下面的位置累加到一起,搞定,二位同学有没有懂,加和是怎么回事儿,他不就是在分析递归行为中我一哪些位置吗。

这个with 3方法也一样,任何dp index rise,它依赖了后面的哪些格子累加到自己身上去分析,这个也一样,同学跟大学同学有没有懂,还有这个杰森同学。

位置四方法。

方法那怎么改,b index rest,会获得dp index加一它的值,如果,减去我当前面值的货币,它不越界,p index rest,直接获得我自己这一行,它减当前面值或并列的值。

为什么强调这样一套轨迹呢。

只是你是简单的暴力过程,对,计划搜索的方式之后,至少你可以去分析一下他这个表应该有多少,数据有多大,初步建立空间感,经典动态规划的时候,至少你已经从简单到复杂了,没有这样的过程。

可能观察出枚举行为被你替代的这个细节,让你建立空间感,每一步都图像化思想,每一步都可以用例子解决掉,不会晕脑胀,如果你没行为,通过观察或者通过技巧,哪三个观察是一方面,还有技巧。

哪哪几个技巧预处理数组的技巧都啊,斜率优化的技巧和四边形不等式的技巧我们都会讲,但是不是在基础班上,所有这些技少都是为了省掉枚举行为来搞定的,来省掉枚举行为,为什么强调整条优化轨迹。

因为我们最终逼近的那个最优解啊,一步优化得非常坚实,骗人呢,他到自己是一步一步这么优化出来的,比如说这道题。

比如说这道题,他的版本是这个with 4。

它不送你,它是怎么样一步一步优化来的,因为比较麻烦,他怎么给你,你讲这个动态规划呢,他给你憋一个动态规划转移方程,但是它的动态规划反应转移方程是他直接利用这个有限两个位置,再去少。

再去硬找它背后的决策过程给你去解释,结果你看哇怎吃的方法需要枚举大神,直接想到就是这么试,然后你就他的这种水平惊叹调,擦掉了所有的轨迹之后呈现的版本,它在为最终的版本去现找解释,你没有整个优化轨迹。

你自己憋有可能吗,听懂同学,强调一点,任何动态规划都是从最自然智慧的暴力递归出发弄出来的,出来的我们还有很多题啊,下午的继续,包括祥龙同学说的计划搜索有些时候会比,一结构的动动态规划要强。

是有这种情况的,最明显的体现就是我们这个题目。

二七老钱问题已经有所体现了,我给大家举个例子,什么例子,假设我第一个面值就是100,下个面是1000,再加个面值是500,我的一直都很大,它就都是百位数,我是百位数,我让你找的钱数是100万,好。

剩余的钱数是不是不可能在十位和个位数数字上出现不是零的状态,就是你你剩余的钱数,它只能剩余某几百几百的这种对吧,听我同学,因为你所有面值都是百位数吗,电池都是百位数嘛。

所以我们其实我们的rest根本就不会有一的时候,我们不会剩一块钱,不会剩两块钱,也不会剩三块,也不会升99块钱,但我们有可能升100块钱,但是绝对不会升101块钱,知道吧,所以我们啊如果计划搜索的方法。

他不关心你底层状态怎么依赖的,就是你真实出现一个rest,我才给你去准备那么多空间,当然我们的法是啥,我们经典动态规划的方法是啥,我们是把参数做最最细粒度的划分,是这啊,我们把参数做最细粒度的划分。

这就有可能会导致我们划分的状态有很多是实际暴力递归中用的位置,那么此时搜索的方法再吊起来,就有可能比精细化力度的划分的那个动态规划方法要快,情况下你完全不需要,力度的划分只用记忆化搜索的方法就够了。

什么你需要细粒度的划分呢,题比如我们这道题,如果他题目告诉你,他所有的钱数都不是都是百位数字,那你就直接也可以不用细粒度的动态规划的方法了,直接用记忆化搜索的方法对吧,如果原来的数组中无限制。

那你细粒度的方法,我因为它和我们计划做的方法等效,因为我对于数组的状况未知嘛。

二其实又是在说明这件事情,题目二其实就是一个非常没有办法做细粒度划分的一个动态规划,我们将下午的课给你做重点的讲述。

听同学打个一,其实蛮简单的,大家有没有发现你它规划是什么,它不就是你小时候搭积木嘛对吧,你想怎么设这几个城堡,从底层地基开始搭,想个办法把把格子推到最上层,你小时候玩过搭积木,你就知道我在说说什么。

对不对啊,满分十分,来啊,别的地方你听不到这种讲述的啊啊我们下午肯定拖堂嗯好,那我们下午再见好吧。

系列 2:P73:左神算法-动态规划 - Java视频学堂 - BV1Hy4y1t7Bo

大大家好啊。嗯。我们这周是结不了了是吧,得下周才能讲完了。我们把这个的士特斯拉讲完之后开始讲递归了,是吧?非以让你看到很多叹为观止的地柜设计是吧?然后但这不是重点,重点我们是要讲。动态规划的是吧。

你看我动态规划给你准备了9个题。这9个题说句实话,那可都不是瞎准备的是吧?就每一个题都说明一个问题哦嗯。唉。讲完地质特斯拉,我们就开始开。

这个递归了。

稍微再等几分钟。还有十几分钟呢,是吧?他,今天。哎,今天今天是母亲节是吧?所以大家可以给自己的。母母上大人是吧,发个短信打个电话。买个小礼物啥的。大家稍等一下啊,我先下点一下呃,先别点下哥。

我先把这关了。喂喂,大家好。嗯。有啊,一直有啊,开完基础班还要讲题呢,训练营一期一期的都要开起来,而且没有间断的,时间上没有休息的。也就是说你们下周我们把基础班讲完,再下周直直接讲题刷题啊。

直接给你讲题,给你做总结。另外再补一下什么线段数啊,AC自动机啊,这些东西可能都要讲了。能听到吧。嗯。嗯,好。嗯。给过PPT代码,你看一下群资料里啊有。打分的话。其实就是现场对你听的感觉进行一个打分。

然后我自己看着是吧,我自己看这些分。就是来感受一下大家课堂的接受水平啊。你可以直接向学习委员或工作人员反馈,说我讲的不好或者是。有什么别的问题啊?这个这个非常欢迎是吧?你说这个我现在讲课讲的。还行。

那都是年轻时候被锤炼出来的,是吧?你自己懂了不没没用啊,你得让。金主爸爸们会是吧,你这自己懂有个啥球用是吧?所以这个我们共同进步嘛,是吧?这不是满足一下子。

就确实看一下大家有哪些东西有没有感受上面有没有什么不好的是吧?我们保持沟通,别突然间一直都不统计。然后你突然间哎,那个货他妈讲的有点也不行,我去骂他是吧?你这别有有反馈机制,对不对?

每节课你都能提意见吗,是吧?嗯。😀啊,哈呵。😊,还有还有些人啊,这我有的时候换一个用户名,各种回答算法问题。有的同学说。哎,左老师,我看他有个逼是吧,他冒充你的讲法,在那讲写帖子。后来我一看不好意思。

那个逼他就是我是吧?嗯,这个。这个也会出现这种尴尬的现象,但是。谢谢大王最热心,你说?😊,嗯。嗯ん。嗯。稍微再等一会儿啊,马上开始了是吧?我觉得这节课能够把。能够把这个迪的特斯拉讲完。然后再把。

递规讲两讲讲3到4题就很不错了啊。然后我们下周就直接进入递规收尾以及动态规划,给你做一个系统性的打底是吧?所以打底就是基础知识的建立。那么我整个动态规划,我计划用。

大两节课啊两节半课给大家说说的清楚一点,就5个小时吧,对吧?这个是。我可能还会给临时加一道题是吧?这都是很便于你理解的那种例题或者是很经典的题啊,让你理解什么叫动态规划,好吧。嗯。

今节课上完能面字节跳动吗?我觉得没问题。我觉得没问题。但是你得保证你都吸收了是吧?这你说你刚上完课老师是吧,我我听完你的课之后,我明天就要面字节跳动是吧?然后你告诉我没问题,我要面不上。

我过来骂死你是吧?别别别是吧,这个你还是要吸收一下是吧?刷le的 code啊各给大家提一点建议啊。这个把录像看开。这个大家刷刷力的扣。就是。你你自己在刷的时候,你至少要保证40分钟独立思考。

然后去写代码的时间。然后是40分钟,毫无毫没有任何头绪。他那个lead code不是有那个讨论板块吗?你找讨论板块投票数最多的回答,那里面大部分是最优解。你就看一下人家怎么写的是吧?

然后你就找到一些启发的点,然后把它学会。当然,不得不承认的是,即便是lea得 cold的投票最多的帖子,也有很多不是最优结。但是我看基本上。七成以上它是最优解啊,七成以上它是左优解。所以你就看就行了。

我的课上也有很多dd code上帖子里面讨论,根本没讨论出最优解的,只是一个优良解。但是我找到更好的解,我会给你讲啊,但是刷一 code大体的一种技巧,就是说你总你总得给自己留出一些。自己想的时间。

不然的话,你其实一直在背思路,这个其实非常不好啊,你至少要一个人折腾个40分钟,半小时到40分钟,自己去写一写啊,没有任何头绪了,你再看答案就会比较好是吧?嗯。

他那个他那个lea code上面的那个讨论板块里。投票数很高的那些回答。其实他的他的算法就是说能够保证你lea the code的测试的t case能过,它未必是最优解,但是已经足够优良了是吧?嗯。

这种还是非常值得学习的。然后你要是你要是面算法工程师啊,你这个你不仅要掌握我现在讲的这种基础算法。你还得去掌握算法工程师所自己所所所需要具备的,比如机忆学习跟数据挖掘的那一块的知识,对吧?

这个它属属于我我我在课上讲的只是基础算法,就是你不管在面什么岗位,只要你是写code的,你都是需要会的这些问题。但是。你比如说你去面图像算法工程师,那你至少要把图像算法专项领域要搞搞清楚吧,是吧?

你比如说你去面机学习数据挖掘,那你至少把概率型算法那些什么模型这那的是吧,你得搞清楚吧嗯。哦哦。进阶课多久能上完?说句实话,这个。现在我目前为止计划的进阶班已经到三期了,我正在做PPT也正在备课。

也就是说每一期的进阶就是我们基础班上完之后,要接下来讲进阶班,进阶班所谓的就是训练营也不分的是吧?如果遇到一些经典的基础知识,也比如说线段术,一些比较高端的数据结构,我会给你现场讲给你练题。

如果要是没有分类的呢,那就是高频题目直接给你刷,就都放到训练营里。基础班讲完之后直接讲开始讲训练营,没有中间没有休息,就是这周上完,下周直接来,就那种是吧?那么你像这个这个训练营能够开多少期。

其实可以非常多期。但是基基本上会把我要讲的技巧集合讲讲完。就是前两期训练营就能讲完,后面几期训练营就是在不断的强化我们学过的基础知识的敏感度。这个练习。我之前也讲过这个问题是吧?你会了基础知识。

你不一定把能把题解出来,原因是什么?原因是因为你对这个东西可能不熟,或者它应用场景没有体验。甚至有些题目你会发现特别天外飞仙是吧?我靠,他怎么就拧到这个结构上去把它解决的。这就属于敏感度的问题啊。

这个东西其实大量是靠练习的,但是通过我教的话,也可以让你建立感觉啊。所以回答你说进阶课多久能上完,可能永远也上不完。但是对于你要熟悉的面试过程中的所有技巧,其实我们三期班就已经觉就已经能够让你。

得到刷题的过程中需要的得到的所有技巧了,这个时间差不多是。再过两个月。再过再过两个月一个月吧。对,再过一个月。那么我们这个训练营的两期也就讲完了,对吧?再过一个月训练营的两期也就讲完了。

技巧级就给你挖空了。啊,以后你再遇到什么陌生算法,对你来讲就属于一种专项算法了。比如说啊这个啊我已经了解了二叉树了,我了解二叉树的地归套路了,我了解KMP了,我了解mynaature了是吧?

我这些我都了解了。就哪怕以后你面对一个陌生算法,比如说AC自动机。那你通过自己读帖子,你是完全可以理解的,理解这意思吧?啊,就是他对于你的学习上不会有任何的障碍了,就达到这种水平。

当然我们课堂是讲AC自动机的啊,我们课堂是讲AC自动机的。😡,我只只是举个例子,以后再遇到小的一些算法的小小模块啊,临时遇到一个很小的算法,其实你可以理解它啊,你说这个算法这个世界实在是太多了。

我要是都跟你讲尽,其实。可能我们讲一年未必能讲进是吧?但是你面试的技巧集合其实是有穷尽的啊,是有穷尽的。比如说我我很多很多很多开这种算法班的老师,他可能就是就只关注那点一亩三分地,其实很就已经够了。

比如说我跟你去扯一些蛋,大家都是都搞全前端框架是吧?某著名的前端框架叫react,有多少同学用过?这里面。这里面有个核心技术,对吧?这里面有核心技术,就是你浏览器在刷新的时候。

它怎么判断你哪个组件刷新了哪个组件没刷新的,它有个时间窗口去刷新你的前端的渲染,对吧?这里面他用到什么算法了?我告诉大家两棵二叉树的编辑距离问题。😡,巨他妈难的一个算法。

而且华人在这个中国人在这个算法领域是非常强的。比如说周那个张氏算法,周莎莎算法,这都是我没有在湖边,你自己去查论文,都属于两二叉树的编辑距离问题,研究的非常牛的人。😡,你需要去搞到这么专专精吗?

你不是这个领域的专家,你根本没有必要搞,难道这些我都给你讲吗?那是不可能的对吧?所以我们就用最功利的想法,面试的技巧集合是有穷尽的,算法本身是无穷尽的是吧?😡,嗯。可能同学你不你不玩这个react。

你都不知道我在说什么,是吧?😡,然后再给大家报个黑幕是吧,这个。也不是黑幕吧,是吧,自己发现了一些小点react当时出来的时候,他号称自己是吧?在一棵树里面编辑代价能够B个ON,实际上并不是。

它是一个B勾N平方的算法,而且很丢人的是facebook搞这个react的框架,它底层的算法包是google的人给他写的4000多行的一个大文件里面用到的所有算法,google人帮它写好了。

facebook人用这个算法包,对吧。哎,你跟我扯什么淡啊,是吧?你都是千年的狐狸,跟我聊什么聊斋是吧?你自你自己写嘛,对吧?你让co狗给你写什么,是不是啊?😊,嗯。嗯,然后。算了,不说了。

有早些年跟re开发社区的人有过撕逼是吧?完了没思过我,他们就选择不理我是吧?嗯。好吧啊,这个这点掐了别播啊,这样得罪人啊。好啊,这个。

啊,我们来讲这个都到了吧。来,我们来讲迪确特斯拉算法是吧,这个啥意思?说白了呢就是。在一张图里。这张图。必须要求边的全值不为负。而且是其实有像图无像图倒无所谓是吧?你可以认为是有像图。

也可以认为是无像图,这都无所谓。你我我举个例子,这样一张图。画的有点猥琐是吧?嗯,做了这么多年老师,但是说句实话,这个板书啊真的我就看完我都想掐死我自己是吧?好,那么假设A到B的全值是一。

A到C的全值是7,A到D的全值是4。B到C的全值是2C到D的啊,咱不说这个4是吧,不说这个4。觉个也可以。然后2到C到D的全值呢呃。这个这个不是别人46啊。然后C到D的全值呢是2,然后B到E的全值。

这条边是170。C到E的全值这条边23D到E的这条边全值是。4。那么这样一张图呢,它就是一个。没有全职没有负数的一张图,对吧?那迪士克斯拉解决的是什么问题呢?

迪士克斯拉想问你的问题是你必须给给我一个出发点,迪斯克斯拉一定要给我一个出发点。比如说对A来说。我的出发点就规定好是A,当然你也可以规定它是C,它是B或者D什么无所谓是吧?

总而言之就是他要求的问题是我这个出发点到所有节点的最短距离是多少?求这个问题。那我们知道这个客观上来讲,它的这个客观上来讲,我们先不设计算法,我们就用肉身来看。那么你。A到A的距离肯定是零嘛?

对吧那么你A到B的最短距离是一嘛,那么A到C的最短距离应该走怎么走呢?从A走到B是一,从B走到C是2,所以A到C的最短距离应该是3,对吧?然后A到D的最短距离,你你你可以从这走到6。

但它没有从从从A跳到B,再从B跳到C,再从C跳到D这样省,因为它这样全值是5,对吧?然后我们看A到E的最短距离是多少,应该按道理来讲是从A跳到B跳到C跳到D再跳到E是最短的。

这样的话它的全值就是5加4就是9嘛。好,我最终想要返回这么一张表。就是我敌着特斯拉想要完成的工作啊,你必须给我指定一个出发点。然后我告诉你在这张图中,这个点到所有节点的最短距离是多少。

如果这个点无法到达某一个节点,那就说它最短距离是正无穷。😡,在我们这个图里面是都能到达的,但是有些图里面可能到达不了,尤其它是有像图的话,真可能到达不了,对不对?😡,那就是说他那个距离是正无穷。好。

理理解迪克斯拉想做什么,同学打个一。😡,好,有的同学这个。祥龙同学其实他这个已经比较高端了是吧?在说的这个这个问题,的克特斯拉跟商旅问题有什么区别哈。在在这里面商旅问题我们是会讲的。

而且商旅问题非常的难。商旅问题属于动态规划里面顶级难题的那一类。就是我们日常说的那个TSP问题。那么给大家先博文强制一下TSP问题是说的什么意思?TSP问题指的是。我。我有一个旅行家。

或者说我有一个邮差,我一定要走过所有的城市,最终回到某一个城市。就是我我规定我我从一个城市出发,我最终一定要回到这个城市。但是沿途所有的城市只能经过一次。请问总距离怎么最短。

和我们迪列特斯拉完全是两个问题?😡,呃,大家听明白两个问题,不同的同学打个一。啊,TSP问题指的是我一个我我我从呃就就这。TSB没是这样的啊,就是。😡,我认为我的图一定是全连接。😡。

就比如说我有N个节点,我随便一座城市到剩下的N减一个节点一定有路。😡,这是他一个前提,就是我商旅问题就是我我认为所有这整张图是全连接的情况下,我从一个城市出发。😡,转一圈回到原城市。

但是沿途的节点只能经过一遍问你最短距离是多少,这是TSP问题要解决的问题。😡,啊,除了出发点,最后要回来之外,中间的剩下的所有点都只能经过一次,怎么样距离最短?😡,嗯。啊,那TSP问题指起点需要指定吗?

大家想一想起点需要指定吗?TSP问题是你转业圈最后回到这个点。😡,它不就是一个环嘛,对不对?你不管指定城市是哪儿,这个总距离肯定是不变的。所以TSP问题是不指定出发点的,因为没必要,因为它本来就是个环。

😡,听明白他们来打一。啊,这个这个问题啊,我们留在这个动态呃,不留应该留应该绝对是留在这个训练营讲的啊,绝对是有留在训练营讲的。而且说句不客气的,我现场手撕TSP不会出错是吧?

这是在是在某次上课的时候是吧?这个电脑死机了是吧?突然间换一台新电脑给大家讲TSP我操,没有代码,自己现场手撕,还写了个对数器过了是吧?现在想想我操,真是。哎,要是我现在讲课。

我绝对不这么干TSP问题太容易出错了,是吧?现场首次能过的也都是运气是吧?运气。😊,这个装了个逼是吧?好,我们来讲回这个迪J特斯拉算啊嗯。那么我们我们呃说一下这个这个算法。

其实这个算法在流程理解方面也是很简单的啊,也是很简单的。我们来现在来展示一下它怎么做啊。你要注意我为什么规定没有全值为负数的边,这个它是一个设定啊,因为它这个全值为负数的边出现啊。

它就意味着你有可能有全值为负数的环啊,啥意思?你比如说我正常来讲一个一个东西它走向B是吧,B走向CC走向回来了A。我这是三,我这是2,我这是一的话,你说你A到达每个节点是不是有唯一的最短距离啊?

对吧我A到B的最短距离是3,我A到C的最短距离是5嘛,只能从A跳到B再跳到C嘛。😡,对吧。如果你说你有一个负数的环,那就那就那这个问题就没有答案了。我这是负7,我越赚越小越赚越小,我是不是富无穷了?😡。

对吧你就先转个100万圈,然后你再到达B100万圈不够,你再转个1000万圈是吧?😡,这是这事这事儿就没头了,理解吧?所以我们迪丽特斯拉用的一个潜台词,就是你不能有全值为负数的边。

这是一个这是用迪瑞特斯拉的一个常见的设定啊。当然也有的同学说,这个哎我可以要求有全值为负数的边,只要我没有出现全值为负数的环不就行了吗?对吧?你比如说这个A到B它是-一,但是B到C呢,它是2。

然后A到C呢,它是5,对吧?我没有出现全值为负数的环,是不是也可以求最单元最短路径问题可以,但不是dele特斯拉。😡,叠特斯拉就要这个算法能够执行的前提条件就是没有负数的边。虽然说没有负数的环。

我是可以得到一正确的答案的,但不适用叠勒特斯拉做啊。😡,好,这么多设定是吧?加了好多的定语,那都是为了让我们的思维更加的严密一些。有一张表,一开始先有一张表。这张表完全是对A负责的。

一开始这个张表里面只有一个记录,那就是A到A的节点距离是0。没毛病吧啊,一开始这张表里只会有一个记录,A到A的距离是0。那么A到B的距离就认为是正无穷,A到C的距离就认为是正无穷。

A到D的距离就认为正无穷。A到E的距离就认为是正无穷。因为我现在还没有开始走嘛,我就是先认为你们都不可到达。😡,可以吧?好的,也就是说你一开始先在这张表里面增加一条记录,叫A到A的距离是0。

剩下A到所有的点的距离都是正无穷。接下来。在这张表中选一个最小的记录出来。就是他。好,我就选了A0出来。A0代表什么意思呢?代表我从原节点出发到此时的A距离是0。那我就要看从这个A。

当前的这个A还能跳向哪些节点?我就会发现我从当前这个A啊。我可以承受一个一的距离去跳向B,也可以承受一个七的距离是跳向C,也可以承受一个6的距离去跳向D。是这意思吧?我A到A的距离是0。

所以我如果通过当前这个A往外跳的话,我就可以更新原本的原节点到美到BCD的距离了。我原来是正无穷,现在我通过A的跳转,我也找到了一个0加一的距离。那就是一。我再通过当前A的跳转。就是0加7的距离。

那就是7。我再通过这个A跳转,那是0加6的距离,那就是6。因为这个桥联点的出现,导致我。原来到原来原点出发到BCD的距离是都是正无穷,现在他们变成了176。好的,结束了。关于这个记录就使用完了。好。

你要注意,当你使用完了一个记录的时候,他在表中永远别碰它了。他在表中永远别碰他了,他被锁死了,这个玩意儿永远放在表里,但你别动它了。😡,然后你再剩下的。😡,记录中再选一个最小的出来。B1。

那B一是什么意思呢?从原点出发到达B的距离是一。然后我再以B作为桥连点往外跳,它能跳出哪些呢?它有一个走向二的距离是到C的,有一个走向170的距离是到E的。我就看我这个桥点点的出现。

会不会更新表中的某些记录。因为我从A跳到B这个调梁点,它是一的距离,而我从B再往外跳到C的话,是二的距离。所以我从A到C的距离就有一个三的距离了,一加2对吧?这个一加2嘛。

它是不是比原来我一我我从之前的调梁点跳到C7的距离要好啊,所以就更新。😡,如果它没有变得更小,就不更新。那我就可以把七这个距离就变成3了。这个三是怎么给我的?是通过B这个桥连点往外跳跳出来的。😡,好了。

我们再看B这个桥联点跳到E呢,它有个170的距离。那么我从A到E原来是正无穷,现在就能多少?A到B的距离是一,再从这个桥梁点往外跳,就会得到171,对吧?好,更新它,因为它正无穷。然后B的工作就完成了。

擦掉。你使用了哪一条记录,你就在表中把它锁住,以后再也别碰它了。再也别碰他了,既下来你再再在剩下的东西里面拿出最小的记录来C3。C3什么意思呢?就是你通过原点出发跳到这个C的桥梁点,最小距离是3。

我再看看从这个C以它桥梁往外能跳多少。两条路,一个是我通过二的距离跳到D,一个是通过23的距离跳到E。那我来看一下有没有更新最短距距离。我原来通过别的桥梁点跳的是A到D的距离是6。

现在我通过C来跳转的话,A到C的距离是3,它跳的距离又是2,所以3加2等于5能够更新这个6,我就更新。我们再看原来我到A到E的距离是171,我不知道是之前哪个桥梁点跳的,我也不关心是之前的哪个。

我现在就关心现在的,现在呢是A这个桥梁点往往外跳,E是23的距离,而我A到C的距离是3,所以更新成26。😡,使用完了使用完之后,同样道理。你把使用过的记录画个框,把它锁住,永远别再用它了。

最后通过D往外跳A到D的最短距离,现在是5,而D往外跳只有一个四的距离能够跳到一。所以A通过这个桥梁点往外连到E的话,是得到九的距离,是不是比原来的26要好?是的,所以它变成9。使用完之后。

把它的距离锁死。最后你把E9拿出来,它没有办法往外跳好,那把它锁死锁死之后的记录就是迪J特斯拉要求的每个点到所有点的最短距离。😡,这就是算法,听懂先打一。这就是所谓的迪士特斯拉,它它在实现方面真的。

我们先看一种。跟贪心有什么,这就是贪心哼。😊,这就是贪性。中间过程也要做记录吧,如果有相同的呢,如果有相同的选谁都无所谓。你如果有相同的,你可以不更新。如果有相同的,你可以不你可你你你可以不更新。啊。

啊,注意啊,你整个图是没有负数的边的,所以这么跳它一定是对的。呃,直接深度呃呃,这个翔同学,我要是问问题很好。你深度优先便利,如果你能够还原深度优先便利是可以还原出所有的之路的。😡。

你用一个暴力的深度线变历是一定能够求出答案的,但是它不会比迪迪特斯拉好啊。😡,对吧。什么问题都可以用深度优先解啊,你深度优先走过所有之路,那必然是可以啊,对吧?但是它它就是它是一种相当暴力的解法了。

而我迪士特斯拉可是根据每一个拿最优的桥点点往外跳,看能不能推出下一步的最优来搞的呀。😡,是吧。😡,哦啊。啊,那么。这个这个这个算法呢,我们怎么实现啊?先给大家展示一个特别容易理解的实现。

然后我们看能不能改进这个这个改进可太值得说了,是吧?

现在先看一下迪克特斯拉一啊这个。你看我返回的东西是啥呀?哎,我我必须指定出发点,我给他改个名是吧?别head了,容易跟那个二叉树的点的名字重有歧义,这叫from,好吧。出发点就叫from。

我必须指定一个出发点。😡,你告诉我他到所有点的距离是多少?😡,那么。我当时就返回一张表。这个点。这里面是啥意思?他一律这张表啊是对from来说的对吧?一律这张表一定是对from来说的。

就是你能找到的每一个点到from的距离是度,最短距离是多少?如果某一个点在这个map里面没有记录,那就说明距离为正无穷。可以吧啊,如果某一个点在这个表里面没有记录,那就说明from到它距离为正无穷。

可以吧?啊,好,那么这张表我们要生成,我们现在就开始看这个叠列特斯拉算法了。首先有一个distance map,这就是我们刚开始那张表。😡。

刚开始我们是哪张表呢?😡,这张表啊就是里面只有一条记录A0的那张表。对吧这就是我们的distance map,这里面是哪张表呢?只有一一条记录A0。那为什么剩下的没有记录呢?没有记录。

你就认为它距离是正无穷嘛。😡,是这意思吧?啊,这张表一开始只有1个A0,这张表没有的点,就认为距离是正无穷,还没找到嘛。好,所以。😡。

这个dc map就是我们现在要玩的这张表是吧?我们依次要把它生成好。😡,他一开始from。到 from的距离为0,这肯定是显而易见的。

是吧注意看这个东西是啥?它是一个哈希表。哎,你们还记不还记不记得我们刚才说的时候,哎,我们当我们用了一条记录之后,我们把这个记录给锁住,对吧?再用下一个记录之后,我们再把这个记录给锁住。

我们是不是有这样的操作呀?那么怎么实现锁这件东西呢,我们就可以设置一个set嘛,如果里面有A这个节点,它就说明你这张表里面A的记录就被锁了,你永远不要再更改它,也永远不要再使用它。

所以我们利用的是这个set的机制,set里面有某个点,就认为它的记录在distance map里面被锁了,对吧?如果这个set中没有这个点,那就说明在它它的记录在distance map中没被锁。

所以怎么实现锁这件事情,就是我们这个用一个哈西用一个哈西表,我们看这个名字也很直白,叫已经选择过的点。😡。

或者你可以认为已经选择过的记录,这个点呢就会放到这个选择过的这个列表里去,是吧?这个set里去,那一开始肯定是我什么记录都没有被选是吧?哪怕from零我也没用到它呢,所以它这里面一开始就是空嘛。

啥也没放。然后注意。这个方法你不要看着很唬人,我靠,这个方法这么长,大家看一下啥意思。😡,得到最小距离。但是呢要是没选择过的点中的最小距离。第四次map。和这个参数啥意思?

就是你便利distance map。😡,但是你如果是选择过点的记录,你不要便利,你把没有被锁的记录中把最小的。😡,最小距离的这个节点给我拿出来。你看我们这个方法怎么实现的?😡,你看啊看着很唬人。

实际上巨简单。😡,这张ds map对吧?我有哪些点已经它使用过它的记录了,我就会放在这个touch的 nose这个这个这个这个东东西东西里,它其实就是我们slect node是吧?名字不一样而已。😡。

然后接下来我们干嘛了?我们便利这张dsance map表。一定要确保哎,它是之前没有是之前没有被选过的点,并且它的距离要最小。我们把这个点抓出来返回。所以我们看我们有这个方法之后。

也就是说哎disistance map中哪些点没有锁过,你就把这个最小距离得到的点给我,我就使用它。那你一开始就会把什么弄出来,必然是from。对吧你一开始得到这个minote的是谁。

那一定是from自己啊,因为它只有一条记录,就是from0,是这意思吧?是这意思吧?好,让后我们来看。有了这个min node了,干嘛?有了min node,我当然就能把整个记录取出来。

在distance在distance map中把这个min node它对应的记录取出来,就是distance。那么此时这个min node和d,就是我们所谓的刚才在例子中举那个桥连点。

对吧比如某个桥点点X原节点到你的距离,假设是个1,你再通过你往外跳,那么这个X就是此时的min node。那这个十呢就是我找到此时的distance啊,我从原接点from点,我我不知道是怎么连到X的。

但是我知道最小距离是1啊,然后再从X从过桥连点往外跳,是这意思吧?😡。

好,那么这个minn呀。minode怎么往外跳呢?大家看一眼min node它上面拥有的所有的边,我要去枚举,没毛病吧。比如说你为什么一开始的第一条记录是A,会往下找到D,找到C,找到D呢。

原因是因为你上面连着三条边一这条边七这条边,六这条边没问题吧。好,那么我就去枚举当时当前min node出来的所有的边,它们跳往下一条的节点呢?就是to node。

那我就要看一下了。而如果在distance map中,它就没有关于to node的记录。那说明啥意思?说明之前出发点到这个凸 no的,它是正无穷。对吧他还没有发现过距离。那此时你有什么好说的呢?

你就见上它的距离嘛,因为你是找到的第一条路啊,对吧?那怎么建这个距离呢?从from点到min node的距离,最小距离,加上此时你你现在以minode做桥连点往外跳的这个长度。😡。

相当于就是我第一次发现这个to node的时候。我就在第四次 map中啊,把这个to node的记录给它加上。那否则是什么意思呢?否则就是之前你有过记录,那我怎么办,我就看看能不能更新你的记录。

看怎么更新的。我在第 map中之前之前跳出过你啊,你之前有一个距离啊,对吧?现在呢老的距离就是原本to no的那个上面的距离。那你现在的距离是什么呢?

现在的距离是distance加上我这个作为当前这个桥联点往外跳的这个长度,取最小值来更新distance map。😡,呃如果老距离更小,实际上你的效果就是你没有改,只有说新距离变得更小了。

我的to node的距离才会改。😡。

那我把min note上面所有的桥连点都跳过一遍,是不是该更新就更新,该新建就新建了,对吧?然后干嘛?min note这条记录是不是被我使用过了呀?

我要当然要在已经选择的点中把minode加上以后再在distance map里面找记录的话,你自动给我pass掉它的记录。相当于画个框,被我们给锁住了。😡。

那下一步的minode的是啥?再在dsens map中找到没有选择的节点里,没有选择的节点里最小距离的点拿出来周而复始。最终dsance map一定能够更新成全对的样子返回。听懂他打一。嗯。Yeah。

这是为什么不只选择un selectlect node,确实只选择select node呀。你这个就这个就相当于你的黑名单。😡,理解吧?你给我第四次map,我再给你一个黑名单。

请你把黑名单里面的东西自动过滤掉。黑名单里没有包括的内容给我选出一个最小的距离返回。😡,听懂啥意思了吗?听懂同学打个一。😡,我要看一下这个方法,它就是黑名单的意思嘛?来看。

一开始minno的为空找到的最小距离为系统无穷大哦,这个这个整数最大值。我在便历记录的时候,我在便历这张哈希表的记录的时候。必须啊必须是没有碰过的点,你看。没有。没有碰过的点。

对吧并且如果此时发现你当前的distance比我之前找到最小值还要小。好,那就更新你你你现在就是我整个记录中的minode,我遍利这么一个放循环之后,是不是该了这两个变量就更新好了呀,对吧?

然后把minode返回嘛,这玩意儿是干啥用的,这玩意儿不是说在它里面选,是它是黑名单,不要选它里面的东西,理解吧?😡,我觉得写的蛮直白的,是不是?😡,唉。哎呀,为什么要求最小啊?

这这不是迪着特斯拉的算法吗是吧?啊,为什么要求最小?这不第一特斯拉的算法吗?迪一特斯拉就是你先在最小记录中桥点点跳一遍之后,看能不能更新出来更小的,然后再再选一个最小的理由之后,再能不能更新个更小的。

这迪斯特拉算法如此,对吧?好啊,那我们看啊这多余的闲拔中西也不说了是吧?迪于特斯拉就是这么一个算法。那么我们看一下这个。那你像这个题,它。

我觉得有些同学可能会需要一些简单简单的证明是吧?你为什么这这样一个策略能得到系统最小呢?啊,能得到所有最小呢,那你就证明一下嘛,我们就。

用还是用一种比较直白的理解方式来证明他。你比如说你A吧。你要当我说A到D,它的距离是100的时候。如果客观上存在一条更短的路径,能够使A到达D。而且是比这个100距离要小的。我们的着特斯拉是什么算法呀?

是A先往外连的最短距离,你给我。😡,再由他去跳桥连点。对吧这个100一开始A到D的这个100这个距离会留着。但是如果你真的存在一条更短路径的话,我们的算法是我A它的它到它的桥梁点的最短。

先去结算这条记录,再由它往外跳的桥梁点选一个最小跟整体选一个最小,对吧?😡,你你如果真的存在一条客观上到第的最短路径的话,我们迪克特斯拉这个算法一定能够逼近到这个地。😡,我已经贪心证明。

严格证明可能就变成了回字有几种写法那种在数学语言上极度精确那种证法了。我相信大家不会愿意听的。但是你可以理解说,如果我真的存在一条更短路径的话,我这个算法是可以帮助我找到它的。

你不就是每一次选最小桥连点往外跳嘛?不就这么回事吗?你又没有全职为负的边,这个算法没问题啊,听懂条员打一。😡,对吧。好嗯。哦,我感觉到很多同学问问那个那个疑惑,是因为这个证明问题是吧嗯。😡,嗯。好啊。

那么我们现在看一下这个。他他为什么需要改进?😡,原因是。你每一回是不是要便利好多距离选出一个最小啊?对吧我们来举个例子。比如说你A,我们现在换一张别的图啊,A到B的距离。9A到C的距离。7A到D的距离。

3A到E的距离14。一开始这张表中啊。只有一个到A到A的距离是0。然后你把这个桥梁点拿出来之后,A0这条记录,你拿出来之后,你就去跳吧,你跳出个啥到B的距离,9到C的距离7到D的距离3到E的距离14。

然后为什么这个这个这个需要优化呢?因为我每一次选最小值,我是便利这张哈希表的。😡,不够快,对不对?😡,但是大家想象一下,如果用堆呢。用堆啥意思?搞一个堆。来。这个堆是个小跟堆,就拿距离做小跟堆。

是吧就拿距离做小跟堆,这个小跟堆。这个小跟堆啊一开始只有A0这条记录。然后把这条记录弹出来了,对不对?😡,A0这条记录弹出来了,然后我去做桥联点。😡,A到B的距离是9。

那就写一个A到B的距离是9A到C的距离是7。哎,小跟推会自动帮我组织C放到这条记录放在上头,对吧?A到D的距离是3,所以小跟推会自动帮我组织到D的距离是3A到E的距离是14。

所以小跟推会自动帮我组织E到14,你感觉很爽,对不对?我靠,这样好爽啊,我下一回选最小距离,直接从小跟堆里拿了。😡,但是这个小跟堆它比较特殊,它为什么特殊?😡,比如说你以C去做桥联点的时候。

它到E的距离有一个E的距离。你说你会。😡,啊,不好意思啊,这个先弹出的是D的距离啊,对吧?你举举个例子,假设你到D的距离,它到E呢有一条E的边。😡。

你会看你会发现你会你你有一个需求是要改小跟堆里面已经进去的距离。😡,为什么呢?D三出来了,对不对?😡,D三出来了,对不对?而你D呀往下跳,它有一个到E的距离是一。😡。

其实你是需要在小跟堆里面把E14改成E4。因为三加这个一是4,哎,你是临时要改E的距离,还得指望小跟堆把它调对,对不对啊?😡,你要上到这儿的。😡,这意味着系统给你提供的堆做不到。

只能因为你已经上堆的东西参与排序的玩意儿,你是要改它的,然后你还指望都调成小温堆,系统提供的实现不了。😡,听了他要打一。理解吧,系统提供的实现不了。😡,但是如果你想象一下。😡。

你如果实现了一个可以改动的小跟堆,就是你你临时把某个记录的值变小了之后,你还能让他自己手动自己写一个小跟堆,把它调对,你是不是就不用便利了,那就真的是不用便利了。

那就会比原来便利哈希表的方式选出最小距离要好的多,这就是我们DJ特斯拉要改的地方。😡。

看版本2。我会给大家讲的非常的细,因为我这个代码写的非常的。容易理解,上面都不用看,大家只用看主方法,就这么短。啊,我们先介绍一些东西。主方法就这么短啊,你你你现在可以按照黑盒来理解。

现在我要改的这个堆啥意思呢?这样的啊。😡,我现在说啊,大家看一眼这个这个堆里面放的是啥啊,这个堆。它里面放的。就是按按照组组织一些小跟堆放呃,组织一些记录放进去啊,组织一些记录放进去。

然后你现在对你来说啊,你不用想这个堆它内部是怎么实现的,先不用想这件事情,你现在就想一件事,就是你要需要什么功能,你需要这个小跟堆给你什么样的功能。😡。

他给你的功能是。举个例子。假设你有一个小分堆。😡,首先你得有个功能,是新建一条记录,对吧?比如说我从from这个点出发。😡,当我通过某一个点跳出来说,我到X距离目前是假设1。

我这个小跟堆需要能够接收这样的记录,而且是通过后面这个值来组织的小跟堆得有这样一个接收的,就是I的操作,对不对?😡,得有个I的操作,对不对?😡,能方便我把这个X10放进来。如果还有其他记录的话。

那么这个十将根据其他记录去PK,这个X10会来到堆上的某一个位置,没错吧。😡,所以需要一个爱的方法,这个小分队你还需要一个什么方法,还需要一个up day的方法。😡,为什么呢?

因为你比如说就像我们刚才那个例子,假设啊我原来到Z的,我我从from点到Z的距离是100,我中间某一个桥连点。😡,from到这个桥梁点的距离是7,但是这通过这个问号跳到Z的距离呢,只有3。😡。

所以我现在要有一个update的一个操作,就是我把到Z的距离更新成10,原来是100,对吧?所以我还需要一个update的方法。😡,而这的方法就是你你自己把Z的这个100啊改成10,然后呢。

你找到这个Z的这个位置,在堆上的什么东西,位置上,在在东在在这在这个堆的哪个位置上。😡,它的值变小了,它在堆的那个位置上往上做hiop insert调调整。所以那个小关众还需要一个upd的方法。😡。

没错吧。那你这个小关东还需要什么方法呢?😡,还需要一个方法叫。就是。exor方法啥意思?为什么我还需要一个exel忽略方法?😡,因为根据我们的说法。😡,一个节点的记录一旦被弹出。😡。

相当于这个记录我们以后永远都不要动了,对不对?😡,我给大家举个例子,大家就明白了,我从A出发。😡,我一开始有一条记录,A到A的距离是0。😡,A通过B的桥联点,它是三的距离。B通过再跳到乙一的距离。

跳到C的桥梁点,结果C又跳回来是五的距离。大家想象一下,我一开始已经使用了A0这条记录,小跟堆里它应该是没有再也没有A这条记录的了。但是你有没有可能从C当时跳的时候,它又有一个五的记录,又能跳回A。

我们小跟堆要能够识别说当我想把3加1加5,当我想把生成一条记录,3加14再加59,我想把A9这条记录重新扔到小跟堆上去,应该失败。为什么?因为你原来弹出的记录。A0,你已经是关于A的记录。

你已经再也不需要去操心了。如果有朝一日转回到某个一个,你已经不再操不想再操心的节点上,甭管这个距离是什么?甭管你小跟堆上有没有,你都应该exor。😡,就这么三个功能。听懂他打一。

对吧只要你的堆能够实现爱的方法,upate的方法或ex个闹方法。😡,你这事儿就就干就干完了嘛,对吧?除此之外,你什么都不需要,就需要这三个。好的,大家看。😡。

这就是我的堆。我堆的我堆的记录是什么呢?😡,当我某一条记录要加进去的时候。😡,一开始加入headd到head的距离是0。大家看这个方法牛不牛逼是吧?😡,这个记录如果真的是需要新加的,你就给我去ad去。

这个记录如果它已经存在了,我需要更新它的记录的话,你就给我update去。这个记录如果是不更新的话,我就认为你现在调这个方法,我就当你是个P给你放了一个no方法。

直接一个大名字ad or updateate or一个no。😡,听台打一。所以我们看这个代码,你其实非常好理解的,怎么样呢?你一开始的原结点到自己的距离,到到自己的距离,在小跟堆上是零的距离,对不对?

好,你就把这条记录加进去。😡,然后注意看。每一次在小跟堆里面弹出一个记录,哎,这个记录是啥?很简单,这个记录就是当前节点是什么?😡,原节点到它的最小距离是多少?给你封装成。

我管它叫node record这么一个东西。所以你看这个方法它很短,说的是什么意思?就是我从小跟堆里面,我弹出一个。😡,当前小跟堆里最小的记录。😡,弹出了最小的记录,而且它一定不是之前已经弄过的记录。

😡,弹出了,然后以它做桥连点,我看看能不能更新to的记录。如果这个to的记录压根之前就没有,你就给我艾去。如果这个to的记录之前有,并且它现在这个距离是更短的,你就给我upd去。

如果这个to是之前我搞过的记录,它只是之前弹出的话,你就给我ignor去。😡,每一次都是ar add or update or ignore。😡,然后我再把这条现在目前出来这条记录是不是已经是答案了。

对吧?当前这个点到原起点到它最短距离是不是已经是答案了,放到redo里面去,最后把redot返回。😡,所以我就扔给了一个特别傻瓜的一个结构,你给我艾或update号或igor,我主函数根本就不操心。😡。

这个主流程看明白同学打一。接下来我们再想一下这个小跟堆该怎么实现不就完了吗,对不对?😡,对吧。是吧好,那么这个小跟堆怎么实现呢?😡,看一下。小跟堆里面。它有一个node类型的数组,这玩意儿啥?😡。

堆结构。这个东西是啥?😡,如果一个节点。他再堆上。😡,那么他的记录这个位置就是在堆上的一个index。他就有下标。😡,比如说这个一个node,它在7位置,那就认为它在堆的实际结构中在7位置上。😡。

如果一个node,它后面是-一的话,就认为这个node曾经进来过,但现在不再堆上。那你说这样的node是不是就是你需要一个node呀?😡,听台打一。对吧。这个方法我给你讲过吧。

我们在第讲堆的那个章节的时候,给你拆析过类似的结构。当时就给你讲了一个怎么手写改堆的。现在我们继续重复再来重温一下手写改堆这件事情,就这个目的。😡。

所以这张表就是说任何某一个节点value上是指它在堆中的位置。😡,如果他曾经他有记录,但他记录是-一,就表示他曾经进过堆,但现在不在,那只有一个可能性,就是他进来之后就弹出了嘛,对不对呀?😡。

所以用这张表就来维持我们刚才说的那套东西,还有就是。原节点。啊。原节点出发到该节点的目前为止的最小距离distance map。啊,原节点触发到该点的最短距离,我们管它叫dsin次 map。

然后堆上现在收了多少个点,就是size,就这么四个东西在那玩儿,看怎么玩的。初始化的时候。你给我一个size,我就给你建这么大的堆。😡,对吧你给我个size,我就给你建这么大一个堆。

应该说准备这么多的空间。但现在目前为止,这个空间上没有任何堆的范围,因为你的堆的size是0,是这意思吧?那你一开始什么记录都没进来,你当然不会你当然这个在堆上的距离表呃。

在堆上的位置表就是空的dsance map表也是空的。对吧我们先看一些小方法,比如说怎么判断这个堆空了。你接收的节点数量是零就是空的对吗?😡,容易吧,我们再看这个。哎,怎么知怎么知道一个节点进来过。😡。

怎么知道一个节点之前进来过,就跟我们说的。😡,如果这个节点在堆中的位置是有记录的,表示你进来过堆,不管你这个记录是-一也好,还是一个正常的下标,从零开始的也好,只要你有进有有过这个。😡,堆位置的记录。

你就曾经进来过我这个结构。所以就这么判断吧,你是否包含这个之前有个记录,甭管它是负一还是什么,只要你有记录,你就进来过。😡,哎,怎么判断一个节点是否在堆上呢?😡,首先他必须进来过。

并且他在堆上的位置不等于-1,就说明你再堆上这两个小方法,看同学打一没能打2。😡,好,那么接下来我们就要看这个。最关键的两个方法了,一个就是ad or update or一个no,对吧?

还有一个就是我们的pop方法,在小分堆里面拿出一条记录返回,拿出最小的记录返回。好,都是怎么做的,先看。😊,我现在是关于node,它的距离,现在目前为止发现的距离是distance。😡。

对吧这个n这个dist不是说我现在最选最短距离,不是它是说n现在有一条新的距离是distance。你要跟你如果它没有这条记录的话,你给我新加。如果它有老记录的话,你要比对之后选择最小值作为它的距离。😡。

如果是他你不需要操心的东西的话,你就当他方是个P给它放掉,对吧?我们看这个node,如果它压根儿就在堆上。😡,他已经是再堆上的了。😡,怎么办?😡,那就把它在diistance map中关于它的记录。

它的老记录和此时出现这个新记录的最小值作为它的最新记录嘛。没错吧。😡,然后我们怎么调整呢?你有可能距离是变小了哟,所以请你在堆中从你现在的位置开始往上做infert黑fi的调整。

infert往上你有可能变得更小。所以你要跟你的副节点PK看你能不能往上移动。😡,再堆上手的调整。如果他压根儿就没有从从来就没有进入过这个堆呢。😡,那你就把当前的那就是要新记录,对不对?新记录干嘛?

在堆的最后的位置把节点挂上。😡,那么这个节点它现在在堆的什么位置啊?在size位置上。😡,它的距离是一条新记录,也就不无从PK起,你就把它挂上就完了。😡,那就是说从堆的最后一个位置把它添加上的,该干嘛?

依然是insert黑fi的调整嘛。😡,这两个义服如果都没中,你说啥情况,就是他既不在堆上,他又进来过。😡,什么也没干,直接返回,因为你本来也应该一个or。这细节看清楚,同学打个一。嗯。

但是你如果从来就没有看过我关于堆的那节课,那你真的是听不懂啊,好好去把堆那节课看了。我的这些东西我之前都给你讲过,只是又我们又重温了一遍。😡,好。这就是我们的ad2 update二gon。

那我们怎么泡泡呢?😡,你是小跟堆,你说你应该怎么泡泡,必然是堆零位置的节点是。当前这个距离中最小的节点的记录,对吧?这个节点我们是知道的零位置的节点。它的距离是什么呢?

当然是在dis distance map中把它关于它的记录给拿出来,封装好。作为我的node record,最后给用户返回用户得到的是一组record对吧?这个record就是node是什么?

当前最小距离是什么,是吧?但是在返回之前,我们是不是还得调整啊?有关于堆的操作怎么调呢?你都要弹出堆顶了,是不是拿最后一个位置的东西去顶零位置的东西。是不是要把你看你这样swipe之后。

原来零的东西就来到了size减一,原来size减一的东西就来到了零位置。😡,你现在即将要弹出了,你是不是应该把原本的零位置的东西现在在size减一上把它标记为它现在马上要出堆了,改成负一。😡。

dens map中你要删掉关于他的记录,因为他即将要p泡出去了。但这个我这个这个负一我要留着表示你曾经爱过是吧?曾经进来过,但此时你不再堆上了而已。😡,然后我们要把size减一位置的东西给释放。

因为原本零位置的东西被换到了3的点击上,现在我要不要它了。😡,那你那你原来size简易的东西,现在来到了零位置,你是不是要从零位置开始往下做hyf的调整啊,这么一套东西都弄完之后给用户返回。😡。

你只要理解什么是堆排序,你就理解什么听懂同学打一。😡,每次调整堆不也是复杂度吗?是的,但代价是什么?我原来便利哈希表,我是要通过N条记录,现在我都是在堆上玩,原来是BGON,现在是logN。😡。

这就是为什么要改成手写堆的形式,它就是快,而且快多了。😡,小龙同学听懂啥意思吧?我原来可是在哈西表,我不我不组织,我就散着瘫在那儿,你给我找,你给我便利,我每次都承担一个便利,我每次都承担一个便利。😡。

现在是什么?现在是我在堆上调完之后给你拿堆顶,那代价能一样吗?😡,对不对?理解吗?小龙同学。哎呀,这咱。logN一般情况下也没多少吧。对呀,没多少啊,但是logN可但是BON可可可能很多,对吧?😡。

我假设我记录就是二的32次方,你每次便利吧,是吧?我log n水平,我每次做32次,我能出来,那你B goN得弄到什么时候去,是不是?😡,好。那么接下来就只剩两个。

就你像这个hpinert黑fi这个代码你见没见过,它根据什么来往上移动啊?这个位置它的距离表如果更小了,它就往上出溜。这代码熟不熟啊?😡。

这个距离这它它这个当前index位置跟它负节点的index这个距离如果变得更小,它就往上移动。这代码不就是黑不隐,就是堆的隐色的调整代码吗?黑白饭你熟不熟啊?

小跟堆找到左右两个孩子中最小的那个跟我去PK。如果如果PK没PK过,没PK过,那我就往下沉。这个代码也就是当时堆排序的时候,黑byf的代码熟不熟啊?😡,嗯,不要忘了。交换的时候。

在堆上两个东西要交换位置,你既得既得在堆上交换,也得在堆的位置表里交换堆的位置表跟堆一定是同步调整的,不然的话你找记录就找找乱掉了。😡,我们一律把黑op音就是堆堆的位置表的更新和堆交换的更新封装在一起。

要变,你俩一起变。😡,整个打完收工。看看同学打一。啊,这里面乘除怎么不写成位移,可以写是吧?可以写啊。可以写的啊。好啊。那这个就是我们地质特斯拉的改进是吧嗯。就以后我们又熟悉了一把以后你会发现。

如果你使用堆的时候,已经上堆的东西,要临时改它字段,你就自己手动撸啊,我们已经建了两回了。要会写啊,自己要练练练透啊,因为这种这种技巧真的。它最巅峰的题是一道网易的面试题。啊。

你们有有就在训练营里面好好讲一下那个题,我操那个题要是搞懂了。你就是堆着爸爸是吧嗯。好啊,那个真的那道题是我见过以来考堆考的最他妈变态的一道题。他用了5种堆,5个不同结构的堆。

而且有一些堆要你自己手写啊,太牛逼了是吧?这个我我要是出这种题,我他妈恨不得抽死我自己是吧?但人家网易就考是吧?好,我们接下来呢就要开始搞这个暴力递归的问题了啊,我们休息2分钟,然后继续啊。嗯。啊。

随问了问了啥。😔,嗯,大家把之前的视频看看好,好吧。你把我之前视频看了,我刚才理解刚才我们讲那些真的是一点压力都没有这个已经看过视频同学发表一下感受,觉得一点压力都没有。同学打个一。之之前看过课的。

真的去练过的,就把我代码都摸过一遍的。不不赞同打2是吧?😡,就你只要看过视频,真的一点压力都没有。我当时课上讲的非常的细,理解吧?就真的是巨细无比。就手撕堆这件事情。

我们之前的课用了一个多小时讲过一遍了,其实好吧。😡,啊,那你说你说已经到了基础班了,你你还跳课过来看是吧?那那真的没法讲啊,那这课永远在扯之前的那我们讲到啥时候去啊,是不是?😡,啊。Okay。暴力帝归。

其实它就是尝试啊,大家不用想什么分制啊,或者是什么回溯这些词都是啥意思?你就是一个问题,你把大问题搞成小问题,小问题给你返回一些信息,他妈就是回溯是吧?😡,大问题拆成同样规模的小问题。

小问题给你返回的信息,这就要回溯。😡,对吧你把一个大规模东西拆成小问题,本身它就要分支是吧?这这个东西你不用继承的名词,你就是把一个大问题拆成小规同样问题,同样同类问题的子问题。😡,然后呢。

你这个问题小到什么样的规模就不需要继续了,它就是终止条件base case。😡,你得到了每一个子问题的结果,那就回溯完毕,你怎么做决策,就是回溯完了之后做决策,加工出大问题的信息,往上返回,这就是递归。

这就是尝试,对吧?😡,暴力什么体现在哪儿?😡,不记录每一个子问题的解,它就是暴力。你记录每一个子问题的解,它就是动态规划。😡,我们在动态规划的章节会给你进进行进一步的阐述。

现在我们就解决怎么暴力尝试的问题。好,我们来一道题。😡,给你列了这么多,我们依次来搞。首先我们要搞一个问题,就是汉诺塔问题是吧?扯递归这个东西是绕不过去的。

什么叫汉洛塔问题啊?😡,就是说呃一个叫焚天塔问题。假设我有三个杆儿。😡,这是左杆儿。这中杆儿。这个呢就是右杆。注意这个只是。这个只是焚天,就是或者说汉诺塔问题的。主视图。

就是它主视图看起来它是这么左分左中右的。😡,还有哪问题的俯视图。😡,其实等边三角形的组织。😡,啊,那么它怎么移动呢?假设我是一个三层汉断塔问题,他说的意思就是一开始在最左侧有三个杆儿。😡。

我的移动要求永远你要么一个杆上没东西,你可以直接放到把一个把一层的盘子放到这个上面去。😡,要么一定要小压大。不能大压小啥叫啥叫大压小?比如这是一层圆盘,这是二层圆盘,这是三层圆盘,一层圆盘最窄。

二层圆盘其次,三层圆盘最宽。如果我决定把一层圆盘挪到中间去。😡,如果我这么决定,那么下一步你还可以把一层圆盘往右边挪,当然你也可以把二层圆盘,你还能不能挪到中间了,不行了,为什么?

因为二层圆盘从这里面摘出来,往这里面倒的话,它就变成大压小了。😡,他从这里面他他他从这个这个底座,这是底座,好吧,底座是不能够出来的。你二层圆盘从这拿出来之后,然放进里面去,它就大压小了。

这种操作是禁止的。😡,那么在这样一种规则下,我们为什么要强调它这个等边三角形呢?因为。😡,因为我这个三层的杆三层的盘,二层的盘和一层的盘,我如果把一层的盘先移动,我可以直接一步到位到右边。

我也可以来到中间。也就是说你从你这个圆盘从左边,你可以移动到中,你也可以移动到右,它它距离上并不是说我最小的圆盘一定要通过中间才到右边。这是我为什么要强调它是个等边三角形的原因。😡,你个最小的圆盘。

你怎么动都行。你从这个左边摘出来之后,你可以给它放到中里,也可以给它放到右里,这都是一步的事情都可以做。😡,问题就是怎么样用最精简的步数把圆盘从左侧全挪到右侧去打印这个过程。😡,好。

三层焊洞塔问题怎么样移动是最经简的,给大家展示一下。三层焊盗塔问题怎么移动的最经典的呢?第一步第一步,一层圆盘来右边。😡,第二步,二层圆盘来中间。第三步,一层圆盘落在上头。下一步,三层圆盘挪到右侧。

然后一层圆盘挪到左边。二层软圆盘落上来。一层圆盘落上去结束,这是最经典的步骤。那么当我的汉洛塔问题,这个N层圆盘变得很多的话,你怎么打印所有的最优轨迹?😡,理解这个问题,同学打个一。好。

你们课上老师给你们讲的方法,可能一下就给你们讲蒙了。我这里面用最具启发性的东西来给你讲。😡,我们现在想一下,如果你是1到N这么多圆盘,现在统一停留在左边,你咋都移到右边去。第一大步。

一到N减一的圆盘先都从左边都给我挪到中间去。就是一到N的圆盘都在左边,对吧?我先把这上面1到N减一的圆盘都挪到中间去。我为的目的是什么呢?我为了给N层圆盘腾录,你这样移动过去之后。

N层圆盘就可以跳到右边来了。😡,所以第二小步就是N层圆盘自己孤零零的从左移动到右边去。那么第三大步是什么?你1到N减那个圆盘,是不是它是不是在中间啊?1到N减一层圆盘现在是不是在中间呀?

所以第三大步就你想个办法把一到N减一层圆盘从中间再给我都挪到右上来,结束了吗?这是一个大步,这是一小步,再接一大步,整个问题搞定,听懂同学打一。😡,好,于是。为啥要把N减一挪回去?

因为我们的问题是你要把一到N的圆盘彻底从左侧全移到右侧。你完成第二步,还剩着这一坨没动呢,你是不是得想办法给再子移到右边来?😡,汉诺塔问题的问题是什么呀?是1到N全过去,不是指N过去,对不对?😡。

理解这个问题,同学了吧,这个同学理解了吧。😡,为啥你要移回去?因为我们汉洛塔问题就是1到N一开始都在左,请你变成都在右的样子,要打要打印多少步?😡,或者说要要把整个过程都打印出来。😡。

这个感悟同学理没理解?不是该移N减2吗啊。

为什么N减2是G啊,你来来咱咱咱看一下,好吧,来,咱看一下。我就知道你们肯定懵是吧?或者同学肯定懵,所以我给你写的,你看看我这这多良心,就我跟你说汉诺塔一就没有老师这么讲,但是他最好理解。

然后我们把这个问题讲透之后,你再看看汉诺塔二问题有多短哎,就这么短。😡。

就是没了。那你不你不懂是吧?没没关系,来,咱现在搞。😡,来,我们现在这样。请把1到N层圆盘。从最左。给我移动到说从咱不说最左从左移动到右就行了,是吧?从左移动到右去。😡,这就是我的递归的含义。

这个N它不代表单独的N不代表D只是DN层的圆盘,它代表你一定要把1到N层圆盘全给我从左一到右去。😡,怎么打印?😡,base case是什么?N等于一的时候,N为什么等于一呢?N等于一什么问题呢?

就是你只剩一层圆盘,而且是最高那层圆盘了。你说你怎么从左移到右去,直接一倍。😡,对吧木一 from left to right打印这一句结束了。base case。😡,三大步怎么体现。

我们再写个递归过程,我们再写个函数,这个函数指的是这个函数指的是。😡,我给你我给你传一个参数N,你把一到N的圆盘从left移到中间去,这个过程统一用这个方法来代替。所以这个大步就会拆成这些小部。

第一大步。😡,一到N减一的圆盘,先从最左挪到中间。然后单独的第N层圆盘从最左挪到右边,再把N减一层圆盘从中间移到右侧来,整个过程完毕。这个方法你可以把这两个函数就当成黑盒。😡,懂的同学打一。好。

那我问你。那我问你。这个函数怎么写?这还啥意思呀?请把1到N层圆盘。😡,从左边移到中间去。它是什么过程呢?如果你只有一层圆盘,你就直接移嘛,从左移到中间嘛。😡,如果你不是不止一层。

你说你怎么把一到N层圆盘从最左移到中间呀?你要先把一到N减一层圆盘从最左挪到最右。😡,然后把单独的第N层圆盘从最左挪到中间,再把N减一层圆盘从最右挪到中间上去,还是腾路这件事儿,对不对?😡。

看到他还打一。梅懂达2。哈。😊,你知道多良心吗?你在看这个怎么把N层圆盘从最右挪到中间啊,先是1到1到N减一层圆盘给N层圆盘腾录,怎么腾录,先把一到N减一层圆盘从最右挪到左去,然后单独移动第N层圆盘。

再把N减一层圆盘从最左挪到中间来。下面一个过程是怎么把N层圆盘从中间移到右边去,是腾录。😡,腾璐。腾璐。这6个递归相互嵌套,但主函数是这个你总有打印出来的时候,听懂同学打一。😡,嗯。

对吧这这个讲法应该来说你你你。😡,你是你是可以理解的对吧?你你不就你不就这么几个过程吗?😡,对不对?😡,好。这是我要讲的方法吗?不是,这只是启发你的方法。😡,这只是启发你的方法。😡,那我们来想一下。

他不就是藤路这件事儿吗?😡,我忘掉左中右。我忘掉左中右。😡,我假设我就我现在在from上,你甭管这个from是左是中还是右,忘掉它。😡,我要去往的是兔,你甭管这个兔是左是中还是右,忘掉它。😡。

另外一个叫otherer,你不用管这个otherer是左是中还是右,忘掉它只有from to和 other,你要把1到N层圆盘怎么从from挪到to上去。😡,第一步一到N减一的圆盘。

从f先给我挪到other上去。第二步,单独的N层圆盘从from直接滚到to上去。第三步一到N减一的圆盘,从other给我挪到to上来。

根本不用区分左中右一个from跟to跟other三个参数代表所有过程了。😡,听台打一。对吧。好。这个代码就是底下的。来。😊,别跟我扯什么左中右,我不认这个,我只知道N层圆盘要从from到to上去。😡。

另外一个叫阿er。😡,N等于一的时候,就是一层的时候,一层的时候你直接移move一从from到other。😡,剩下甭管什么左中右。😡,它统一的过程就是N减一的圆盘,从from到otherer上去。

to就变成了子过程的那个otherer。对吧我我这个主过程的to就变成了子过程那个阿er。😡,我一到按键一的圆盘,现在的目标是从from挪到otherer上去,to就变成了那个otherer第一大步。

😡,然后我就给N腾出路来了,N腾出路来了,你怎么从from到to上去直接去嘛?😡,最后一步,我是把一到N减一的圆盘从other再挪到to上去,from变成了other搞定了,就这么短主函数怎么调?

N层问题,from叫left to叫right,另外一个叫meddo。😡,听供他打一。呃,我我还我要我要问一下,这个不会的同学现在赶紧打2,我再给你来一遍。不会,同学现在赶紧打2,我再给你来一遍。😡。

还是有挺多不会的。好,我现在重新给你来一遍,好吧?呃,这个应该的啊,绝对是应该的啊。这样来咱咱咱咱咱这么弄啊,咱这么弄。

我们从那个从哪开始讲起呢?嗯。我们这样来想啊嗯。就直接给他给大家来一个最最最。呃,最后一个版本的讲述啊,但是让你懂好吧,让你懂。诶。你要知道所有的过程。😡,其实是有很多过程的。就是。

我我现在讨论是整体打印行为。好吧,我现在讨论是整体的打印行为。什么叫整体?就是当我说一到N的时候啊。😡,哎,等一下,当我说一到N的时候,我要从最左挪到最右边去,它指的是它的整体得过去。

那你说它的整体得过去。😡,你就单独想一下最后一层圆盘该咋整。最后一层圆盘它出不来,对不对?😡,它是不是出不来啊,它为什么出不来啊?它上面压着一到N减1嘛。😡,没错吧,所以就面临的一个问题。

就是我要想让最底下这个圆盘想挪到右边去的话,我得先把上面这些东西统一的给倒想个办法倒腾到中间。😡,上面这些东西统一的想个办法给我倒腾到中间,只剩第N层圆盘停在左边,那我的第一大步就完成了。😡,然后呢。

我的这个最底层的圆盘就可以倒腾到右侧上去了。😡,等了右侧上去之后,我再想办法把1到N减一的圆盘现在是不是都在中间啊,想办法在咱们再把它们都倒腾到右边来,是不是整个过程就完成了。😡。

就是你最后一层你是没有办法的,你最后一层想要出来,必须把上面东西都倒腾走,它才能出来。😡,这个打二的同学理解没有问题,同学打个一。😡,就你倒腾嘛,对吧?好,现在是说的什么意思呢?

现在它其实这个倒腾的过程,或者说主过程其实是6个。😡,一到N减1到N的圆盘,怎么从最左挪到最右这个过程?一到N的圆盘怎么从最左挪到中间这个过程,为什么都有这些玩意儿呢?原因在于你这个你想往下拆分问题。

你会发现你会遇到这个问题。干为什么你看你最初的问题是一到N的圆盘。😡,怎么从整体从最左挪到右边来,这个问题,对不对?但是。😡,你有一个子问题呀,我们刚才说了。

你得先想办法把1到N减一的圆盘从最左你给我挪到中间去这个子问题。😡,所以你会发现。😡,当我一旦往下拆分下去,我就会遇到一个整体从左挪到中的问题。原本是整体从左挪到右,规模稍微缩小一点。

它就有一个整体从左挪到中,而整体从左挪到中再往下拆分。😡,最终一定是6个大过程,一到I的圆盘,既有从左到右,又有从左到中,又有从中到左,又从中到右,又有从右到左,肯定是都有的。如果这个N很大,毫无疑问。

这6个过程都会发生。听懂同学打一,尤其是打二的同学。😡,啊,咱咱已经懂的同学别别别别别弹幕,就问答二同学,对吧?因为关键就是给这些同学服务的是吧?啊,我我很心安理得是吧?我很心甘情愿啊。

这个因为你们是爹是吧啊。😡,倒腾期间能大压小吗?不行,倒腾的期间依然不能大压小,永远只能小压大。😡,好,那么既然有这6个过程,我就可以做适当的抽象化了。😡,我现在忘掉什么左中右这件事儿。

假设我的问题我定一个函数,这个函数叫。😡,一共有这么多的圆盘,1到N都要考虑第一个参数N,第二个参数叫它们整体要从from挪到to上去。对吧他们整体要从from挪到to上去,另外一个杆儿甭管是什么。

它叫other。😡,那么我其实6个函数就可以变成这一个函数的描述,无非就是你传入的from to other参数不一样,你不就代表着从左到右还是从右到左,还是从中到左,还是从左到中嘛。😡,对不对?😡。

加几个参数概括六个过程了,参数不同而已就能代表六个过程。😡,好,那么我就看只看这个问题就够了。这个问题指的是你一到N的圆盘一定要从from都给我挪到to上去。另外一个叫otherer,这个杆。

另外一个叫otherer。😡,那不就是这三步吗?如果我整个过程中这样一个定义的话,那第一步那就是你说你你现在整体是1到N的圆盘,从from到to上去,是不是你还得让1到N的圆盘给第N层腾录。

让这个N层圆盘可以去往to啊。😡,那你第一大步是什么?一到N减一的圆盘得倒腾出来到other上去,然后N层圆盘才能动去 to,对不对?😡,一到N的圆盘,你先得想办法从from。

你给我倒腾套other上去。那现在to是不是就成了另子过程了另外一个第一大步,你进行完这一步之后,你倒腾好了。第二小步就单独你打印N层圆盘,你直接去嘛,因为所有路都给你开开开了,对吧?

所有路都给你开开了,你直接从第N层圆盘,从from挪到to上去,这是一步打印,就这这只是一句打印,对吧?第三步。😡,你要都你主问题是一到N都去to的。而你现在你经过你第一步的倒腾。

现在一到N减一的圆盘现在还在R上去,你是不是得想办法把一到N减一的圆盘再统一挪到to上去,跟N汇合呀?😡,他怎么他啥过程?第一步,他已经他们都已经在other上了。

你给我想办法挪到to上去from就成了第三部的otherer嘛。😡,就这么个过程。打二的同学听这回听懂同学打一。啊。还是没懂是吧?嗯。上一层地归总是被下一层子地归影响,这是为啥这个。嗯。

我我没懂这个同学这这大帅同学具体问的是哪个点啊。我们现在。

要不给你实际来一把吧,好吧,举个例子好吧,没懂朋学,我再举个例子啊。嗯。三层焊路塔问题原始问题是123怎么从左挪到右边去?啊。只能小压大,不能大压小。对吧。好,那么我就开始了。第一大步。

我不管你用啥办法。你给我把一和2。从最左给我挪到中间去。第二小步。第三层直接从左区右边。第三大步。我不管你有什么办法,请你把1到2。从中间你给我挪到右边去。是这么个问题吧啊,好。

那我们就现在来拆分这个问题。这是我的递归是吧?我地画框的就是递归,没画框的就是打印行为。那他怎么展开呢?它怎么展开呢?😡,你怎么把12从左边给我挪到中间呢?你给我展开吧。😡,我不管第一大步。😡。

我不管你用什么办法,我我这个二。😡,我就要去中间。😡,你要给我腾路。😡,所以在这个子问题里面再拆,我不管你有什么我不管你有什么办法,你给我把一。😡,从最左挪到右边去。这是为什么?因为我的二要去中间。😡。

所以在这个子分题的拆分里二,它就从左边去了中间。那么一已经到右边了,你要挪回来,对不对?所以我不管你有什么办法,你给我把一给我从右边给我挪到中间。😡,就算结束。😡,好。这个问题已经不用再拆分了。

你一的已经是一层圆盘了,你该打印,你直接从一到左就完了。所以他后续没了,直接就是他自己。😡,第二个行为是二,从左挪到中间,最后一个行为也是一,从右过挪到中间。😡,对吧拆分完毕。😡。

第三个大过程不是一样吗?😡,第三个大过程是我这个二,我现在要从中间挪到右边去,我不管你有什么办法,你给我腾路。你怎么腾路。第一大步这个一呀,我你要从中间先挪到左边去?因为咱俩一二现在都在中间。

你的一先给我挪到左边去,为什么挪到左边去呢?因为你要让我的二解放出来,能够从从中去往右吗?😡,对不对?😡,我们整体要从中间挪到右边去。第二大步完成之后,一是不是在左边?

所以最后一步是一从左边你给我挪到右边去。好。打印行为是什么?这是第一句打印,这是第二句打印,这是第三句打印,这是第四句打印,这是第五句打印,这是第六句打印,这是第七句打印整体过程就是第一句打印。

第二句打印,第三句打印所有打印串下来,这个过程就完成了。😡,展示一下,123一开始都在左边。然后要去往中间,然后要去往右边。第一步一给我从左挪到右。第二步,二步,从左挪到中。第三步,一过从右挪到中。哎。

终于能做这一步了。第三步从左移到右。好,腾路了,从左移到右。接下来第五步,一从中移到左。下一步2从中挪到右。再下一步,一从左挪到右。😡,不就完事儿了吗?😡,听懂同学打一。没有办法用递规去想事情。

说明练的不够,那你就彻底的把一个具体的例子还原到最底层,好吧。😡,嗯,这个。

然我们再看一眼这个方法。所以不管你你一到N的圆盘,从from挪到to上去,另外一个叫other,不管你from是什么,to是什么,other是什么。如果你只有一层了,请你直接过去。如果你不止一层。

先给先把1到N减一的圆盘挪到other上去,为什么?因为你要给DN层腾录。然后你再把N减一的圆盘从otherer挪回to整个过程结束,这道理就跟把大象放进冰箱分几步,第一步打开门,第二步进去。

第三步关上。好,现在有没有感感觉了?有没有感觉了?觉得理解没有问题,同学打个一啊。啊。对吧。有非递归解法吗?有。有非递归解法。我们来试图写一下。看了看那个祥龙同学问了半天了啊。嗯,直接左是吧哎。

先打个中文。嗯。嗯。我想想非地归计划怎么写啊。那你不让系统给你压战,你自己压战呗。😡,我想怎么写啊?最最暴力的方法呃,最呃不不对不不不说暴力吧,就是。最好改的改法啊。任何递规行为都可以改成非递归。

尝试的写一下啊。然后。先把无效参数洗一下。如果N等于一如果N小于一。什么也不打印。哦。嗯。record里面封装一个现在最底的圆盘是什么数字?这只是肯定有更优雅的改法啊,但是你突然现在突然间问我。

而且你发了那么久,我不能不理你,所以就改一下,好吧。看能不能改出来啊。任何递归都可以改成非递归,无非就是系统帮你压榨,你不让他压,你自己压,对吧?😡,那我们先来想一下这个我一开始的主过程是啥呀?

想一想啊,这个。把record放进去。这个不用写了,是。那必然的主目标stistic应该怎么压呀?你有软口的吗?我想想啊这个。怎么写啊?这个new record。他肯定是最底层圆盘。

是N层圆盘from呢,那肯定就是。left对吧?to是什么呀?right。other是啥?就是。没懂。对吧。这个站我就压进去了,然后。想想怎么弄啊?啊,用一个树枝不好弄。嗯。那只能那就再加吧,是吧?

他分为他有没有做完一,对吧?第一步有没有做完,一开始默认是没做完的。所以一进来先把这个N层圆盘第一步没做完这件事儿告诉他。是这意思吧?然后我开始跑这个这个站。如果这个站不等一空。

就继续先把当前的record弹出来。呃,如果我发现他第一步没完成。不过我发现第一步没完成。否则那就是。他第一步完成了。是这意思吧。如果我发现他第一步没完成怎么办?我现在不能结算此时的record的。

因为你还没有为这个当前结算这个record的,把这个record的正确执行做好准备。因为你第一步没完成,所以你给我站重新给我压回去。😡,把单天给我压回去。下一步其实我也就知道了我想想啊啊。😡。

我应该先这么判断,就是。如果当前current他的。base已经是一了,你根本不用纠结它第一步、第二步、第三步的问题,它现在就是第一层圆盘在做事情,你就直接做就完了,对不对?所以应该这么写。😡。

打印一下。move啊,我把这个这个current的是相应的值都给我弄出来。好吧,第一个布尔类型叫finish一。current点fin1。然后呢,它的base是啥?呃。

这这这这这这这这可以姑且先调用一下啊,那那我或者说呃 move什么,我想想啊。就是move一 from啥current自己的from。吐什么。cover他自己的库对吧?没错吧,你你为什么可以这么写。

你的你都已经你这个record,此时你要加你要处理的这条请求是就是一层圆盘的情况了。我根本不用区分你第一过程完成没有这个东西我是可以直接做完的,所以就这么写。😡,对吧我这些东西估去省掉了。

但如果你不止一层圆盘。如果你不止一层圆盘,那我就要纠结你第一步完成没完成了,把这套进来。😡,如果你第如果你不止一层圆盘,我就要纠结你。😡,我想想啊,那怎么汇报,怎么往上汇报呢?我想想啊。嗯。

想想啊贝ase等于一的时候,你做完了。😡,恐怕还要加东西,就是。蛮难做的,这个非地硅板啊。嗯。后来再解释他为啥这个。为什么要有这一句呢?因为我们来举个例子,想干啥啊,就是。拿1二来举例。

那就两层圆盘的问题怎么挪?我就想买我就想这么干啊,先在这个站里面啊。😡,它主问题是一个。我一定要把两层圆盘。从左边。移到右边去这个过程。对吧当是他第一步没完成。我怎么知道他第一步没完成呢?

因为我一开始给他的是foss。😡,我一开始给他是fse,所以他第一回把这个信息拿出来的时候,他知道啊这个过程从左到右,这是一个两层圆盘,从左到右这样一个过程。但是第一步没完成。

所以我把这个记录重新压回去。😡,但是我会知道我的第一步是什么。😡,我第一步是什么呢?😡,我的第一步是先把第一层圆盘从左给我挪到中,为二层圆为这个过程腾腾路,对吧?这样一来呢。

我就把他的这个子问题给压回到站里去。😡,把这子问题给压合到这个过程里去。😡,然后开始继续谈这个战。在弹这个栈的时候呢,就把这个过程弹出来了。F1这个过程从左边要挪到中间去。

我发现这是一这个过程我是可以直接做的,它也弹出来了,它已经弹出来了。当然我做完一步之后,就一定意味着某一个过程的第一步完成了谁。😡,现在站的站顶第一步完成了。😡,我做完这一句之后。

他已经弹出了的情况下的站顶,我把他第一步改成处。😡,你就你也不你也不重新扔回来了,占顶的东西也继续也被改了。第一步你完成了。😡,我的我已经打印了。😡,对吧从从第一步从从已经已经来到中间了。

那么当我来把再把这个记录弹出来的时候,就面对是T2。😡,左右这个行为好,我没我我发现我第一步完成了,我可以干啥了?我可以单独把二从左挪到右边去了,做一个打印。😡,然后我的第二步是不是要继续。

我第二步是什么?我是知道的,我第二步是什么呢?你把一层圆盘从最从从中间挪到右边去,这个过程作为一个大过程的话,继续扔到站里去,你给我继续执行。就这么一个过程。

但是所以我们有一个这样一个设计在一层圆盘的时候,你弄完之后,它已经弹出了的情况下,把站的步骤一就当前弹出完了之后,底下接下来的站顶的finn一搞成处,就可以传递下去了啊,时间有限。

所以我课下一定会改出来发给大家行不行?听懂同学打一。😡。

啊。是吧可以吧。啊。好,那么想想用这个时间干嘛呢?再讲点什么,我我记一下啊,记一下,我记己拿个本记一下,要要完成这个东东西是吧?

唉。就是如果你不想让系统给你做这个站啊,你就自己去压,它是肯定是可以做到的啊。

哪怕实现的稍微麻烦一点,多增加一些信息的方式,你把站里面的所有东西该怎么压,你怎么记,其实是可以做到的,是吧嗯。

你比如说呃哪怕再不记就是什么呢?你看你这个不就是四个参数嘛,是吧?你把这所有的参数都给我压进去,你看我这个也是这么设计的,但你怎么去标记第个步骤一完成了,该第二步了,你可能还要加变量。

你在递归里面你是可以知道的。因为它每一个状态都会记嘛。这一步跑完之后该跑这一步了,你自己去做非迭代的时候,你不一定知道第一步跑完了,所以你就你就你就得用状态来控制它。

所以我们要加什么finish一啊等等之类的东西,理解这意思吧?其实本质上还是去模拟递归站,它怎么压,我去怎么做啊,这也不是什么考验技术,它就是一个细心的问题啊。😡,好,那么说一个结论啊,汉诺塔问题。

如果是N层圆盘的汉豆塔问题,它移动移动的次数一定是二的N次方减一步。啊,N层汉道塔它移动的部数最优部数一定是二的N次方减一步。嗯,是这样一个结论啊。怎么推也好推嘛,就是。😡,你1个TN层汉诺塔问题。

你是不是先让TN减一层圆盘一个对等的问题,先搞完之后,再加个一,然后再把N减一层圆盘的规模再挪回来,对吧?这个表达式你一算啊,它就是最后化简成你TN怎么求,那就是二的N次方减一步啊,通过这个公式。

你可以去求它是它应该是拆完之后是个等比数列啊,两倍的N,后面加一,你用列项的方式把等号左边也变成。把等号左边跟等号右边都变成等比的方式,你就整个这个公式你就算出来了是吧?

高中数学的内容所以就不再多扯了啊。😡,好,我们接下来再来一道吧。哦。想我我们我们想把打印所有子序列呀,不要出现重复字面值啊,排列呀,这玩意儿留到下周来。大家先看这个题。仰望一个好的。

尝试或者说一个好的递归函数。大家来先想一下这个问题,我们把这个题讲完之后下课,好吧。啊。呃,小龙同学问的这个问题,其实就是呃递归方法跟非递归方法时间复杂度是一样的吗?那肯定是一样的。

因为你一共有二的N次方减一步,你要想都打印,那你时间复杂度B是2的N次方减1。如果你就想求一个结论,那你只用把二的N次方减一,一共有多少步,返回有多少步数的话,那就很简单了,一个公式就搞定了。

但如果你就是想打印所有的过程。😡,那你解本身就有二N次方减一步,你要要都打印,你这个时间复杂度,你说能省吗?当然不行。😡,听懂同学打一。对吧你的步数就那么多,你要都打印,你想怎么样,对吧?

那你肯定省不掉嘛。😡,你解空间就是那么大,对不对?😡,啊,来大家看一下这个题啊,看一下这个题。写法不一样,但我嗯那那好,写法不一样,递归过程,递归过程的时候,每一个过程是不是来过来三遍,先到你一遍。

去你左过程转一遍,回到你再去你右过程转一遍,回到你递归过程对于每个点碰三遍,你你自己用递,你自己用站来压,是不是每个点也碰三遍,一开始进去的时候,弹出发现你步骤一没完成,你再把你自己压回去。

等你步骤一完成之后,你再把你自己弹出来。搞完之后,你再也不用再压回站里去了,还是一个过程碰有限几次嘛,😡,对不对?小龙同学有没有懂?😡,怎么估计呀,对吧?

你递归碰一个过程几遍和你要把一个东西放到站里面几遍,就用这个东西来估计嘛,对不对?😡,啊。啊。哎。啊可能是我现在老了是吧?其实我脾气蛮好的是吧?其实让我最伤心的就是很多同学听完这节课之后,觉得一头雾水。

然后这个是我最伤心的。因为我竭尽所能的在讲了,是吧?是。嗯。给你一个站请逆序这个站不能申请额外的数据结构,只能使用递归函数。该如何实现逆序一个战?啥意思?给你一个赞。😡,123。请你用某一个迷之方法。

给我把原始这个站变成321。不要申请额外的数据结构哟。😡,你别申请有限几个,别申请一个大的数据结构,往里互相导不行。😡,这个迷之过程你可以使用递归函数,但你不能显示的扭出一个新的数据结构来。

请问怎么实现?懂这个题议,同学打个一。嗯。好。这个过程当年我看他的时候,真的。觉得是人类迷惑行为是吧?而且把我镇住了是吧?我我没有想到这个这个脑回路得扭到什么程度才能够写出这样的代码,是吧?说句实话。

我当年看到这个的时候,当时害怕极了是吧?我觉得自己这辈子都不可能写出这样的代码啊。😊,但是随着年代逐渐的这个自己的逐渐的成长,我发现自己的抠的能力与日俱增是吧?我没有突也变强了是吧?

我发现这样的代码其实很有意思啊?啊,这个我们来讲一下是吧?我们先不用去想怎么逆序它。我们现在想实现一个一个功能,哪个功能呢?就是。你能不能实现一个函数GF。你把这个站传进去。😡,你把这个站传进去。

效果是什么呢?就这个站啊。😡,他能够把最后他最占底的元素给它去掉并返回。哎,你能不能实现这样一个函数,不要用额外的数据结构。😡,也就是说你你把这个站原封不动的传到这个F里去之后,它经过某一个过程之后啊。

它让你这个站变成12直接盖下来。😡,但是你返回是返回三的。😡,能不能实现这样一个函数?哎,其实是可以的。😡,怎么实现呢?我们现在来逐行讲这个code啊,来画这个体系图是吧?😊,看这个F函数。啊。

这个F函数的功能就是请你把这个栈啊,最后一个数你想办法拿出来,也不要留空隙,让上面的数盖下去,然后把最后一个位置的数给我返回了。好,那么这个函数是怎么跑的?我们现场讲。😡,来。😊,有一个站。

123F函数开始执行了。这个F函数怎么执行呢?这样来一行一行看。😡,从战中拿出一个。😡,用一个我的临时变量给它记住。好,那这一句是啥?我的R就是我的变量,我记住的是谁是一。哎,你弹出来了,对不对?

所以你这个站现在是不是空了,没错吧。😡,能我们继续?啊,你现在站空了吗?我来看一眼,弹出一之后,你站是不是没空啊,没空怎么办呢?就执行al。😡,哎,执行I的时候发现我需要一个临时变量。

它等于我调的一个子过程。好的,如果我们把这个过程叫F1的话。

我需要一个临时变量,我我我等着你F2给我值啊,所以不由分说F2就被开开了。

F2就会进入到一开始的过程中,继续去搞这个站。现在F2相当于进来了,对吧?F2相当于进来了,F2说是什么呢?站里面弹出一个元素,用一用一个我的变量给记住,好的,所以F2有一个变量,它现在记住了。2。

你的站要弹出才被我抓住,所以战中就没了啊,这个站中二就没了,对吧?😡。

然后F2我就问了,继续看。那现在此时这个站是空的吗?不是,所以走LF2又需要自己的一个临时变量,让F3给它一个值,它才能继续。

所以干嘛呢?😡,我也需要一个临时变量,我需要F3给我一个返回值,所以不由分说F3开开了。F3开开了,F3开开的时候,又重复进到这个递归里来,在站中弹出一个值,被result抓住,弹出什么么呢?弹出三。

所以F3啊就会把三给抓住,站就没东西了。😡。

那F3会怎么样执行呢?你现在F3过程里站它就是空的了,所以我直接返回我的result妥拉。😡。

我啥我抓到这个三之后,我什么也没干,我就给F2返回了。😡,所以F2终于它结束了,他抓到这个临时变量是谁?他抓到这个临时变量是3。😡。

所以我们来到了F2的哪一步。

F2的这一步。😡,对吧F2的这一步在这儿呢对吧?F2的这一步接下来该怎么执行呢?我把我当初抓到的result,我给它压回去。😡。

我抓到是谁?我抓到是2,我给他压回去。😡。

然后干嘛呢?我把F3给我的东西,我继续返回。F3给我的是啥?F3给我的是3,所以我也往上返回3。😡。

于是我们就到了F一过程的哪个位置,就到了F1过程的这一句,我抓到三了,我会怎么做呢?我会把我自己体内记的这个result压回去,我记得是谁?我记得是一,我压回去,那我返回谁呢?

我返回的是我下集给我返回了那个last,我返回上去,所以往上返回结束,返回三,正好是F函数的功能,听懂同学打一。😡。

啊。好,那你这一句。😡。

你你这一步你想完了之后,你就可以把它理解为一个黑盒了。😡,对吧这个F函数对你来讲,它就是一个黑盒了。它的功能很简单,S去掉最后一个数。😡,去掉底。在S中去掉底并返回。上面东西盖下来对吧?这就是你的黑盒。

😡,主函数就可以为我们改出来了。主函数依然是个递归。😡,来终于可以搞我们的逆序函数了。😡,123。

123。好,我们现在看主函数rereverse。我们还是。用体系的方式展示一开始这个reverse要处理这个站,我们管它叫R一过程。

R一过程说的是什么呢?😡,如果占为空,直接return。你是不是空,你不是对吧?你不是空,所以你继续。😡,I位置掉一个F给我的值,有意思了,这局在干什么?😡。

我的I,我可是掉了一个F函数的F函数的功能是在S中去掉底并返回。所以我这个I当我抓我会抓住谁,我会抓住三,并且整个站会因为F函数的调整变成12的样子。😡。

没毛病吧。😡。

然后我就自己去调用了reverse2。好的。😡,你给我调reverse2去,我不要你返回值,但我要你执行。好,开了reverse2。😡,reverse2上来又是什么呢?占不为空,对吧?

它也会调用一个F函数去掉底并返回,所以它会抓出一个2,而且站会因为它调的那个F函数变成只剩一。😡,然后他让你去调用reverse3去。然后reverse3就开开。😡,reverse3也会调用一个F函数。

我的I会把。😡,一抓到去调用reverse4去。一抓到之后战就为空了。你调用reverse4的时候会发生什么?reverse4一进来就会发现哎,我reverse4一现在站是空的。😡。

直接返回吧。😡,对吧reverse4过程一进来发现战是空的,直接返回吧。所以实际上reverse被调用之后啥也没干,直接返回了,它会来到啊reverse3的什么位置。😡。

这一句。我之前收集到的I给我压回到站里去,我收集到的是什么值?一。😡,好,我终于可以结束了。来到R2的这个过程,最后他也是把自己收集到数压回去。😡,返回吧。他也是把自己收拾到数压回去。😡。

返回吧,逆序了。😡,听我同学打一。这实际上是给你揭示啥呀?其实就是给你揭示这个这个这个递归站是可以帮助你保存一些信息的啊,就这个事儿是吧?然后在这个。这个肉与零的碰撞中反复摩擦是吧?啊。

当然开了个车是吧,不好意思啊,不好意思。好,我们今天这节课试图做一些总结,什么总结呢?递归函数。递归函数真的就是你想怎么试,你就能怎么写。😡,你想怎么试你就能怎么写。

但是他的问题就是你必须保证你的子问题跟你所描述的事儿是一个事儿。😡,理解这意思吧,你必须保证你的子问题和你描述的过程是一个过程,就是同拆成同样规模的子,同它拆成同样含义的子问题。一个大问题。

怎么想办法怎么把它拆分成。😡,小呃同样含义,但数据量变小的一个问题。然后把这个问题解决,但是具体尝试的过程中,真的就是你想怎么试,你就能怎么写。😡,但是尝试是有优劣的。比如说我们汉诺塔问题。

我可以就用6个递归过程去尝试,我也可以做抽象化,给它变成一个问题。是这意思吧。😡,那么尝试到底有什么样的,你们在面试过程中不可能或者说很小概率让你出现用暴力解解的方法。😡。

所以尝试这件事情其实是有优劣的,但怎么评价这个好坏?😡,动态规划章节会给你据重点讲怎么设计一个尝试。能够优化出最优的版本,我可不是在糊弄你,大家看一眼最后一节课的PPT。

设计暴力递规的重要原则及四种常见的尝试模型。在这一句的时候,我要深入的讲你们面试中遇到的尝试问题,它可就不能就是胡视了,他一定会遵循重要原则,而且你在面试场上,一旦你发现你需要写暴力尝试。

要么你是用对数器,你写的多暴力都无所谓。要么你就是一定要指望他改出动态规划的。这个时候在你暴力递归的时候,你的尝试是有重要原则需要去注意的。我们将在动态规划的章节进行进一步的讲述。

今天留的剩下的这些暴力尝试,我们将在下周继续讲,好吧。😡,好啊。啊,大家打个分,满分10分啊。那么我接下来就会把这个刚才的这个啊啊我们提的这个。飞凡那些数列问题的非递柜版本改出来。

然后把这个代码的推到gihaub上,大家在上面拉大码拉拉一下代码就行了,是吧?啊,在上面拉一下代码就行了,好吧。行,那么谢谢大家,希望大家下周。继续来是吧?我们下周就可以把我们基础班的课结了,是吧?

最值钱的其实就动态规划那块那一块啊,还有就是二叉树低归套路,剩下的东西虽然也重要,但是。我觉得那不是我的私货是吧?我给你搞的私货真的是非常牛的,是吧?好好。啊,有多少同学听懵了,实在是不好意思是吧?

那挺麻烦嗯听懵的同学。把这个视频好好看好是吧?好嗯,下周见,拜拜。

系列 2:P74:左神算法-二叉树的递归套路 - Java视频学堂 - BV1Hy4y1t7Bo

呃,大家好啊。大家好,我们下午接着下午就讲,就是二叉树问题。稍微再等两分钟。如何设计一个打印整棵二叉树的打印函数?

稍微等会儿。

稍微稍微再等两分钟。想想看怎么样设计一个打印整棵树的打印函数是吧?这当然你也可以做的非常的好,就是从上往下打印整棵树。那样的话你的函数就会牵扯到比较复杂的事情。因为你这个。

你会你要知道你整棵树可以是任意形硬任意形状的对吧?所以你。想办法把他们对齐啥的,这个还是。需要设计一下啊,但然这道题本身也是一个仁者见仁,智者见智的一道题。只是想让你大家看一下。

我日常处理一棵树打印的一些。啊,经常出现的一些题啊。关键就是让你熟悉一下便利术的这个逻辑啊。其实你知道的就是。你可以用一种什么样的方式来打印一棵树呢?这个这个咱们开放性的来聊一聊是吧?

你你你可以把整棵树搞成一棵满二叉树,然后再打印它。

啥意思呢?就是说。你比如说我我我有一棵树,明明不是马二叉树。对吧你就但是你可以把它补成版的吗?对吧下面如果他不满的那你就认为这边还有吗?无非就是你把点先站住,然后把该填的位置填上,其实你也能打印出来。

是这意思吧。嗯,这种设计方案也可以啊。就是说他这道题本身是比较开放的一道第一道题啊。就是你你总可以把一个残缺不全的数彻底给他补成完全满的。对吧那你就想办法把这些位置先给占住。那你具体在一个格子上。

如果有值的话,你填进去不就完了吗?这是一种设计思路。

啊,但是我们的题我们的这个实现不是这样的。他本身怎怎么想怎么打印一棵树,还真的方法蛮多的。嗯。那么还没开始啊,就是在等嘛,这不刚刚开始。两点嘛是吧?好,正好我们来讲一下这个题。

这个题我们整体想想设计什么样的一种思路来打印它呢?呃。

想想想这么干啊,比如说。这棵树啊。就是想。这边是打印的这个屏幕是吧?那么你比如说你我想用这样的方式,就是这个三。啊,这是一。这是2。但是我这个别急是吧,我这地方再来一个4。这个一。这个号就是。

它其实是这个样子的。我我我自己打印的图像是你把打印的东西,假设假设你看啊这个这是你的屏幕显示,这前面都是空格。然后一行这个三输出了是吧?然后这前面又一一大堆的空格。然后这个四输出了是吧?

然后这个一呢因为是第一层的节点,所以它前面没空格,或者你也可以补出比较少的空格,那随以你就变是吧?接下来这个二呢,你前面补出一大堆空格。然后我要打印了,对吧?那么你你打印这个这个东西你怎么看呢?

就是你你显示出来这个东西,你心里面把它转个顺时针转个90度,其实它就转过来了,对吧?你看你你你这是你这个图像是吧?你顺时针转完90度啥样啊,1234想象一下对吧?想象一下。想象一下是吧。

把它把它顺身转90度,其实就是我们原来这棵树了。那我是用这样的方式来打印的。啊,你要是看的不明显呢。那我们有办法让它变成明显的啊,这个倒不要急是吧?但是这种方这种设设计思路,它其实比较好实现。

那我们来想一下,我们先不管它怎怎么实现了。你看你每一行输出的顺序是个啥顺序啊?你先打印3,然后打印4,然后打印一,然后打印2。这个这个从我们递归上来讲,它应该是一个什么样的便利呢?先右再投在左的便利。

先右对于每棵子树来说,先又在投。在左的便利。听老他要打一。好嗯,那么我们为了实现这种打印是吧?当然我我说了这道题本身仁者见仁的对吧?你可以给他完全不转的方式打印。那样的话你。设计的时间比较长。

那函数可能会比较复杂啊,那我们就不说了,我就只看一下这种打印,你想怎么打。

你像我最终给你做出来的版本,你看啊,我给你搞出来搞了一大堆是吧,这些数各种连接是吧?你还得保证你还得保证它的它的值不同的时候,你得对齐,对吧?你还得保证能区分出来。所以我们看一下这些这几棵树是吧?

你看我们第一棵树好多好多植,它长度其实是不一样的那我们显示的树的样子,你看给你加了这种样子。它就很好看了,怎么看怎么好看呢?你这个6。他是哪?他的副极点在谁?完,准备给他加个箭头,你看到了吗?

给加了个箭头。那它应该是什么样的一个结构,这个数是啥样子的?其实你是非常好想象的。如果不加这个这线箭头的话,你可能很难想象。加了箭头之后你就没有那么容没没有那么难想象了。这个HH啥意思?

就是这个一是头节点。😊。

对吧这一是头节点之后,你怎么画了?你就这这不写个一不就完了吗?头节点是吧?😡,然后。下面的这个三,它的复指针是指向左侧偏下的这就是这个下箭头的含义。对吧说左侧这一列偏下的那就挂在一上了嘛。

那这个负这么多2,那是它的负节点是这个箭头是往上的那就左侧偏上的那就是挂在这底下了嘛,对吧?你会发现这个很容易看的,其实。我是负一大堆二是吧,负一大堆2啊。

然后。你往下这个六跟这个五很明显是挂在这个三上的吗,是这意思吧?然后那你就写嘛,你看这个函数它有个啥好处呢?他把你东西都对齐了是吧?我之所以说你想搞出别的方式打印不容易,就因为你得想办法把它值对齐。

哪怕。

那么你你如果要是正着打印的话,你其实光对齐这个问题你要想的很复杂的啊,这个那这个五呢就是往上它为什么箭头往上啊,它是附接点左侧偏上嘛,然挂在这个伞底下的嘛,所以它就是。

就就就就就这个在在在这儿嘛,对不对?是多少一对5是吧?一对5嘛啊,然后你底下接着继续是吧?

你看你这个负的系统最小值挂在哪的,我的附节点是我左侧偏上的,那就它底下嘛,那你就连上嘛不就完了,是吧?

怎么连啊,就这样连吧。对吧这是负的系统最小值嗯。

然后呢。这个七它要是挂在这底下的对吧?我的负极点是我左侧偏下的嗯,那你就知道是这棵数吗。

对吧。付777啊。

对777。哦,那这棵树怎么看呀?还是一样,顺时针转90度不就完了吗?你可以想象吧,是吧?哦,那这个东西怎么实现?那就像我说的。

你这样这样理解下来,那你底下每一棵树这样你都可以很顺利的打印出来。你怎么加这个箭头,其实就决定了你附节点怎么调用的。啊,我们来看一下这个函数,并不难理解怎么做的。看。首先我要告诉用户。

我现在要打印一棵二叉树了,是吧?来个回车。接下来呢就是我我打印的过程,它就是一个这个函数啊,我把这个过函数打完之后,不要忘了最后提醒哎,再换个行。所以他关键的理解不就是这个函数吗?对吧这个函数是干啥的?

现在来到的节点是谁传进去?这个H所在哪一层的高度传进去,假设我默认以零开始,或者你默认以一开始无所谓。对吧头节点在零层或者头节点在一层无所谓。那么他是一个什么身份呢?这什么叫身份呢?就是它是头节点。

也就是说我们往下传的时候。😡。

如果没有往下传的话。那么。他一的一的身份,他是知道的,他要掉了他右右边的孩子,他就给他传一个下箭头。就是说对于这个他往下走的时候,这个三对于这个三来说,我的身份就是下箭头。😡,到这儿的时候呢。

我的身份还是下箭头。到这儿的时候呢,我的身份就是这一个上箭头,这个箭头是谁给他的,复函数调用给给他的对吧?你比如说我一开始这个头节点,它的分身份就是一个H,我就得到了。那这就这玩意儿就是我的身份。

他表示你要指向哪儿。那你看一下我我。😡,我如果中间这些过程我都不看蓝色部分我都跳过,你看我怎么调用的。最后一个参数,你先别管,我会给我会给你解释的啊,最后一个参数你先别管,我会给你解释的。

复函数掉了一个头阶点在第零层,它的身份是H。接下来我先调右数,最后调左数,中间部分全跳过,对吧?我先调右数,然后调左数。那么我的右数跟我的左数,它肯定是高度加一的。我右数得到的身份就是下箭头。

我左数得到的身份就是上箭头。听到他要打一。就是其实你是可以得到一个身份的,是吧?其实你可以得到一个身份的。你你你发现你是在吊你的右孩右孩子的过程。😡,你你想让他怎么找到他的父,这不就是我们刚才说的嘛。

对吧?😡,理解这意思吧啊,那么这个lasts是干啥用的呢?😡。

其实是为了处理你自己当前节点值怎么打印的?好,我们这这中间这一坨大码,你别看很多,实际上并不难,为什么?他的逻辑就是假设我有一个节点啊,我现在来到了一个节点,这个节点现在目前为止是no。

我怎我怎么打印我自己的纸?我要打印的时候,我前面要留多少空格是由我的层数决定的。哎,合不合理?我们怎么做到头节点上面,前面没有空格,一旦跳了一旦往下跳了一层,它在打印的时候就留出很多足量的空格。😡。

然后再往下跳一层,就下框打印的时候,就再就是你你你一个数,它一行只输出一个数。那你怎么知道你要输出多远呢?肯定是和高度相关的。😡,一个节点你扎的越深,你在深你在输出的时候,其实你前面留的空格数量越多。

这个前面留空格的数量其实是和你的高度相关的。正相关。你可以认为,如果我在第零层,我前面就预留零个空格。我在第一层,我前面就预留10个空格,我在第二层我前面就预留20个空格。

我在第三层我前面就预留30个空格。😡,你不就基本上大致对齐了吗?好,那么第四个参数是干啥的呢?第四个参数就是说我自己的值可能很大,对吧?比如说我这个值我是个十进制的数,我是一个十进制的数,我是222。

那么我这个我这个我我自己的值占的长度就是3个。😡。

那你想一想,如果整棵树它的值它的本身直的长度相差特别悬殊的话,你只预留出空格,是不是还是可能会乱掉啊?所以传一个l是啥意思?就是我不管我长度是多大,我都搞出一个这么长度的东西,字符串打印出来。啥意思?

比如说我我我不管你这个十进制数有多大,我就给你准备17的长度,那你怎么得呢?你就你就一个值,你怎么准备准备17的呢?好,我左边。😡,8个空格,右边8个空格,我们整体这算我值的部分。

然后我前面还有多少空格跟我高度相关给它补齐。就是我我不管我自己的值是多少,我统一我就认为我只占17个空间。那你如果你是323百这这么多呢,那你就是。😡,17减4是13对吧?17减4是13,对吧?

你左边预留6个空格,右边留留7个空格。总而言之,你不管是什么值,你都预留一个总长度,就是17长度。😡,理解这意思吧?就是我自己的值占多少位,我自己的值占多少位,我给预留好前面补多少个空格。我们刚才说了。

跟你的高度相关,这样一来我不就能保证对齐了吗?😡,听到他在打一。啊,所以我们这个东西是啥?你这它没有那么复杂啊,你看你右边是便利了,它他到下一层去是吧?我给他一个身份,他往下指左数,他往下层是吧?

我给他一个身份,他往上指主函数一直传这个时期,就拿17做。你会发现最后一个参数是永远不变的。

我不管调用什么子过程。我我就永远让一个值占17长度,因为我是十进制的数,我实际长度绝对够用了。所以你看接下来干啥的。我先把我的值处理好。左边加一个我的身份,他该是上箭头就是上箭头,该是下箭头就是下箭头。

该是H就是H。就是这个部分。嗯,等一下。就我加个身份,你看这是我前面的身份,这是我后面的身份,中间是塞我的值对吧?这是我前面的身份,这是我后面的身份,中间是塞我的值,对吧?这些身份都是我附节点给我的。

😡,好,接下来往下。😊,那么我这个value它就它就有一个正儿八经中间占位的这么一个长度。我就算一下,我左侧我如果总长度是17的话,我拿17减去我占位的长度,除二就是我左侧贴多少空格。

剩下的东西就是我右侧贴多少空格。所以我自己的value就是我左侧空格数,加我自己本身的值,再加我右侧空格数,这个是绝对是每个值都严格一样大的。我在打印的时候怎么办?我前面根据高度补出这么多空格数。

再把我的值塞上。搞定了。听到同学打一。啊。啊,现在在讲这个怎么直观打印一棵二叉树啊。哦,会了是吧?行啊,那这个这个这个其实你自己回去玩一玩是吧,你也可以改出比我更好的是吧?无所谓啊。

也是作为一种递规的练习,它本身并不是想干啥是吧?啊,就是给你熟悉一下一种二叉树,我怎么去设计。

好,我们接下来讲题目。嗯,这里已经讲过了,早上的是吧?系。一个二叉树的结构定义如下,哎,这个二叉树的结构定义有意思,它多了一个往上指的父亲指针。注意啊。

一那个在我们这个其实很多树的结构呢都会加上一条往往上指的指针。比如说我们经典的这个嗯红黑树设计,它就是往上加了一条往往上指的指针,每一个节点有3条指针,左指左孩子右孩子跟指向我父亲节点的指针。

那么你要注意。我一般在刷题的时候,不是我一般是一般在刷题的时候,如果你遇到一道二叉树的题。你默认他只有左右两个孩子是没有往上指的指针的,理解这意思吧?这是我们预设的刷题环境,除非特别声明。

在这里面我就特别声明了,它有一个指向负的指针。那么我假设我只给你二叉树中的某个节点,我不给你投。但实际上,因为每个节点有指向父亲的指针,你是可以找到头部的这是肯定可以的。你就往上指呗。

头节点的父亲指针指向谁,你可以规定它指向空,对吧?头节点整棵树的头节点的父亲指针,你可以规定它指向空。所以说我给你二叉树的某一个节点,其实你是可以便离到整棵树的。好,但是我只给你这个节点。

数中的某一个节点,请你返回该节点的后继节点。我们解释一下这个后继节点是啥意思。

后继节点。它指的是一棵二叉树中,在中序遍利的序列中,一个节点的下一个节点是谁?就是后继节点。举个例子。比如这棵树中续遍利的结果。4251637。

所以我就说四的后继节点是22的后继节点是55的后继节点是1一的后继节点是66的后继节点是33的后继节点是77没有后继节点,它后继节点是空。这就是后继节点的定义。好,那么我随意给你个节点X。

请你返回它的后继这个东西最简单的做法就是你让X不停的搞到头部,对吧?你你我不管你X在哪,我都给你找到头部,整棵树的头。然后我就给你实现一个中序便历的序列。然后我再便历这个中序变历的序列,找到X的下一个。

那是肯定可以做的。😡,有关于后期阶点定义以及一种普遍的解法,已经会了的同学打个一。嗯。好,那么这道题就是我我我因为我每一个节点都有往上指的指针是吧?我是可以找到整个的头部的。

所以我就可以从头节点开始去玩一个中序便利,把这个序列收集上来,然后找到X中的下一个X在这个序列中的下一个,这个是暴力解,肯定是可以做到的。但是。是不是麻烦呢?你中序便利,我们说不管你是先序变历。

中序便利还是后序败便利,本质上都是递归序的便利,而递归序的时间复杂度是多少啊?每一个节点只到达3次。所以如果节点数是N的话,我甭管你是什么中序先序后序还是什么递归序,一律复杂度,B个ON。哎。

这个点听懂朋学打一。对吧。这个点听懂同学打一,因为我不管你是先续中续后续,你只要是递归序,递归序也是一个节点到达三次,有什么关系是吧?都是B勾N的。😡,但我问你真的需要吗?来,我们来看一下。

你比如说四节点到它二节点,四节点的后继是二,在这棵树上实际的距离是多少?四节点到二的实际距离才是一。而二的后继节点是5,2节点到5的距离是多少?其实它也是一。我有指向负的指针,按道理来说。

我都可以直接到达的。😡,五的后继节点是谁?是一?那么5到1的距离是多少?往上走一位,再往上走一位,后继节点才是2。一的后续节点是哪?一的后续节点是6,所以一走往下走,再往这儿走,它其实能走到6。

它截它的它的这个代价也是26的后续节点是3,距离是一三的后续节点是7,距离也是一,哎,有意思。我就萌生了一个想法,如果你给我实际的一个X节点,我能不能用一种策略,我直接去找他的后继。

有可能比整个便利完成再处理代价更低哦。😡,假设我一个节点到它后继的实际距离是K的话,我希望我的算法做到B个OK,而别每次都是B个ON。懂我想干什么同学打个一。好啊,那这样一来。

我们就要对一个节点的后继节点怎么找这件事情去调研一下了。没错吧,你原来可以不用管一个节点的后继,跟自己是什么样的结构关系。因为对您来说就是很傻的一件事儿。从头节点所有便利完了之后,他爱什么结构关系。

什么结构关系,我才不关心呢。😡,但是是不是不够好呢?是因为复杂度高,它实际距离物如果是K的话,你要想用在BOK的时间内找到这个解,那就需要调研一个节点跟自己后继有哪些结构关系了。好。

我们先说一种最简单的。假设X节点它有。右树。我问你他的后继是谁?必然是它右树上最左的节点。为什么?中序便历的顺序是先左再投,然后右的,你就把X假设为头。那么如果真的打印的话。

谁是最X接下来要打印的东西呢?如果是中序便利打印的话,谁是X接下来要打印的东西呢?毫无疑问是它右数上再去拆分左投右。拆分的结果就是右数上的最左节点,一定是X的后继。听懂他学打一。这是X有右数的时候。

这个结构关系是很显而易见的那我那我X的下一个节点一定是右数上最左的节点。😡,这种是最简单的。那下面我们来想一个问题,如果我X没有有数呢。啊,中区便例好多呀,是吧?那我们就都都列一下。应该是对的是吧?好。

我们看一下,如果没有后继的节点,没有右数,它的节点后继是谁?你看比如说这个I就没有这个H,它就没有后继,没没没没有右数。那后节也是D。附节点。这个I也没有幼数。他的后继节点是B。这个J也没有右数。

它后一节点是E。我们在这练。这K也没有。右数它会几点是A。这个关系直接告诉大家。如果一个节点。他没有右数的话。😡,你就往上找。😡,如果我跟我的我是我副节点的右孩子。😡,你就继续往上找。

如果他还是他父节点的右孩子,你就继续往上找,一直找到某一步。这个节点是他父亲节点的左孩子了。这个父就是当初X的后继。我们来套一下,然后再解释为什么,你比如说我这个H没有后继啊,我这个H没有右数。

我就往上找,我是我父亲节点的左孩子了,就停,那个父就是我的后继,所以你看有他第一回往上就发现是自己父亲的左孩子,所以D就是我的后继。😡,你再看这个哎,我说我父亲节点的右孩子不行,一定要找到左孩子为止。

所以再往上D是B的左孩子。所以这个父。😡,就是我当初挨的后继。这个G也一样,我没有右数,我往上找,我是我父亲节点的左孩子,所以E就是我的后继。这个K我往上找一步,E是我的父,但是我是我父亲节点的右孩子。

我就继续往上E是B的右孩子不行,一定要左孩子为为止,所以继续往上。😡,B是A的左孩子了。停,那么当初K节点的后继它就是A。这个这个这个这个这个标准听明白同学打个一,我会给你解释道理。😡。

就是你不停往上不停往上一直到某一组父子关系,这个子是父亲节点的左孩子了。停。😡,你找到那个负,就是当初那个节点的后机。就这个意思很很很容易理解吧。那他是为啥呢?😡,我们想。你的目的是想找X的后继。

那我那你看这样,那你看这个这句话对不对?😡,如果某一个节点,它左数上的最右节点是X。则这个问号就是X的后继。再来一遍。如果某一个节点,它整棵左树上最后打印的节点,也就是最右节点是X的话。

那么这个问号就是X的后继。听懂他在打一。没懂好,什么叫中续便利啊?中序便利是先左在头在右的便利。我现在说的是这回事儿,我说某一个头它是一个问号,然后我明确的告诉你,它左数上最后打印的节点是X。😡。

然后就该打印这个问号了。😡,以中续方式便利的方式打印的。那么这个问号毫无疑问,它就是X的后继,这难理解吗?😡,我不假设X为头,我假设X的后继是头。😡,那么这个X的后继是头的话。

这个这个问号应该跟X具备什么样的关系呢?要求的关系是这个X一定要是它左数上最后打印的节点。听懂他打一。嗯。对吧你想想什么叫中序便利啊?如果你有你中序便利都是先左在头在右的。我假设某一个节点X。😡,我。

假设某个节点问号X是它左数上最后打印的节点。那我找到的这个问号就是X的后继嘛。😡,理解吗?好,那看我们刚才在干啥,我们不就是在干这种事儿吗?如果X他跟他父亲是右孩子的关系。我跟我父亲是右孩子的关系。

那此时我并不是这个节点左书上的最右。😡,所以我就继续往上,如果这个节点跟他也是右孩子,他是他父亲右孩子的关系,那对于这个节点来说,他的左数上的最右节点也不是X。😡,你一直往上找找到某一步。

这玩意儿开始是我是我父亲的左孩子了。😡,你看你打眼看一眼,因为X底下是没有右数的。😡,那这个X是不是这个节点左数上的最右节点啊,你中续便利是不是打完X就一定会答这个问号啊,你不就找到了吗?😡。

听审他学打一。嗯。梅懂打2啊。好啊。啊,那就是这个意思是吧嗯。对,如果X有右数,就直接右数上的最左节点了。如果X没有右数,你就往上这么找,但是你不要忘了。整棵树的最右节点。他是没有后继的。

那整棵树最右节点找的时候会是什么状况啊?我他我找他的伙计。哎,我往上我是我父亲的右孩子,我再往上我是我父亲的右孩子,我再往上。哎,我再往上我父亲节点就是空了。如果你一直都没有找到一个节点。

是这个父亲节点的左孩子的情况,那他一定是整棵树上最右的节点,你返回空就行了。你只话。整棵树最右的节点,它就是没后继的。

好,我们看一下这个代码。这代码特别好理解啊,你是真的好理解。你比如说我就给你一个节点,我告诉你这个节点不是整棵树的头,它就是这个树上任何一个节点。有可能你看这个节点是由左有右由指向负的指针的对吧?

那么这个节点你看如果他等于空的话,你让我找什么后继呢?你压根就没给我节点,我就给你返回啊,你自己玩吧,是吧?如果我node的右孩子不等于空,说明啥?我有右数。既然我有右数。

我就找到我右数上的最左节点这个方法在这儿不断的往左往左往左往左左到不能再左了,返回。好,有关于这个第一个逻辑分支,看懂同学打一。好,那么接下来就像我们刚刚说的,如果一个X它无右数。嗯,还是放这儿吧是吧?

还是放这儿吧。如果如果它右数是空就进入al,如果它无右数怎么办?先把node的parent找出来。注意看,先把node的parent找出来。接下来我再找什么样的情况,我这个w怎么能继续?

就是我一直发现当前的节点和自己的父亲是幼孩子的关系,我就继续。看父亲节点如果不等于空,并且父亲节节点的左孩子不是no的。就是说我有父亲节点,并且我不是他的左孩子,那你一定是他的右孩子。

你也可以等效的改成这个。😡,都是对的。所以我这么写最直白是吧?如果我附近节点不等于空,并且我是我附近节点的右孩子。😡,我来到父亲的位置,我父亲在往上。这一次就是往上登两个,一次往上登两个,看到吧?

我note上到parent的位置,parent,你再往上移动一个。😡,在这个well里面周而复始。只要我发现当前的子是,他父亲的右孩子就往上,只要发现是右孩子就往上,一直到什么时候停。😡。

我是我父亲的左孩子了,停返回父亲是对的,或者我父亲节点变成空了,直接从well里面出来,返回空节点也是对的那什么时候会返回空呢?给你的n是整棵树最右节点的时候。看到同学打一。嗯。第二7行会空指针异常吗?

不会,为什么?因为我限制住了parent不等于空。如果我限制住了parent不等于空,那么node来到parent的位置,它怎么可能parent没有呢?这就是为什么我要加一个parent不等于空的原因。

你不说27行会不会控制任异常吗?不会,因为n它 node来到的是parent的位置,而你为什么能进到这个外里面来?是因为你pit不等于空。😡,不会控制人异常。嗯。啊,这就是边界考虑啊。好啊。

那就是这个题是吧?那同样道理我跟你说前驱节点啥意思啊?

什么叫前驱啊?后继所对应的就是前驱。对吧所以你后继会讲了会会搞了前驱怎么做呀?哎,如果一个数有左孩子有有左数的话,它左数上最右的节点就是它前驱,否则怎么怎么样,那对等的就不再多说了吧。你你会找后继。

你反一下,你就会找前驱啊,后继节点跟前驱节点都指的是在中序遍历中,一个节点的前一个或下一个的概念,好吧。

这就是我们的后继节点。好,我们再看底下这个题。我开一下摄像头,大家。这个看一眼题目,这道题是要求大家互动的,准备两个纸条和一支笔。这道题非常好玩。这道题在国外流行了一年多,从微软开始流行。

facebook谷歌全考过准备两个纸条,干净的,没有折痕的纸条,纸条就行,然后准备两支笔是吧?我我也准备一下。嗯。Yeah。哦,开一下摄像头啊。好啊,大家准备好了吧啊。😊,这个。纸条是吧。

那我们来展示一下这个怎么折啊,这个怎么折,你别说好了是吧?我开个摄像头,你说你好了,哇,这个吓死我了是吧哼?😡,啊,开个摄像头,哎,我好了是吧?😊,哎。太逗了。嗯。来啊这个。我们我们正面对这张纸条是吧。

这么面对这张纸条。然后你从下方往上方这样对折是吧?从下方往上方注意你纸条千万不要翻面,也不要上下颠倒,握住了它。什么面对着你,永远什么面对着你。😡,也不要让他翻面,也不要让他上下就捏住。

不然的话你会折乱的哟。😡,从下方往上方对折之后。打开。你会发现你有个折痕,这个折痕呢,如果你这么看的话,它是凹下去的。对吧我们管它这个折痕叫凹折痕。啊,它这个折痕是凹下去的,没错吧。好。

然后我们恢复成折的样子,恢复一下。就是刚才你折了一下,不是这个样子嘛,对吧?你再从下方往上方对折一下。然后给他打开。这个时候你会发现你有三条折痕。😡,上面两条是凹折痕。最后一条它是一个凸起来的。好。

我们就管这样的折痕叫凸折痕。😡,这个问题就是说。😡,我让你对折N赐。让你打印所有折痕的方向,从上往下打印。所以如果我给你输入二的话,就是对折两次,你就应该打印出来凹凹凸。那么如果给你任意一个N值。

你给我全部把折痕从上往下方全打印了。该怎么实现?听懂提议,同学打个一,以及跟我折的一样的同学打个一。嗯。哦,没关系啊,刚看不到画面无所谓。我现在让你做一件事儿,再拿出一个纸条,没折过的。再拿出一个纸条。

没折过的,现在能看到了吧,现在能看到了吧。啊。好,你拿出一个你拿出的干净的纸条,我们现在来做这样的事情,从下方往上方对折一次。干净的。打开。是不是有一条凹折痕,它是你第一次折的时候出来的对吧?好。

你在这个折痕上画一条线。并且在这个上方用小字写EO。来做这件事儿。折完之后就应该写完之后就应该是这个样子是吧?你这个折痕上画一条线,然后写个一凹啊,非常清楚是吧?好,然后。我们把它恢复成折一次的样子。

进行第二次对折。折完之后打开。现在出现了一个规律,叫你划线的折痕,上下两方出现新折痕。上方出现凹折痕,下方出现凸折痕。好。两条新的折痕上面这一条你画条线写个二凹底下这一条折痕,你画条线写个二凸。

写完之后就这样是吧?对吧那为什么糊了?好,那么。你把它还原成折两次的样子。千万别翻面儿,也别上下颠倒。进行第三次折。你再打开。你会发现在你上一次折出来那个二折痕的上下两方,上方都是凹折痕。

下方都是凸折痕。理解这个规律,同学打个一。在你第二次折的折痕的上下两方出现两条新折痕,上方出现的都是凹折痕,下方出现都是凸折痕。所以我们有理由相信,如果我们的每一次折新的折痕都会跟我上层的折痕。

上下两方出现,而且上方都是凹折痕,下方都是凸折痕。没错吧。没错吧。好,那这玩意是啥?能看到屏幕吗?能看到屏幕,同学打个一。我现在摄像头关了。

,我们来想一下。这是纸条。这是纸条的上方。这纸条的下方。你第一次折的时候,在这个地方折出一个折痕来。是一凹。当你第二次折的时候,在一凹折痕的上方出现一条凹折痕。

在这个纸条的在这个折痕的下方出现一条凸折痕。然后你第三次折的时候,在每一条小二啊每一条二折痕的上方都出现凹折痕。每一条的下方都出现凸折痕。所以你想从上。到下打印所有折痕的方向,就是这棵树的中续便利。

听到台打一。啊,那你就会想了,我靠,难道我要建出一棵树吗?你不用建出一棵树。很多同学会想,哎呀,我最终能算出啊,我不我不搞你这个数是吧?我不我不根据我不根据你这个数的分析方式来分析。我就自己想。

我发现每一条规律就是如果有N,你让我对折N次,一定会产生二的N次方减一条折痕。然后你就根据这个N做出来一个好大的一个数组,长度是2的N次方减1,我看怎么把这个数组填满。然后我再依次打印这个数组。😡。

它不是不行,但它会巨大的浪费空间。你要准备一个长度为2的N次方减一的数组,把它填满。那么当你有了这种模型之后。我们来看一下,你真的需要建出整棵树吗?其实你并不需要,为什么这么说?来。

我们来看一下这个code。

这个打印函数有多么简单?

就这么短。那他怎么理解呢?

如果我折三次的话,就把这个三传进去。所以它是我的主函数,打印所有折痕这个主函数。直接进了一个递规。那么关键就是怎么理解这个递归。好,我们说开始看这个递归有三个参数。

这个递归第一个参数指的是我当前来到的过程。你可以认为你当前来到的过程就对应着一个点。就你你当天来到这个过程就对应着一个点。我没有真实的node,我们怎么样的表示node的递归的调用来表示的?😡。

当我来到这个过程的时候,就认为我来到了一个点。那么你当前来到的这个点是第几层的点,它就是I这个值的含义。所以我主函数要传一,因为一上来头节点出发,它必然是在第一层的。第二个参数是一个固定参数。

它是不会发生变化的。它指的是我最多有多少层。固定参数它以后再调用的子过程,第二个参数都不会发生变化,它就代表我一共有多少层的意思。第三个参数就代表我此时的点。是不是凹折痕的点?如果是凹折痕的点。

它就是处。如果是突折痕的点,它就是fse。所以主这个含义定了主函数应该怎么调用。我当然从第一层的点出发,一共有N层头节点是凹折痕的点,为什么?

因为必须是这样的。你这棵树有什么规律?你左子树的头部全是凹折痕,右子树的头部全是凸折痕的这么一棵树,这就是这棵树的规律。

所以我我的头节点一定是传触的。然后大家看。那这个函数怎么理解呢?假设我们有三层,我们看这个函数是怎么调用的。全擦了。也就是说这个函数这个N我就单独抽出来了,因为它是永远不变的。

我就不把它作为状态代表的参数了。我第一个过程我就会掉了F1O嘛,为啥?因为我掉了个处,对不对?主函数调的是F一O嘛,我就说我把这个中间这个参数给省掉了,因为它每次都是固定不变的,所以我就不看它了。

主函数是不是掉了一。

凹啊,我给的是处,当然是凹的意思,对吧?所以主函数掉了一凹哦,没问题。然后你看它怎么掉的。😡。

I大于N了吗?没大于N为多少,因为N是3,我规定好N是3,它是个固定值。3,我就打印三层,假设对吧?我假设我就打印三层,你也可以去假设四层,你也可以假设五层,那你这棵树就画的很大无所谓。😡。

先假设它是N等于3好吧。

然后看。I没有大于3。我先调用的是下一层中。

凹折痕的点。所以好你直行不下去了,我需要你调子过程F2O。

因因为什么我传的是处。然后2凹就进到这个函数里来了。2它这是二层的,它有没有超过N,它还是没有超过N,所以它还会去掉什么?调三凹。

那么三凹执行进来之后,它还是没有超过N,因为它现在是三,它没有超过3,对吧?它又去掉什么,它会掉了四凹。

但是四凹调用的时候,他其实什么都不会做。为什么?因为四凹一进来就reen了。😡,四凹一进来就return了,所以它会回到上游的三凹上。

当我再次回到三凹上的时候,就等于说三凹的过程执行到了。

把这一句执行完了,再执行这个。那我就打印了我的折痕凹。

他就打印了一个折痕哦。

接下来他又去调了第二行,我调用4。土兀。

但是四图什么都不会做,因为此时的四是超过三的,所以四图一旦遇到他什么也不会做,直接return我的过程彻底结束了。我返回到2O的时候。😡,我就会打印哦。然后2奥又会去掉三图。三突会调它返回来。

第二次返回,它打印突再去调右边什么也没做,返回,彻底往上返回,然后再往上第二次回到一的时候打印这个哦。其实你就是拿地规模拟了你脑海中的树,但这棵树其实从来没有被建出来过,但是你拿地规过程模拟了它。

听懂同学打一。为什么你不需要建出整棵树,你也可以完成所有节点的打印。因为这棵树是有明确规则的,左数节点都是凹,右竖节点都是凸,头节点默认也是凸的这么一棵树。既然这种明确规则的数。

我当然不用建出所有的节点才能够打印。有什么问题,完全没有问题。但是这个空间复杂度是多少?递归站的代价,递归站一共才开N层,你这个递归函数最多压N层,所以我是额外空间复杂度就是一个B勾ON的事儿。

它是不是比你做出一个数组都填好,再打印达到B勾2N减一的空间复杂度要优秀啊。

就这么简单的代码。好,我们想说什么呢?我想说的是,为什么我们要开实战班?为什么我给你练完了基础,你要好好去写,因为这就牵扯到了一个问题。一个基本的数据结构,或者说一个基本的算法原型。

你用它是需要敏感度的。那么在我们的课上会先打基础,然后进入实战班里面练每一个小东西,每一个底层的底层算法数据结构的敏感度。你敏感度熟了之后,自然你就想到了这个方法了。但是在这之前你就是可能会面对。

虽然你学过该道题不会还是不会的境地。听懂同学打一。嗯。这个代码本身就是中序啊。哦。好,我们现在来讲一个,那还有一个小时嘛,赶紧开始下一节课啊,下一节课非常的重要。二叉树的递归套路啊,这个东西很值钱是吧?

啊,它它可以说是我们整节课,我们的课上小技巧多如牛毛,但大主线就两个,一个是二叉树的递归套路。还有一个就是我们暴力递归,改动态规划的套路。任何动态规划题目都可以解。啊。

那么我们来看这个什么叫二叉树的递归套路。一开始你可能一头雾水是吧?它实际上就是在树上做动态规划。那什么是动态规划呢?动态规划就是用空间换时间的方式,你现在先不用管动态规划的定义,因为树形DP问题。

你可以不去理解什么叫动态规划也是可以理解,能够做的。好吧,我们把这个动态规划的严格定义放在我们最后一节的时候再去做。但此时不会影响你听这节课的。可以解决面试中绝大多数二叉树,尤其是树形DP的问题。

这个绝大多数大到什么份上,95%以上。为什么没有百分之百?因为谁知道哪些面试官犯神经是吧?这个不好确定。但是二叉树的题目由二叉树递规套路解的,可以占到95%以上。

那本质其实是利用这个二叉树便历二叉树就递归序便历二叉树的便利性。因为每一个节点都可以回到自己三次。好,我们先来看一下这个套路啊,这个套路你一开始会看的一头雾水,我们直接把它跳过来看具体题目。

我们每看一个新题目的时候,都利用这个套路告诉你怎么做。用例子加深概念。比如说第一个题。给定一棵二叉树的头节点,返回这棵树是不是平衡二叉树。我知道大家很多人做过这道题。

但是请你忍着听二叉树的递归套路的解法,为什么?因为这个套路你掌握了之后,比它难得多的题目也变得不难了。关键是在于学习套路本身,不在于你会不会这个题。

好,我们看那这个题你想怎么解?什么叫二叉树的递归套路?先讲一下。

二叉数的递归套路指的是我就假设以X节点为头的数。我就假设以X接点为头的数。我看看要想得到我此时的答案。我需要哪些信息?再来说的具体一点就是说。我我我我有一个。潜台词。我的潜台词是什么?我的潜台词是。

我每我任何节点X为头的数,我可以向我的子数左子数要信息。左子树是可以给我信息的。打。柚子树也是可以给我信息的。这个信息是什么,你别管,反正能给我,你爱要什么信息,我就可以给你有这样一个假设。

左子树的信息是可以得到的,右子树的信息也是可以得到的这样一个潜台词。😡,好,接下来你会你怎么想这个问题呢?就是你你先看一下你求的东西是啥。我们这道题比如说是平衡性。😡。

对吧我们这道题具体的它的他的求的问题是平衡性的问题。好,你有了这个潜台词的基础上,你去干一件什么事儿,就是你利用左数跟右数能够给你的信息,你怎么把以X为头的这个问题求解出来?对于这道题来说。

就是假设物以X为头,怎么样它整棵树就是平衡树了呢?😡,我必须满足如下的条件。第一啊,什么叫平衡树?就是在一棵二叉树中,每一个子树左树的高度差呃,左树的高度和右树的高度差不超过一。在一棵二叉树中。

每一棵子树,左树的高度和右树的高度差不超过一,这叫平衡性。那我现在假设以X为头的树,它要想做到平衡性,要满足哪些条件?第一点,我的左树得是平衡的。我的右数第二点,我的右数得是平衡的。第三点。

我的左数的高度和我右数的高度差不要超过一。我们再来一遍。因为平衡性指的是在一棵树中,每一个节每一棵子树左树高度跟右树高度都不要超过一。如果你X左树已经不平衡了,你X是不可能平衡的。

即便你X左树的高度跟右树的高度没有超过一,但因为你左树本身已经不平了,那你就不是平衡树。😡,所以我想怎么让怎么想让X整棵树它有平衡性呢?左数得整体是平衡的,右数得整体是平衡的。

并且我此时左树高度跟我右树高度差不超过一。😡,听懂他要打一。好,这样一来我们在干嘛?就是列出了以X为头。答案的可能性。在什么情况下去列这个可能性的?是在我默认我可以向我左数跟右数要信息的情况下。

我去列这个可能性的。好。

这就是我们递归套路说的。哎,不是这个。假设以X节点的头,假设可以向X左数跟右数要任何信息。在上一步的假设下,讨论以X为头的数得到答案的可能性。好哦,讨论完了。那然后呢第三步列出所有可能性后。

再确定到底需要向左数跟右数要什么样的信息。那我现在看D就是第三步了。那我这个问题,我到底需要向我左数跟右数要什么样的信息呢?😡。

我左述是否平衡,是不是我需要要的信息?对吧你平否。还有我左书的高度,是不是我要要的信息,你高你的高是多少?😡,就这么俩信息,我对我右数要什么信息呢?我的右数一样,右数平否。😡,以及右树高度是多少?所以。

我对我左数的要求和对我右数的要求是一样的。这样我们就列出了你到底需要向你的左书跟右书要什么样的信息。理解到这一步,同学打个一。好,那么接下来我们就用实际写代码的方式。然后去列到底怎么做。

现在的情况是这样的。

现在情况是。我这个信息。结构题我就定义好了。因为我对我左术和我右术要求是一样的。所以我这个info类型是啥?就是。信息返回的结构体。这就是我的音,对于每一棵子树来说,我都要俩信息,你是否是平衡的。

它是个布偶类型的值,没毛病吧。😡,第二点信息就是你的高度是多少,它是一个整形值,没毛病吧。好的,然后呢然后写代码。假设以X为头的数。假设以X为头的数。我也要返回info。

为什么你对因为我们要写接下来要做的是递归函数,你对你左数有要求,你对你右数有要求。😡,你是可以在调用X的时候,先得到你左数上的两个信息,再得到你右数上的两个信息。但问题是他们都是用递归去调用的。

所以你必须规定好X自己要返回的信息,这两个信息你都要返回你才能够说我可以默认我左数给我这样的信息,右数给我这样的信息。换句话讲,因为你对你左数跟右数有这个要求,所以你也得符合这个要求。

因为你们是递归函数。😡,也就是说,原本我是求平衡性的问题,现在我必须要在这个代码里面解决X为头的数,怎么返回这两个答案的问题。只要我解决了这个问题。整个过程递归就结束了。啊,听懂同学打一。那我怎么做呢?

来看。当我X为空的时候,我返回什么样的信息呢?空数是不是平衡的呢?是。空书的高度是多少呢?0。base case这么给完全没有问题。然后我假设我左数可以给我这样的信息。我右数也可以给我这样的信息。

你要注意他给你的信息可是两个值,左数上是否平衡,左数上高度是多少,右数上是否平衡,右数上高度是多少,俩信息都拽到我手里。接下来是我也得加工出我的两个信息返回。那整个函数不就连起来了吗?好,怎么做?😡。

我的高度是最好求的。😡,我左树的高度和我右树的高度最大的那个再加我当前头节点的这一个高度,就是我整棵树的高度。😡,这个信息对不对?对,而且被你左右两个信息加工出来了。那我怎么样叫具备平衡性呢?

我先默认我的平衡整棵树的平衡性是处。如果我左数不平。我改成false,或者我右数不平,我改成false,或者我左右两竖的高度差超过了一,我改成false。😡,如果我没有改fs。

那我就知道我所有标准都验证通过了,我得到处。😡,加工完毕。主函数怎么调?主函数把整个had传进去,最终只要它exsbal的值。但是你为什么要准备高度?因为你的平衡需要它来决策,所以你塞俩信息。

但是主函数只要你是否平和不平。听到同学打一。这就是二叉树的递归套路,他说起来很直白,告诉你威力无穷。😡,我们这个二叉树的递归套路,它既告诉你你应该怎么想问题。😡,你应该怎么想问题怎么想。

就是我假设我左右两竖可以给我这样的信息。😡,可以给我我想要的所有信息,我只要以X为以X为头的数,整棵树的答案在在我前提假设可以要信息的情况下,把所有的可能性整理好。我再通过我整理好的可能性去反推。😡。

我左右两数应该给我什么样的信息,我都拿到手之后,我自然可以整合出我应该返回的信息。它和我的左右两个数要求是一样的。这是大思路。为什么要判断三个条件呀?你看。😡,你或者可以这么写。

我先默认我的平衡性是fs。如果我左边的数是平衡的。并且我右并且我右边的树。是平衡的。并且它俩高度差没有超过一,我给它改成处也对,等效。听懂同学打一,刚才问问那个问题的同学,你是不是想问这个?

对吧我可以我可以让它默认为false,它成立,我就给它改成t,我也可以先默认它为 true,它有一点违规,我就给他改成false,有什么区别?😡,刚才问那个问题,同学不就是这个意思吗?就是这个守核同学。

你现在理解了吗?😡,为什么要判断三个条件呀?不是只判断左数右竖高度差就可以啊,不是啊,不是什么意思?

平衡性它指的是它不光你对你X自己这个节点有要求,它是X为头的所有呃以以X为头的整棵树吧。什么叫平衡性?是至上面的每一棵子树都满足平衡性,这叫X的整棵树都有平衡性。😡,我们举个例子。这个节点是X。

它左数它左数高度是3,它右数高度是3,它自己不违规,但它是平衡数吗?不是为什么这个节点它违规了,这个节点它左数高度是零,它右树高度是2,它不没有平衡性,懂啥意思吧?什么叫平衡性,就对每一棵子树都平衡。

这叫整棵树具有平衡性?😡,听没听懂。

啊。听懂了吧?所以我所以我不能呃所所所以我为什么要纠结左右左我左术是否整体平衡,我右数是否整整体平衡,然后我自己达不达标,理解这意思了吧啊。😡,嗯,这个代码就是肯定是对的,是吧?好,这个这个都是毛毛雨。

这个并没有什么炫酷的,因为这道题本身特别不炫酷。那我们来一个男的。啊,不是说来个男的女的啊,来一个难度高的是吧?

哪个难度高的呢?看最后一个啊,我们来X看一眼,假设以X为头的数,假设X的左数跟右数可以要任何信息。在上一步的假设中,讨论以X为头的数得到答案的可能性。在确定可能性之后。

确定到底需要左数右数提供什么样的信息,把左右两棵树的信息求全集。这个我们还没有遇到,因为左右两棵树的要求是一样的,所以你不需要求全集。但是我们会遇到的时候啊,这些题给你为什么准备这么多题。

就是未人把这个套路彻底打通的。每一个点我们都会讲。现在。然后你看啊,如果你列出了信息,如果你列出了信息S之后,递归函数都要求返回这个S,每一棵子树都这么要求写代码的时候。

考虑如何把左数信息跟右树信息整合出整棵树的信息。这就是整个二叉树的递归套路,换一道难的点的题。这个。给另一棵二叉树头节点head。任何两个节点之间都存在距离。😡,返回整棵树的。最大距离啥意思?😡。

有一棵树。我说任何两个节点之间都存在距离,这个节点到这个节点存在啥距离?就是你从它怎么样用最精简的方式走到它怎么怎么样呢?通过第一个节点,通过两个节点,通过三个节点就到它了。这是最精简的方式。

什么叫最精简,就是你走向它的过程中,任何节点都只能经过一次。😡,在这样一条路径上,一共有几个节点,就叫做两个节点的距离。所以这个A点到这个B点的距离就是3。那么任意两个节点都有距离。

比如说我从这个节点怎么走到这个节点是往上走,再走这儿再走这儿1234。所以我说如果它是C,它是D的话,那么C走向D的话,它一共的距离就是4。😡,这棵树任何两个节点之间都会存在距离。我问的是。😡。

整棵树的最大距离是多少?听懂提同学打个一。嗯。你如果要是不不不你如果要是最暴力的方法,你这个问题你怎么解?我靠,你把所有节点都拽出来,任何两个节点之间一共有多少对儿?😡,任何两个节点之间一共有多少对?

N方对,那你这样求你就没头了。新息人类同学说,最大距离就是从最左到最右,对吗?轻松给你画出反力来。😡,最大距离是从最左到最右吗?不是是从这个点到这个点。大。听有他要打一。这距离你感觉好烦啊,对吧?

我怎么求这个呀?想想我们的递归套路。😡,假设我们可以向我们的左数要信息,什么信息都行,可以向我的右数要信息,什么信息都行。我现在干嘛?以X为头的数最大距离应该是什么可能性?常见的分类。

注意递归套路最难的部分就是列可能性,但是它是有套路的。常见的套路分类时,这个最大距离是跟X有关还是无关?第一点,如果我整棵树的最大距离跟X是无关的。什么叫跟X无关?就是你最大距离连通过它都不通过X。😡。

这个最大距离压根儿跟X就不不经过X。😡,那你的最大距离是什么?左树上的最大距离或者右树上的最大距离。我们来举个例子。你X整棵树的最大距离是从这个点到这个点走过这样一个叉。

这个最大距离压根儿跟X一点毛关系都没有,它就是我左数上的最大距离。听懂他来打一。听懂了吧?所以该X跟跟X无关,都跟它无关了,必然不会是跨过它嘛,所以要么是我左数上的最大距离。😡。

要么是我右树上的最大距离。这这是第一种可能性答案。那你选哪一个左数上的最大距离跟右数上最大距离中最大的那个。右数最大距离同理对吧?好,第二种可能性大分类,这个最大距离跟X是有关的。什么叫跟X有关。

就是最大距离通过X呗。那是哪种情况?X左数上离它最远的点,一路走来走,走到X走到哪去,走到X右数上离它最远的点。只有这一种可能性。听懂同学打一。好,那什么叫X左数上离自己最远的点呢?左数的高度呗。😡。

左X离自己最远的减点走过一个左数的高度,加上X自己这个节点走到哪儿去,走到X右数上离自己最远的减点,那也就是右数的高度。所有可能性都列全了,不可能有例外。常见分类就是你这个答案跟X有关,还是跟X无关。

这只是常见分类而已。可能性的分类可能有很多种,无所谓,都在套路中。理解吗?好,我们现在写这个代码。那你对你左树的要求是什么呢?要求你给我返回整棵树的最大距离,以及你的高度。😡。

那你对你幼树的要求是什么呢?返回你整棵树的最大距离,以及你的高度就俩信息。

直接写扣的。上面都是验证方法,写给你写了个暴力的啊,上面给你写了个暴力的。这是。这个是我们要讲的,就俩信息,整棵树的最大距离。以及整棵树的高度。好,开始假设以X节点为头。假设以X节点为头。

如果我要是等你空的时候。😡,我最大距离是多少?0。你都没有节点,哪来的距离啊?那你的高度是多少?0啊。发回这个完全没有问题。接下来我先默认我左数可以给我两个信息。我在默认我右数可以给我两个信息。

我利用这两这一共4个信息,我也得想办法加工我上面的最大距离和我自己的高度,整个低归才能连起来。我的高度是最好加工的。我左树上的高度和我右树上的高度的最大值,再加我自己这一层就是我的高度。这是最好加工的。

最大距离是?最大距离。我左树上的最大距离和我右树上的最大距离,以及我左树的高度,加我右树的高度,再加我自己这个点三者中求max就是我这棵树上的最大距离。打完说工听我同学打一。😡,有体会了吗?有体会了吗?

哎,他说就说我靠,你这个好玄学呀,一点也不玄学,他在干嘛?😡。

他是这样的一件事。就是说这样的啊,我X。😡,我左数给了我一个信息,占了个空间,我左数整体给了我信息,占了个空间。我右数给了我个信息,占了个空间。我把这个信息跟这个信息通过某一种结合的方式搞出来。

我自己的信息往上返回。那原本我左述的信息跟我右数的信息,我就可以彻底的不要了。这不是动态规划,是什么?😡,就是如果你觉得你的子数可以给你这样的信息,你加工出你的信息之后,也许你有父亲。

你就把你的这个信息再往上扔。那你原本子的信息就可以被你扔掉了,因为不再重要了。😡。

听有团学打一,本质上就这么回事儿。

本质上就这么回事儿。😡,这就是动态规划。😡,就是为什么这是动态规划,我我我不想我不想自己去执行啊,就是我每一次我左数好烦呀,我就觉得他能够给我。😡,对吧他给了我信息。

右手给了我左处给了我加工出我自己的信息往上返。他其实在这用利利用地规这种强大的返回自己的机制,他可以做到。😡。

119行为什么要加一?我的高度是什么?我左数的高度和我右竖的高度是不是没有算X的情况下?😡,你左竖有个高度,你右竖有个高度,那是那是他自己这棵树的高度。你因为你自己X是负节点,所以要加个一。😡,啊。

你不懂,我就给你彻底过一个例子啊,听懂同学打个一啊,119行明明明明白了吧?😡,好,你不懂是吧?不懂,我就给你举个例子,啥例子啊,就这样的啊。😡。

我发现这个跟你们说熟悉地归这件事一点用都没有,还是得自己给你拆地归,没问题啊,给你拆。就这个例子。我把编号ABCDE。我想要来A的信息,不好意思,你先去给我要FB的信息吧。我想要来FB的信息,不好意思。

你去要FD的,先要来D的信息吧。FD我去你去要空接点的信息吧,得到了什么呢?最大距离是零,高度是0,你去要你右输的信息吧,得到了最大距离是零空高度是0。好,所以我的高度是什么?

我左输的高度跟我右输的高度都是0,我只有我自己,所以我的高度是一。😡,我的最大距离是什么呢?😡,左数的最大距离是0,右数的最大距离是0。但是我左数离我最远的距离是0,右数离我最远的距离是0。

我自己到自己的距离是一返回了一。😡,这样一来,FB就得到了FD这个过程给它的返回值11。然后FB再去右边要他的信息得到00,他再把这个四个信息整合再往上给,看到了吗?本质上不就是拆了拆了。

用用了拆再往上给吗?😡,这跟这跑个递归是一样的,理解吗?听懂同学打一。😡,啊,如果不懂的同学,就把这道题你画出个复杂点的数,你给我一层一层把地归给我脑图画出来,好吧,你就懂了。对吧你你画一半你就懂了。

你现在还不懂,就说明你对地规太不熟了。好。😡。

就没了啊,主函数怎么掉呢?主函数怎么掉呢?哎,整个节点的信息你给我去收吧,我只要你最大距离的信息,说完之后就这么掉。我们再来一道题,你看你能不能体会。如果你没懂,不要紧啊,今天下午不干别的。

就给你熟悉套路。😡。

虽然每道题都是不一样的,但所有题都可以用套路解。😡,来再来一个男的啊,来个来个这个嗯。嗯。来个需要求全集的啊,来。给定一棵二叉树投地得害的。返回这棵二叉树,最大二叉搜索子树的头节点。什么叫搜索二叉数?

我们现在讲一下,对吧?搜索二叉树就是说整个数上没有重复值。😡,然后左树的值都比我小,右树的值都比我大,每棵子树都如此,这叫搜索二叉树。

比如这棵树,它整棵树就是一个搜索二叉树,为什么?😡,你以五作为头,左数是不是都比你小,右数是不是都比你大,所以五达标。你以三为头,是不是左数都比你小,右数都比你大,所以以三为头达标,你以七为头。

是不是左数都比你小,右数都比你大。好,以七为头达标。后面以二为头以四为头,以六为头,以八为头就不用说了,只有一个树当然达标,这样我才能说整棵树是搜索二叉树。😡,搜索树定义就是这个就每一棵子树都满足。

才叫整体式搜索杀树。好,现在我的问题是这样的。我整棵树理。😡,它未必完全都是搜索而他数。比如说这个。它整棵树其实不是的,你很明显能看到零的左数都比它大了,对吧?呃,零零零的左数都不比它小是吧?

但是肯定不是。😡,但是我问你满足搜索二叉树结构的最大子数是谁?😡,你会说啊,我知道了,是三,然后底下连个连个2,然后这边连个5,然后不要这个6不对。😡,当我们说子数的时候。

是下面的所有东西都要的这叫子数。😡,你如果以三为头,整棵子树应该是这个。它不是搜索二叉树,因为五的右左孩子比他大,所以以三为头的整棵树,它不是搜索二叉树。😡,哪个是你最大的搜索二叉子数呢?

47这个玩意儿。也就是说,原本整棵树可能不是搜索二叉树,但如果它有某一棵子树,它整体是的话,这棵子树的整体是的话,它就算达标。我问你满足搜索二叉树的最大子树,请你返回那个头部节点。听懂提同学打个一。

不是求节点数量,就要它那个头部那个节点是什么?返回求节点数量是另外一个题。如果有多个同时一样呢,那你返回哪个都行好,无所谓,我们就求最大二叉搜索数最多有多少个节点。好吧,似乎大家都更加关心这个问题。好。

那我们就做这个问题可以吗?我们就看一棵搜索一棵21一棵二叉树里最大二叉搜索子树有多少个节点,这个问题可以无所谓。😡,来啊裂可能性。我可以向我的左数跟我的右数要信息,以X为头的数。

它整体最大的二叉搜索子数怎么分可能性?第一种大分类X无关,X有关。什么叫跟X?这个答案跟X无关呢?就是你最终找的这棵最大上搜索树,它不以X为头呗。😡,答案是什么?你左数上满足条件的最大二叉搜索数的。😡。

大小或者你右树上满足最大二叉搜索树的子数大小。听台打一。我把这个问题往下扔嘛,对不对?😡,大小定义就是节点个数。😡,对吧。大小的大小的定义就是节点个数。好。那什么叫跟X有关呢?😡。

就是我要以X为头整体的大小。那我们来想一下。你要想跟X有关,要想做到X为头的数,整体都是搜索战术。其实你这个条件二,它成立是有是有条件的,什么条件?你左述得整体是搜索二叉树。

你右数得整体是搜索二叉数的情况下,你左数上最大值要小于你X的值,你右数上的最小值要大于你X的值,这些条件都成立。才叫跟X有关的答案存在,有一点破坏,实际上你是不存在可能性二的,你只存在可能性一。

听懂同学打一。好,那么我们看我们列一下我们到底需要什么信息。左树上。需要什么?它上面最大二叉搜索子数。我们管它叫最。大。😡,子。收。Size。需要第一个信息。第二个信息,左述整体是不是搜索二叉树?

没错吧。这是一个布尔类型的纸,叫e。Oh。BST。对吧还要什么左数上的最大值。看。这是对我左数的要求。而我对我右数的要求是什么?😡,你右数上也要求最大只sosize。😡,最大的搜索二叉子数的大小。

以及你也得告诉我你整体是不是搜索二叉树。😡,以及你的最大值。啊,你一进的最小值。😡,这里面你要注意哦。它里面还隐含了一个信息,你们可能没有注意。如果我左数整体它就是搜索二叉树。

那么我最大搜索二叉子树的大小就变成了我整棵子树的大小。😡,听懂同学打一。这个max是啥?max是左数上的最大值,命是右数上的最小值。好。那我你看我这种就属于左数的要求,跟我右数的要求。😡,不是一样的。

干嘛求全集,为什么?因为我们是递归函数,我根本不想对我左数的要求和我右数的要求做区分。我就想一劳永逸的解决写一份代码套所有东西,所以我对我左数的要求和我右数的要求,我就给它憋成一样的。

所以我不管你是什么,只要你是子数,你给我返回四个信息。第一个信息最大二叉搜索子数的size。第二个信息,你只你自己整体是否是搜索二叉树。第三个信息,你整棵数的最大值,最后一个信息,你整棵数的最小值。

我就给你搞成这样的,求全集,这就是我的info。

我们直接开始写。一写就明白了。怎么写?在这儿呢。In否。对于任何子数。对于任何子数都返回4个信息,你整体是不是BST直接改成名is ofBST你整体是不是整体全是BST,对吧?Eal BSP。

然后最大的。子数满足搜索二叉树条件的。最大指数s。节点个数。整棵树的最小值。整棵树的最大值。好。这就是我的信息。啊,有点乱是吧?我们一行一行写啊,我在我我就我为了防止你看乱了,我们现在写。

这样一行一行写的方写一行一行写的方式,可能会让你加深印象,对吧?反正有时间去掉,重新开始写。

这都不要了。

我的音符是啥,我都考不过来。😡,咱从这儿就开始好吧。不管是什么子数,这四个信息你给我憋吧,我以X为图。😡,哎,这里面还要讲一下啊,大来看。首先想空的时候,如果X等于空。哎,你看一下你你好不好。

就设置这四个信息。是否整体是BST考设置?空数的最大二叉搜索子数大小0好设置,但空数应该给什么最小值,给什么最大值呢?好像不是很好设置。好。它不像之前做的题那么好设置了,那你就返回空。😡。

可以接受你返回空。但是如果你是这样的话,你在用这个信息的时候,你就得自己去判空了,理解这个意思吧?好,那我们就选择自己判空。😡,接下来怎么做?我就默认我的左数可以给我四个信息。

然后我就默认我的右数可以给你可以给我四个信息。接下来对我的目标不就是我也加工出我的四个信息返回吗?😡,这不就套路嘛,对吧?我怎么加工出我的四个信息返回呢?这个加工的完成,这个加工如果完成了。

整个代码就连起来了。😡,好,我先给他我先给他写上return new info这四个信息,你给我塞进去。虽然说现在我还没填值,我会有填的时候的对吧?是这意思吧?

exel BST它的size它最小值它最大值就这些东西。好,现在呢是没设置值的状态,所以它我就我反正我最后要返回的,我就给它放到最后去。😡,怎么加工就是问题了。

最好加工的就是整棵树最小值跟整棵的最大值嘛,最好加工的是整棵树的最小值跟整棵数的最大值,对吧?怎么加工啊?我那我就先加工这两个。😡,首先我的最小值先让我自己等于X的值,X是不是在我整棵树上的?是的。

所以我最小值先让它等于X的值,最大值也让它等于X的值。因为我X的值就在整棵树上,X的值当然要参与决策整全局的最大,全局的最小跟全局的最大,我先给它写上。接下来大家看。😡,如果。

我左边的信息不是空的那就说明我左数不空,因为只有在空数的情况下才返回空信息。除此之外,没有返回空信息的时候。所以如果我左数不空。我当然就能用他的信息,那怎么做这么干?如果我左数不空,我的最小值。

我就可以决策一下。我之前收集到的最小就是X的值和我左数信息中收集到的最小值,咱PK一下,谁小谁是现在我目前发现的整棵树的最小值。同样道理,最大值,我也这么来。啊,左数。可以吧。对吧我左数不为空。

那么它的最小值就可以参与决策全局最小值。如果左数不为空,那么它的最大值可以参与决策全局最大值右数你也这么干。😡,好,我干这么干完之后,我命跟max我可以再也不用管了,它加工完了,我只用去加工这两个。

最后返回就行了。有关于命跟max的加工结束了,听懂同学打一。😡,没懂打2。这个意思就是说什么,你如果发现空值的时候好设置信息,你就设置。如果不好设置信息,你就给他空,无非就是你在用这个信息的时候。

你人为判空不就完了吗?是这意思吧?你怎么写都行,然无所谓是吧?好,下面的问题就是哎。😡,那么怎么加工出这两个呢?好。注意看。

X无关时候的答案是不是总存在?对吧我们说X2跟X有关的时候,你得既满足左数是整体凑造二叉数,右数是整体凑造二叉数。然后你X的最还得大还得大于人家左数上的最大值,还得小于人右上的最小值。😡。

情况二是有条件成立,但情况一是不是永远成立,我跟X我都跟X无关了,对吧?我左说上的答案跟我右说上答案我总能用吧,那我就先用一下怎么用。😡。

我先默认我整棵树的最大二叉搜索数大小是0。如果我左数不为空。左边的信息不为空,先把我左边的信息拿过来,变成我的。然后。不过右说不为空。我就决策一下。啥意思?左数不为空,那么左数的答案先成为我的答案。

如果右数不为空,那么右数的答案就跟我之前发现的答案求一个最大值,变成了一个我更好的答案。😡。

相当于是我们已经把可能性一。考虑完了。听懂同学打一。

然后干下来不就考虑可能性2吗?考虑可能性2之前,我先默认我整体是不是ex造BST呢,我先默认它不是。😡,然后我看看什么样的情况下会成立可能性2,对不对?那什么样的情况下会成立可能性2呢?

如果啊这个这里面说白了就是一句话就是。😡,如果。可能性。二、成立。那我底下要干嘛?我把这个玩意儿。😡,它等于。以X为头的整棵树,所有的节点数给我设置上是吧?😡,然后我的椅子奥BST为处给我设置上。😡。

不就是这个玩意儿吗?你都你都你都可能性二成立了,你X做头整棵树都是搜索二大树了。😡。

那你不是最大吗?对吧?所以这种情况下就是我我以X为头的所有节点数就成了我的答案。我已造BSP就是处。如果可能性二不成立,那就维持上边的总对返回就行了。既然就是想的怎么把这个实现了,整个就结束了。

听懂同学打一。😡,好,那怎么做来。可能性二成立啥条件呢?可能要TR条件成立的第一个条件是你左述的整体是搜索二叉数怎么写?这么弄,如果我们把。第一个条件是左数。整体需要是搜索参数。好。

我们把这个条件整体认为是小括号的一个东西。那如果小括号怎么填?😡,想一下,如果我左数是空的,它满不满足,当然满足我左数是空,它必然是搜索二叉树。所以life。info如果等于空,就代表我左数是空的。

这种情况下,我就认为你一定成立。否则你信息就是不空的,我就拿你的信息用。听懂同学打一小括号里面就是左树整体需要是搜索楂树的条件。好,你懂了,下面在第一个条件成立的情况下,并且对不对?😡,并且该并什么了。

右数整体是搜索二叉数的条件,那不就同理。左数整体需要是搜索二叉数,右竖整体需要是搜索二杀数,这都是处,对吧?如果是空的话,就是处,它空的话也是处,不会破坏它,否则就用信息。好,还有啥条件?😡。

还有一个条件是。左数。最大值。小于X。怎么判断?假设这个条件叫括号。如果我左述的in符是空的话。是不是可以认为左数的最大值小于我。是的那就是处。😡,但我如果不空的话,返回什么?😡,正常拿信息判断。

没错吧。😡,并且。右数上的最大值大右数上的最小值大于X,那不是同理。如果你右数为空的时候,你不会破坏。这个你不会破坏的对吧?你唯空还有什么好说的,你的你就没有最小值,拿什么跟我比,对吧?

我就认为你最的最小值大于我可以吧?😡,你没空的时候,我右树上就不会完全不会破坏这个搜索二大叔的性质啊,给它处。😡,如果他有信息的话,你拿右数上的最小值。问它是否大于XY6。这一套打下来。

不就是衣服里面应该有东西吗?听懂同学打一。嗯。好。都听懂了吧。那么在四个条件都成立的情况下啊,有的同学不懂了,我们讲一下。因我们为什么要这么写?我们为什么要这么写?因为我们的信息是有可能得到空的。😡。

所以我们一定要关注空这个问题。那现实情况就是说我X,你说如果它左数为空。什么情况?就是你你你这个左输不管返回什么,都不会影响你X跟它连起来,连起来之后也是搜索二叉数,是吧?😡,你X左数都空了。

它是不是它上面返回的信息?😡,这它它也不会返回什么正常信息,对吧?X左数为空,它不会破坏X为头,整体的搜索性,因为它是空,它怎么都不会破坏。同理,如果右数也是空的话。

X它右数上怎么都不会破坏X整体能不能跟左数连起来,整体是搜索二叉数不会破坏,正是因为这样我们写出了这样的代码。😡。

因为你是有可能左数为空,右数为空的。你在返你在数为空的时候返回了空信息,所以你在用每一个信息的时候都要判空,否则的话你可能会出错。正是因为如此,我左数整体是不是搜索二叉数怎么判断。如果它是空。

反正它怎么都不会影响它的搜索性,我就默认它为处。😡,如果它不为空,那我就要实打实用它是否是椅子奥BST的信息了。如果他右数为空,那他怎么都不会影响我连起来。但如果它真的不是空,它有数。

那我就去真的要实打实的用它是否整体的做到上周信息了。😡,如果左数为空,那么它的最大值小于我这件事怎么都不会破坏,所以我就返回处。但如果它不为空的话,那我就要实打实的去看它最大值是否小于我了。😡。

理解了吗?刚才打二同学。应该还需要判断左右儿子头节点吧,这跟头节点没关系啊,我们列可能性的时候说谁头节点了吗?没说只说返回最大size。你看我们列可能性的时候,没有说什么头节点呀。😡。

哦,擦了已经。

哦。嗯,那我们就继续讲是吧?

好。那你如果这所有条件都成立,你怎么得到以X为头的所有节点数啊哎。

你的你的左数已经整体是搜索二叉树了,所以你左孩子一共有多少个节点?你左树整体已经是搜索二叉树了,所以你左树上最大搜索二叉子树的size。是不是就是你左述的塞子呀?你左数已经整体式了。

虽然你求这个答案不代表你左数整体的size,但是你已经告诉我,你左数整体都是BST了,它就变成了你左数的大小,对不对啊?😡,加上你右数的大小呗。再加你X这一个节点呗。所有东西加工完毕。返回。

听懂同学打一。搜索二叉树是什么,自己调研一下吧,好吧嗯。刚才讲过了是吧?这哦对,这里面还得加上判空是吧?你有可能是空的呀。哼说的对,所以应该这么写。我左数一共有多少个节点?如果我左数的info等于空。

那它就是零个点,否则的话。说的对啊。否则的话,我就用他的信息。啊,说的对。加上如果我右数是空的话,那我的右数的节点数就是零个点。否则我就用他的信息。再加一。没错。只要用信息就得判空,为什么?

因为你当时空信息的时候,你没有个塞具体的值,你也怕干扰,对吧?直接给它塞空。那你用的时候就得判空。😡,啊,听台打一啊,这个新代码。是吧。嗯。啊,这东西威力无穷的。😡,威力无穷的。😡,好。

我们还有一些题目,我们再讲一个。我们再讲一个。再给你让你再让你体会一下,然后我们再重新看一遍这个二叉树地归套路,好玩儿,这玩意儿你在网上找不到,这都不知道是多少回总结的。我我我总结的啊,假设以X为头。

假设可以向X左数跟右数要任何信息。

在上一步的假设下,讨论以X为头的数得到答案的可能性,常见分类式和X无关的答案,和X有关的答案。这一步是最重要的,它决定了你解题要怎么去列可能性。当我的第二步确定了所有可能性之后,我再反过来看。

在所有可能性中到底需要向我左手跟右数要什么样的信息。然后把我左数跟我的右数的信息求全集,为什么对递归来对于递归函数来说,我并不想区分左左是左数还是右数。所以我给你求全集,我所有信息都要。

任何一棵子树都要求返回这样的信息。那么我的递归函数就可以开始写了。在你函数里面,你就可以写空的时候,你想设置成什么值。如果你发现这个信息好设置,你就给它设置上,保证你不会被干扰。

上游你拿到这个信空信息的时候不会被干扰。如果你不想设置信息,那就给它空,那你在上游用信息的时候,你就需要判空。😡,写代码关键是怎么把左右两数的信息整合出你自己也规定好的这个信息体。返回。这就是整个套路。

我们再讲一个题。派对的最大快乐值问题。还有一些题没讲啊,那留在下节课好吧。我还有哪些啊,把这个题先讲了。这题你看它是啥,这是一棵多叉树,谁告诉你必须二叉树才能玩这个多叉树一样。😡,一样的。

每一个员工有自己的快乐值,以及自己的下属员工。这些员工都是自己的直接下级。如果我的下级还有下级的话,不在我的列表中保存。举个例子啥意思?😡。

这个这个A节点,它有三个下级BCD。好,那么在A的这个后续列表中就会只存BCD那B可能也有下级EF。KC只有一个下机S,那么在B的列表中就会存EFK。C的列表中就会存S,理解吧?😡。

就是每一个每一个员工他可能有若干个下级,我只存我的直接下级是什么?😡。

就是这个表。就这个表哪一嗯这些这门员工有哪些直接下机,就这个表。😡,我自己有一个值,就是我的happy值,就是我这个圆我我我这个人可以带来多少快乐值,就这个结构。😡,那么我规定好整棵树。

整棵多叉树不会有从下往上指的情况。就是你别给我搞什么1蛾子,B的下级是个K,结果K的有是A以A做直接下级,没有没有这种情况。

他就是在一个公司里面非常森严的那种等级结构。最基层的员工他可能就没有直接下级了。那么他列表里面那个节点个数就是零个。如果他是基层员工,他不再有直接下级了,他就他他就他就他就是夜节点。

那么那么整棵树你就可以写成一棵多叉树结构。整棵树就可以写成一个多叉树结构。

啊,每个员工都符合in类的描述,就是整个公司结构可以看作是一棵标准的没有还的多叉数。数的头节点是公司唯一的老板。除老板之外,每个员工都有唯一的直接上级。啊。对,这个也是就是我不可能存在有两个上级对应我。

就是我我我这个点我属于他,我不可能出现说我你我也是你的直接下级,没这种情况非常森严。每个部门的人,我也就是说每个人都只有唯一的一个老板。😡,啊,每一个人都只有唯一的一个老板,就就是一个标准的多叉树结构。

好。😡。

业结点是没有任何下属的基层员工,对吧?也就是说他的下级直接下级列表为空。除了基层员工之外,每个员工都有一个或多个直接下级。嗯。好,那么要干嘛呢?现在公司要办party。你可以给某些员工发请柬。

也可以不发请柬。你发请柬的员工会来,你不发请柬的员工一定不会来。但是你发请柬是有原则的。他必须遵循一个第一个原则。如果你给某个员工发了请柬。那么这个员工的所有直接下级都不会来。你发请柬的。

也就是说你发请柬的时候,你必须遵循第一条原则发请柬。😡,这可能这个公司对于老板比较恨,对吧?好,那么你不满足条件一的情况下,其实你是也你也可以有非常多的选择权。去发这个请柬的,对不对?

你即便你只是说一个员工来了之后,他所有的直接下级都不来,对吧?都不能来,但是你还是可以有很多决定权,你还是可以决定哪些员工来,哪些员工不来,即便不满不违反原原则一也存在很多选择。😡,好,那么我问你。

你怎么发请柬能够让到场员工的快乐值最大?

我们来举个例子。你怎么发清柬?😡,我让这个17的来,让这个500的来。最大。我如果给17的员工发了请柬。三跟五你就不能发请柬了,这是规则。😡,然后给这500发清柬。你可以有其他选择。

比如说你你你就给三发请柬,给五发请柬也不满,也不违反规则,对不对?😡,但是他得到快乐值就没刚才那种选择大。😊,就是你一棵树,它只用你发情前只有维持一个规则,就是必须满足一个规则。

就是只要老只要他的直接上级来了,他的直接下级是肯定不会来的。😡,你不破坏这个原则,你就可以随便发请柬。但是你在这么多选择中还是有得到不同快乐值的选择的。问你怎么得到最大的快乐值。

返回这个最大快乐值是多少?听懂提议同学打个一。😡,有的同学说没发的能不能来,没发请柬的不来,一定不来。啊。那个陈欣同学是哪里没有没没懂是吧?好,我们来先来分析一下啥呀。假设以X为头的整棵树。

我可以向我每一棵紫树要信息。答案是什么?根据X来跟不来分类呗。我不管你底下树是什么样子。😡,你发请柬的所有方案都可以分成两类。你给X发了请柬。的情况下,剩下的最优和你给X不发请柬的情况下,剩下的最优。

你的所有方案中就只会有两种分类,就这种分类肯定是合理的。我不管你发的是什么,你到底让X来没来。😡,所以它必然这种可能性。这两种分类是罗列所有可能性的。好,我们来看。如果你决定让X来。

我们不妨设它有三个后代。如果你决定让X来了。😡,你是不是能够获得X自己的快乐值?废话X自己的快乐之一,他已经决定来了嘛,你决定给他你决定给他发请柬了,对吧?好,那一定能获得X自己的happy。😊。

接下来。ABC都不能来,所以你需要你的子数给你返回什么样的信息?A不来情况下,它整棵树的最大快乐值。B不来情况下,它整棵树的最大快乐值。C不来情况下,它整棵树的最大快乐值,这就是可能性2。听懂他学打一。

全是家。对吧你X自己的快乐是获获得了。在A不来情况下,A整棵树的最大快乐值B不来情况下,它的整棵树最大快乐值C不来情况下,整棵树最大快乐值整棵树的最大快乐值。😊,A的子数的整棵数,B的子数的整棵数。

C的子数的整棵数,对吧?好,我们再看第一种可能性。你如果X决定不来呢。或者说你X决定不给他发请柬,来不来,这件事就是你发请柬决定的,理解吧?当我说他不来的时候,就是说你不给他发请柬的意思。😡,理解吗?

好。那我X如果要是不发请键呢。X不来了,所以你获得它的快乐值是多少?0。零加钱。X,你决定不发请柬。A要来还是不来呢?A既可以来,他也可以不来,你不给X发经典,就一定意味着给A发吗?谁告诉你的?😡。

所以当你决定不给X发行检ABC什么状态?😡,我爱发不发。哎,关于这个点听懂同学打一。所以接下来应该加什么?😡,它应该加的是A,在来的情况下,它整棵树的最大快乐值或者A在不来情况下。

它整棵树的最大快乐值求max。加上B在来的情况下,它整个数最大快乐值和B在不来情况下,整个数最大快乐值求max。😊,再加上C在来的情况下,整个说的快乐值。C在不来的情况下。

整个说最多快乐值求max三个max相加,最后跟零加是答案。听懂同学打一。😊,嗯。

好,那就写呗,是吧?Max, happyapp。员工有自己的快乐值,有自己的直接下级,我给他改个名叫nax词了,因为比较直观是吧?搞那么大个单词,那个单词是直接下级的意思。

那没有max没有没有nex直观。好的。然后你看我怎么做。在这儿呢。和音yes, no哼。yes指的是头节点在来的情况下,整棵树的最大快乐值。no指的是头节点在不来情况下,整棵树的最大快乐值。

哎。啊,还没列好,要需要什么信息呢?对吧?所以任何子数你要返回俩信息,这个子数的头节点在来的时候,最大快乐值是多少?整棵树的。这个头节点在不来的时候,它整棵树的最快是多少?整棵树的这就是我的信息结构。

没错吧,所以我也得想办法加工出我的两个信息来。

所以开始写代码。对于任何子数,你都要返回在你投来的情况下,整个数的最大快乐和X和你投不来的情况下,整个数的最大快乐。😊,per太2。注意。X的直接下级为空的时候是我的baase case,啥意思?

基层员工。我不再把空作为我的base case了,我不想去扯空这件事儿,我就拿我的基层员工做base case。😡,就终止条件。如果你你如果你这个人没有直接下级了,你来的情况下快乐值多少。

你自己的happy你不来情况下,整棵树的快乐值多少,因为你整棵树只有你一个人儿。😡,因为你没有再也没有底下的下级了,所以你返回零合理吧。啊,你你就是最基层的员工了。你来的话。

yes的值就获得你的happy你不来的情况下,那你的no就是零,对吧?这就是我的base case。😡,接下来大家看。yes是什么?X决定来了,所以yes可以直接获得X的happy。no是什么?

X决定不来,所以no先获得一个0。然后我对我每一个基层员工,我都调递归函数,要来他的信息。如果我X已经决定来了,我累加的就是我每一颗子树在它头节点不来情况下的最大快乐值。

我只能获得他们不来的时候的状态都累加上每一颗子树都只能获得no的信息,累加到我自己的ys上。但如果我不来呢,我就每一颗子树的yes跟no都做max累加到我的no上返回。😡,看到同学打一。

大理解这个套路的用处了吧啊,告诉你常见的分类,就是你就讨论哎这个答案跟X有关的时候,还是讨论这跟答这个答案跟X无关的时候。我大量的那我只能说这个比例就是8成以上面试题你是可以这么搞定的。

但不是每一次用套路的时候都是这么分类的。关为所以这就是我为什么没有写套路的时候,我为什么没有把这种可能性,后面加上就讨论跟X有关跟无关的时候,它只是一种经验。

大量的题是可以用在这种可能性的划分下搞出来的那会不会有其他的可能性划分,就是我不以X参与答案跟不参与来分类,会有,但是并不多。😡。

只是一种常见的经验而已,但这个套路本身是不变的,你怎么列可能性决定了你怎么写代码。这个套路既有你想法方面的提醒。又用高度结构化的coding,让你即便是一个新手,也能把代码写出来。这就是这个套路。

它背后的总结是吧?好,我们剩剩下的东西我们留在下节课,好吧。啊。这个。我觉得挺6的对吧?他家觉得六的同学打个6吧,鼓励鼓励我是吧?这玩意儿你你见不到啊,高手去炫动态规划。

高手去炫去炫这个树形DP他不会跟你说这么多,也没有什么套路可以借鉴。高手就直接给你该什么返回,怎么返回返回啥,那是你给我看去吧,是吧?反正我代码写的一团乱,我他不给你做什么info结构,让你看呢?😡。

是吧所以这是这就是我给你总结的,而且非常好用。经过了时间的检验啊。嗯,你听什么,你不听这种私货嘛,对不对?啊,好,我们以后的直播课啊,不是直播课,我们以后的训练营会大量的牵扯到二叉数的递归套路。

解决的问题太多了。太多了啊。好啊,那么我们还有一些这个题我也知道没讲完,所以我们留在下周好吧嗯。好,那么拜拜拜拜。😔,打个分啊,满分10分啊,拜拜。嗯。没事,跟不上同学把这个代码看一下。

把这个我讲的东西。看一下是吧。嗯,哎,有有的同学问那么。嗯,不来的时候怎么获得呀?这。

我给你举个例子吧,好吧。哎呀,你说这个点它是3。它下面这个点是100,这个点是200。你怎么算三步来的时候怎么获得,那就是no。翻 the no。你三已经决定不来了,所以下面是什么呢?什么过程呢?

它就累加上1个100这棵子树在100来的时候和100不来的时候的max,那就是100和0的max。你说你选谁,那你肯定选100啊。😡,加上啥?200这棵子树在它来跟不来时候的max。

那那就你就得到了3no了,那不就是100加200吗?这不就是no的时候怎么获得值的嘛,对吧?嗯。😡,嗯,理解了吗?房东员。啊。复杂度是B勾N吗?是的,为什么?递归方法,一个节点最多经过3次。

我所有信息整合的过程。啊,你要说之前我们讲的递归套路呢。之前我们讲的递归套路就二叉树问题,肯定是B勾N的。这个是多叉数问题,我们来想一下啊。嗯。多差数问题的复杂度应该也是B勾N的。怎么估计呢?

我们来看一下这个首先。

啊,我们来看一下它到底发生什么。比如说。把这个过程写一下是吧?一。23。4。5。67。来到一的时候。去收集了二的信息,二信息的收集需要依赖五的信息返回了,他去需要六的信息返回了。但他返回的时候。

五的信息之前也跟他累加上了,所以他给一一得到了二的信息之后,再去调三的信息,三去调七的信息返回了,直接加工出返回了。当他来到这一集的时候,其实已经把二之前的这个东西该累加累加上了。然后他再调四的信息。

就还是B勾N啊。你每个节点就过一遍呀,对吧?要完信息,我以后再也不掉你了,那不是B勾N是什么呢?节点数量是N,它是复杂度就是B勾N啊。😡,啊。那个问复杂度同学理解了吗?听懂同学打个一。

为啥有的递归复杂度是N平方?哎,你别管,我在讲我在讲那个贪心的时候,我会告诉你为什么有的是N方,那个是一个全排列的呃递归啊,那是一个全排列的递归。好啊。然后。如果来了限制人数,那就是一个别的题了啊。

这个题我没有准备,所以我也不不不卡大家时间。大家可以想一想,如果限制了人数咋办是吧?我备课并没有准备这个。好,拜拜嗯。😡。

系列 2:P75:左神算法-二叉树的基本算法 - Java视频学堂 - BV1Hy4y1t7Bo

喂喂大家好,今天都上班是吗,哇人好少啊,呵呵。

人很少要好好讲啊,因为,好你今天今天的内容还是比较重要的,我们这个二叉树如果大家不懂的话,嗯我们可以把这个一共两节课,关于二叉树是吧,拆成三节或者是更长啊,都无所谓,嗯好谢谢大家,嗯我回头。

其实我自己自己在录,自己在录,这一段路呢,但是他现在还是用的腾讯自带的啊,看看工作人员没有管我要视频啊。

我课的视频都在录啊,先把他录上。

啊大家好啊,这个我们来看一下今天的内容,就讲到第五节是不对,第六节诶,第六节讲完了吧。

啊讲完了,第七集,哦那个第七节呢就开始进入到我们这个二叉树的内容里,是,这个内容其实不容易啊,尤其是跟大家说第八节啊,完全是我一个特别好的一个总结,好的一个私货,虽然你在网上可以看到很多关于树形dp。

也就是怎么在树上做动态规划的这种方法,或者说找到很多相应的题目,但是对于新手来说呢,还是不够友好啊,那么我我干了我干了一件啥事呢,就整个第八节我就教你怎么用树形dp的套路来解决二叉树的问题。

这个套路本身既有思想上的提醒,又可以帮你很快的写出代码,应该算是一个嗯很长一段时间以来对于树形dp的一个总结,而且它非常好用,我自己刷题的时候也经常用啊,那么多年经过了检验是吧。

他会比你单纯的去理解树形,dp,抠手抠半天代码可能也看不懂要好很多呢,所以我们一点点来,但二叉树的题目本身内容还是挺大的,你就把这个二叉树讲明白,然后什么各种便利来一遍,其实时间都挺长的。

所以如果要是讲不完,我们就留到下节课去讲,因为准备了12节课,内容也没准备,12节课完了就讲完了是吧,可能会拖到14节或15节,反正总而言之就是讲清楚为主,对大家踊跃发言一下啊。

因为啊你们互动的话还是学的比较比较好的好,我们下面我们来看一下什么叫二叉树啊,所以说白了这个二叉树你要是单纯单纯从这个结构上定义的话,它是一个蛮简单的一个结构是吧,你比如说一个note。

它里面有属于自己的一个值类型,还有一个你跟那个单链表不一样的是,它是有两条指针的是吧,一条指向左边,他名字叫left是吧,一条指向右边。

那也就是说直观理解的话,你就可以认为是某一个节点上面有自己的v值,但是它有两条指针,所有那所有这个东西串成的形状是不是都是二叉树呢,不是你不能胡串啊,比如说唉我这个一指向左边,指向右边是吧。

然后这个二他突然间指回来了是吧,这不行啊,这种我认为它不是二叉树理解吧,就是说从一个概念上来讲啊,你这个你这个东西能够串成啥样的东西,多了去了是吧,这个node能够穿成啥样的东西,那简直多了去了是吧。

但是我们必须做一些限定,那么什么叫二叉树呢,嗯你就可以直观理解为一个节点值往下指是吧,这个这个节点它再往下指,如果它底层没有节点了,就是空是吧,如果还有节点,就继续往下指这么一个玩意儿所形成的树形结构。

它就是二叉树,它是不能够形成环,不能够形成环的是吧,你这个每个节点,每个底下的节点也不要通过自己的指针往上指,那么这样一种结构呢就是一棵二叉树的结构啊。

这就是我们关于这个二叉树no的类型,它的这个说法,那我们来看一个概念,就是所谓的二叉树,先序中序,后续的便利,这个我先解释一下你们课堂上是怎么说的,然后我再以我的角度给你讲一遍,你看哪个更清晰是吧。

可能有的同学没有学过啥书啊,不要紧,没有学过二叉树啊,不要紧,那么我的想法肯定是比你老师讲法要好太多了啊,先说一下这个我们在这个学术上,或者说在这个平时我们看到概念上的一些定义,就是很很广泛的一种定义。

二叉树的先序中序后序遍历是什么意思,他指的是啊,你会可能可能你就简单的理解为先驱就是中左右是吧,中区就是左中右,后续就是左右中说的啥玩意儿是吧,你也不知道啥东西,它很好的一个定义就是在二叉树上。

对于任何子数是任何子数处理的顺序都是先头节点在左子树,再右子数的啊,首先我们定义什么叫子数。

这个可能就有个同学又不知道是吧,这个子数啊不是像大家想的那样,哎你看我这个点是吧,这是a点底下有个b点,这个c点这边来个d,这边来个e,那我问你值,你把这个c然后这个d拿出来,就这个小东西。

他是不是子数,不是我们说子数的时候,一定要是从某一个头节点出发,下面的东西全都要这叫子数理解吧,你说你从c节点出发,你有把所有东西都拿到吗,没有你为什么要省掉一个e呢,所以这个东西它不算它的子数。

你要是拿指数,你就拿整个的,我们说这是一棵子树,是单独这个b节点也是一棵子树,所有的整棵树是以a为头的子数,这都对,但是你不要从一个头节点出发,你选择拿某些不拿某些不行,说子数就是全须全影,全部都要的。

从一个投递点出发,后面所有都要的叫子数理解吗,那我们说所谓的先序中序,后序遍历是个啥意思,你比如说有一棵树是吧,我们当我们说先序遍历的时候,就是对于所有子数来说。

对于所有子数来说都是先投节点在左左数在右数的的便利,那你说这个应该是个什么顺序,12453,六七他应该是这个顺序,你不用管这个顺序是怎么得到的,我会告诉你怎么得到,我会告诉你怎么得到。

但是我们知道这个顺序它正就是先序遍历的,原因是因为你看以一为投的子数来说,是不是先出现了头结点,然后接下来打印了它的左子数245对吧,然后打赢他右子数367是那对于二这颗子数来说,是不是也是这样。

你先打印它的头节点,然后打印它左子树,然后打印他右子数,对于三这棵子树是不是也是这样,先三再六再七,剩下的四单独这颗子数五单,这个子数六单独这个子数七单,他这个子数肯定满足要求,因为他们就一个节点。

那么我们说符合这种顺序的这个序列,它就符合,那这个序列就是整棵树的先序遍历的序列啊,先序遍历的序列它是唯一的,你不可能再加工出一个别的序列,也满足这个,因为对于每一颗子数都得成立好。

那么中序遍历的序列是啥呢,就是对于每一颗子树来说,都是先左在头,节点在右节点的,那这个顺序应该是啥,516,三七这就是中序遍历,看对不对呢,你看对于一这颗子数来说,是不是我先打印了我左子树的值。

然后打印了我自己,然后打印了我柚子树的值,是的,对于二这颗子数来说是不是是的,对于三这颗子数来说,是不是也是的,好那么这个序列它就是中序遍历的序列,然后再看后续后续是啥呢,就是先左再右带头的打印。

那他血液应该是什么呢,就是4526731,对不对呢,在验证吗,我以一位投的子数,先打印的左子树吗,是的,再打一个柚子树吗,没错再打一个我的头,对于二这颗子数来说是不是也是先四再五再二。

对于三这颗子数来说,是不是也是先先左先左再右再中,那4567肯定是的,因为单独一个节点好,那么这就是我所谓的先序中序,后序遍历,你不用管他怎么得到这个序列,我们先把概念搞清楚,理解没有任何问题。

同学打个一,有一点问题就打个二或者发弹幕,好啊,没事啊,昨天已经大家已经说了,今天要上班,我完全可以理解是吧,好的,你现在已经知道定义了,那么怎么实现,我们先讲一下啊。

你这可能1万个人在自己班上学的时候都是这么学的。

但是他欠解释,你知道吗,来我们来看一下这个东西怎么实现,其实实现一下理解还是蛮简单的,你看这个,先去便利的方式打印,谦虚,打印所有节点,很容易理解是吧,你看这个代码一看你就知道了。

我靠对于每一颗假设had的就是此时的子书,我的方式是先打印头节点,然后你这个过程你给我去左数执行吧,执行完了之后,你就再去右数执行吧,先去便利,他肯定是对的,因为它对于每一颗子树来说,他都这么干。

你接下来进行底下执行的左子树,它也会这么干,底下执行的右子树它也这么干,你稍微具有一点点递归思维,你就能理解他,递归我们之前已经讲过很多了,连带你想象的图的方式,带你就是从系统上怎么支持递归的。

我都讲了是吧,那么中序遍历就不言而喻了,啥呢,对于每一颗子数来说,先去我的左数执行,回到它之后再打印它的值,然后去右数执行,那么后续遍历的方式就是先去我左数执行,去我右数执行都回来之后,答应我的节点。

你们在课上可能就是这么学的啊,这三个代码理解没有问题,同学打个一,好那我给你讲一下我的理解啊,这个我给你讲一下我的理解啊,这个我的理解听完之后你会更加的明白啊,因为如果你对递归不熟悉的话,无所谓。

我让你熟悉,你不觉得这三个代码很奇怪吗,你不觉得这三个代码很奇怪吗,为什么奇怪,它结构除了打印行为之外,这不都一样的嘛,你看这个函数,这是f函数,这个f函数它不是先序,也不是中序,也不是后续。

它就是这么一个函数,这个函数呢子子节点传进来是亥为空的时候,返回没有打印行为,去我左树转一圈,去往右数转一圈儿,我为什么说这三个方法奇怪,因为当你把打印行为放在这儿的时候,他就是先去打印。

你把打印行为放在这儿的时候,他就是中序打印,你把打印行为放在这儿的时候,他就是后续打印,明白同学打个一,所以,先序中序,后序根本就不是这个递归便利的本质,递归便利的本质是递归虚,我们来讲讲什么叫递归虚。

这个很重要,这个比你想象的重要多了,因为我们往后讲的树形dp的在树上做动态规划,其实全基于这样一个认知,只是你们老师省事,没给你们讲。

这棵树当我用f函数,去调用把头节点传进来的时候,那么我我先不画个图,我先说你这个f函数,当我处理head的时候,其实这个head他一定会回到这个函数三次的,这么理解你刚进来的时候来到这个head的三次。

怎么理解,你刚进来的时候,我问你这是不是你在害的中,你看你head的已经传进来了,在这个函函函数f里,在这个蓝色区域,我们姑且认为它是时间点一的时候,其实是在你你可以处理这个head的,没错吧。

然后去了左数转了一圈之后返回了来到这个点,虽然什么也没干,但你得一定回来,你才能够知道下一行的调用,你是一定会回来之后才知道下一行有这个调用的,所以虽然你什么都没干,但你一定会回来。

当我走完了这个过程之后,我是一定会返回之后,我是一定会来到三这个点的,虽然我什么都没干,但是我发现我结束了,我才正式退出。

这就是递归序,对于图来说就是这样的,我们先来到一节点,来到它之后,函数告诉我们,你去你左数执行,我们就来到了二节点,来到二节点之后,函数又告诉你,请你去左述执行,我们就来到了四节点,来到四节点之后。

函数告诉你,你去你左数执行遇到空返回了四,函数告诉你请你去右数执行,遇到空又返回了四,三次返回啊,三次到达这回可是真的结束了,返回到二函数告诉你,请你往右数执行,你来到我左边遇到空返回了,回到五。

函数告诉你去右边执行,遇到空返回了又回到五,这回是真结束了,往上返回,第三次回到二,第三次回到二的时候是真结束了,往上返回,第二次回到一,然后函数告诉你,你往右执行来到三三,往左直行来到六六。

左数返回了,第二次回到六,函数告诉你往右执行又返回了,第三次回到六,这回是真结束了,往上返回回到三三,函数告诉你往右执行来到七七,左边返回右边返回两次,又到达七,这回是真结束了。

往上返回来到三已经是三次返回三了,真结束了,往上返回来到一递归虚,每一个节点都会到达三次,听懂同学打一一,好,听懂了吧,那什么叫先序遍历呢,就是你每一次第一次到达一个节点的时候就打印,他就是谦虚。

我们用三角来表示,哎我第一次到达了一,我要打印,这是我第一次到达二,我要打印,这是我第一次到达四,我要打印,这不是我第一次到达四,我不管,这不是我第一次到达四,我不管,这不是我第一次到达二,我不管。

这是我第一次到达五打印,这不是第一次,不是第一次,不是第一次,不是第一次,是第一次打印,是第一次,不是第一次,不是第一次,不是第一次,是第一次打印,六忘忘写了,你第一次到达一个节点的时候就打印。

他就是谦虚,你第二次到达的时候再打印,它就是中虚,你等到第三次到达时再打印,它是后续,先序中序,后续只是地工序加工的,结果,听不出来,打一,啊你们老师没有跟你这么讲吧,那我为什么要这么讲呢。

这说明任何一个节点都有机会去他左树转一圈,回到他收集一些信息,任何节点都可以向他右数转一圈,回到他收集一些信息,还能第三次回到他,把左右两个信息做整合,这是在树上做动态规划的基础,你现在不懂不要紧。

我们第八节专门讲它了,但是前提是你得理解什么叫递归序,理解吧啊为什么为什么为什么递归很强,为什么一个方法可以改出三种序列,只是打印行为不同,因为递归它很强,递归可以让一个东西来到三次,正是因为他这么强。

所以他随便加攻,先序中序后序,听懂同学打一,嗯,理解吧好啊。

我觉得这个东西已经讲的很细了,但是很少有人会这么听话,很少也很少有老师会这么讲好。

那么我们这个就属于我们这个已经完全理解了是吧好,那我们看,嗯实现先去中序后序遍历,你需要理解递归虚,然后先序中序后序都可以在递归序的基础上加工出来,第一次打印就是先序,等到第二次再打印,就是中序。

第三四它就是后续好,那么我们先来讲一个内容,就是怎么样用非递归的方式实现二叉树的先序中序后序遍历,任何递归函数都可以改成非递归啊,首先这一点你要明确,这不就是压战吗对吧。

那么你可以通过自己设计压榨来实现二叉树的先序中序后序遍历,这个在面试上也是经常考的啊,我为什么,下面我们就来讲一下非递归的方式怎么实现三种便利,不好意思,我先吐一下,我有点难受啊,稍等了两分钟。

不好意思啊,这个慢性咽炎是吧,早上起来喝水,喝多了容易吐,所以不要抽烟是吧,千万不要抽烟,别碰这个玩意儿不是啥好东西吗,这玩意儿什么抽象,没什么快感,不抽挺难受一个东西,所以搞得有严严,千万别抽烟啊。

千万别抽烟啊,作为过来人给你提醒啊,然后你看这是我们的地,我们先说这个先序便利怎么样,怎么样用自己压榨实现,你注意我实现这个方法,你会发现它不是递归的,他就是一个迭代,你看他有自己要用自己吗,没有是吧。

那这东西怎么实现呢。

说起来挺玄乎,其实一点也不玄乎,给大家画个例子就懂了啊,那么对于这个非递归遍历二叉树的代码,我个人建议啊,你记住流程理解他,然后强记住就完了,因为他太基础了,理解吧,没有什么好解释的,就跟公理一样是吧。

但是我还是要解释一下,你怎么实现这棵树的非递归方式,实现先序遍历,怎么打印,做好一个战,那么方式就是你一开始先把头结点放到这里去,第一步啊,以后你就可以依次按照统一逻辑来执行了什么呢。

我们在弹出一个节点的时候就打印,所以先把一弹出,弹出就打印,让我们把规则记好,什么规则,第一条弹出就打印,所以弹出来之后就打一一,接下来注意如果有右孩子先压右孩子,如果没有就不押了。

然后是如果有左孩子再压左孩子先右再左,所以第二步,有有孩子就压入右,第三步,如有左,就压入左,就这么简单,没了,那好我们来执行一下这个一它有没有用,有三进去,这个一有没有左,有二进去可以了。

你永远以后永远别碰你了,不要了,然后我们继续重复这个过程,二节点弹出弹出就打印,如果有右孩子先压右,那就是五,如果有左孩子再压左,那就是四,可以了,不要了,然后继续重复弹出四弹出就打印,他既没有右眼。

没有左,就什么也不干,再弹出节点五弹出就打印,他既没有右,也没有左,就什么也不干,再弹出节点三弹出就打印,先压右再压左,所以先压七再压六,好结束了对吧,然后再弹六的时候打印什么也不干。

谈七的时候打印什么也没干,因为六七都没有左孩子和右孩子,这不是先去便利吗,看代码。

前面不用说是吧,哎这个先来个提示,我现在要打,先去便利了啊,先来个提示是吧,然后站准备好,第一步没什么说的,把头结点放进去,然后以后就可以跟着执行了,怎么了,站如果不为空。

你就重复我刚才那个行为,就这个行为这三点。

弹出一个节点啊,弹出就打印,右孩子不为空,先压右,左孩子不为空,再压左,结束。

这个道理是很简单的,然后我先压右再压左的时候,那就先压了右再压了左,然后我先处理的就是左了,因为战士先进后出的,那我处理左的时候,我又让他先压右再压左,但这可是我左树上的,先压右再压左。

哎你这样一发现正好是每次都先处理头节点,然后左子树右子树为什么要先下右再压左,因为站他会逆序啊,所以我先压右再压左,就意味着先弹先处理左再处理右,所以整个逻辑是对的,听懂他再打一连代码再解释都懂。

同学打个一,好的有了它之后,我们就可以处理后续了,很妙是吧,非常的妙,怎么妙呢,这个我们来讲一下怎么妙啊,你现在已经有啥了,先投对于每一棵子树来说,先投再左再右的便利,没错吧。

好那么我问你我我我如果是我现在想每一颗子数都是先投节点在右,减子在右还在右数在左数这个顺序请问怎么加工得到,很简单啊对吧,你你一开始是所有指数都是先投再左再右的,现在你对所有指数都想先投再右再左。

那你先压左再压右,你不就实现了吗,听懂同学打一,对吧,你先压左压右,你不就实现了吗,好那讲这个,那你那你现在可,那你就说如有左,压入左,如有右压入右,你就实现了对吧,你就实现了好。

那我们来看一下这种打印它的顺序,先把头结点放进去一,然后我们跟重复刚才那个顺序,一弹出的时候就打印,然后先压左再按右对吧,我改了,先压,原来是先压右,先再压左,先先压左再压右,所以二进去三进去。

然后就是翻出来弹出就打印,先压左压右,所以先压六再压七对吧,然后七弹出的时候什么也没干啊,就打印了之后就什么也不用干了,六弹出的时候也是弹出之后打印就什么也不干了,等到二弹出的时候,二弹出就打印。

先压左再压右,所以先压四再压五,对吧,然后我五四弹出的时候都什么也不干,所以五四好,那么这个就是我的头先右再先投再右再左的顺序哈,你逆着看它是不是后续,你头右左的逆序不就是左右头吗,这玩意不是后续吗。

你从你从右往左看他是不是后续,听懂打一,好如果是这样的话,那么在我打印的时候,我把它单独放到一个站里去,我不打印,就是我每个东西弹出的时候啊,我不是他的打印时机,我就把它放到一个另外的站里去收集他。

我收集完了之后,我在整个过程处理完之后,我再把那个我额外准备好的站,就是专门每一次打印的时候,把一个点压住的那个站,再从头弹出来,我不就实现后续打印了吗。

所以大家看代码,后续便利,准备两个站,这个s2 完全是辅助用的,s一就是我们那个站是头节点进入到s一里去,啥顺序,每一个节点弹出了,不打印,用一个s2 收集它,先压左再压右,周而复始。

等到所有过程都结束之后,我再单独处理s2 ,每一个东西打印出来,我就实现了原本的这个序列。

逆序打印,它就是后续啊,听懂打一。

对啊这样的额外空间需要增加一个容器,那么下面这个方法就是只用一个站的,我们后面再讲,因为他其实比较好玩,他也比较骚是吧,你可以认为他和我们昨天讲那个基数排序差不多少啊,这也是我自己写的是吧。

怎么样用一个站来搞定,但但是如果你觉得哎呀这个你不想秀这个技,那你每一次就老老实实这么写也行,但是对于我来讲,我要给你们讲一下,因为我们课上要承担两个任务,第一个就是让你懂算法。

第二个就是让你提高coding对吧,所以我会给你讲这个方法,我们把中序遍历讲完之后,再讲第二种后续便利的方法,好吧好,我们看中序遍历。

中序遍历呢,也是准备一个站,我们先来看一下它的流程,然后解释一下他是为什么啊。

他的流程是啥,大家看一下代码,直接看代码吧,你看的可能会比较晕,他一上来啊,他准备了一个站,接下来你看这个while就写的很烦是吧,如果占不等于空或者头节点不等于空,这两个条件,然后你再看看发生了啥。

如果头节点不等于空压入头节点,头节点往左窜,然后又进到这个while里面来,如果头节点不等于空压入头节点,头节点往左窜,然后又到这个while里面来,如果它头点不等于空占压入头节点,头节点往左窜。

所以在干啥,这个函数这个while一进来,如果他面对的是一颗子树的节点的话。

那么它它会不由分说直接把整棵树的左边界先给我压到站里去,就这个意思,头节点如果来到啊,它不为空压入到战争里面去,头节点往左窜,如果头一点不为空,不由分说直接压到站里去,然后头有点往左窜,如果不为空。

不由分说要到这里去,头节点往左窜,窜到空了,才有第二个逻辑分支。

所以你可以理解这个代码就是我只要一进来,我就把整棵树的左边界全压到这里去,其实就这个过程。

当我压不动了,但我压不了了,什么意思,头几天已经来到空的位置的时候了,他才会走第二条逻辑好,所以我们说这个第一条逻辑是什么,就是整条左边界依次进站,就第一条逻辑是整条,左边界,依次,入站。

这就是我第一条逻辑啊,第二条逻辑就是当我穿不动了,当我已经左边界已经处理完的时候。

发生了啥对吧,els就一定是我穿不动了,我没有左边界,再让你穿了,干嘛呢,弹出节点就打印好。

我们看弹出节点就打印,所以四弹出就打印。

然后,来到右数的位置。

哎这看上去那我那我害得来到四右数的位置,不还是空吗,没错,所以下面又穿不动了,再弹出一个节点,二弹出就打印,头节点来到这个弹出节点右数的位置,它就会来到五,如果以五下面还有一整条左边界,就重复了。

条件一,但是在这个在这种情况下呢,五只有他一个节点,所以五自己就是它左边界唯一的点,所以我们也会进入条件,一直是没有压入那么多而已,所以就只把五放进去了,接下来high的又来到五的左孩子的位置。

他又窜不动了,所以第二条逻辑是啥,就第二条逻辑就是当我第一条逻辑无法再命中了,一无法再继续了,我就弹出节点并打印,然后来到弹出节点的右数上继续执行条件一,来到右数上继续执行条件一好。

我们把整个只要把整个过程先串一遍好吧,把整个过程先串一遍,所以你看我当时弹出四就打印了是吧,弹出二就打印了,那么二呢就来到他右数上继续执行条件一,整条左边接入站,所以五就进到站里去了对吧。

然后had它又窜不动了,所以干嘛呢弹出五就打印,然后还会来到五的右数上,它又窜不动了对吧,接下来干嘛呢,就弹出二节点就打印哦,哦哦哦刚才二已经弹出了是吧,刚才二重新来一遍吧是吧,刚才有点有一点模糊是吧。

所以就重新来一遍,第一句,一进去二进去四进去,然后四节点来到空,弄不动了,开始执行条件二,如果一无法继续执行了,弹出就打印,所以弹出四就打印,然后来到四个右数上继续执行条件一,那么四的右数是个空啊。

所以条件一其实判断了,但没执行动对吧,于是就又执行二,因为他执行不下去了,他又数没节点嘛,就又执行二,执行的时候啥弹出就打印,所以二弹出就打印,然后去他这个二的右数上继续执行条件一。

所以五就该进去了对吧,所以五就进去了,然后五进去之后,它就只有一个节点,它再往左窜,他没有左边界了,所以又是空干嘛呢,就执行条件二,弹出就打一,然后去五的右数上去执行条件一,但五的右数是空。

所以没执行条件一,他不执行了吗,其他执行了,只是他没有节点,那就又执行不动了,干嘛呢,韩初就打印,所以这个时候一弹出就打印,然后去他又树上继续执行条件一,所以三六进去,然后他就又执行不动了。

就执行条件二弹出就打印,弹出六就打印,然后去右六的右数上继续执行条件一啊没有,所以你下面弹出三打印去看右数上再次执行条件一好,那就三弹出之后七进去,然后又弹不动了,最后等七弹出来,其弹出的时候就打印。

七的右数也啥也没有,结束,这个流程我们再看一眼这个过程。

如果你能够执行条件一,你就一直执行,head不等于空,就是你现在能够还继续往左窜,你就把整条左边界压到这里去,当我这个条件一执行不动了,我就会进入条件二弹出节点并打印,然后去来到他右树上。

继续重复条件一,有关于这个流程,听明白同学打个一,然后我们来解释一下啊,这个东西是啥。

为什么呢,其实你可以这么理解,我们来举个例子。

我们话多一点节点,这棵树吧,我用一个什么视角来看这棵树,注意整棵树是可以被左边界分解掉的,啥意思,这是整棵树的左边界嗯,这是他这棵子树的左边界,这是这棵子树的左边界,这这颗子树的左边界。

这是这颗子树的左边界,这是这颗子树的左边界,这是这颗子树的左边界,是这棵子树左边界,整棵树是可以完全只被左边界分解掉的,那么当我把左边界依次压战的时候,我是先压头节点,然后左边界后续所有压进去的。

这可是在站里,所以你可以认为,如果我只以左边界的视角来看整棵树的话,对于任何一条左边界,它弹出的顺序都是先左在头,没错吧,对于任何一条一条左边接的弹出顺序都是先左在头的,那我们同时要注意到。

我这个节点把我整条左边界要依次进站,我在返回的时候,可是这个东西返回了,打个对勾,你返回了打个对勾,然后去我右树上继续这么执行,那么对于你看,对于这个节点来说,他一定是把自己左数处理完了之后。

还会轮到这个头节点的,然后轮到他之后,他再让他右数继续投,左要继续左投,所以整个顺序也就是说我把整我把整棵左树全用他自己的左头分解,我把我整棵幼树全用他自己的左头分解,而我们整体执行的顺序是。

只有当你左边界弄完了,你才会去你的右数上继续左投的分解,所以大顺序就是先左再投再右听我同学打一,当然你如果不懂的话,不要紧是吧,你就我已经说了是吧,这个东西没有那么好理解,他没有谦虚跟后续好理解。

所以你就自己可以记一下吧,以后你就这么写吧,你写熟了你就知道它有啥用啊啊简单给你解释一下,它实际上也没什么好说的,其实啊就这么记就行了是吧。

嗯中序遍历呢就是讲完了是吧,cd归版本,那我们先来看一下这个这个玩意儿啊,我好久没有讲他了,我之前的课都是给大家,这是我写的,我写这个方法写的有几年了,但是好多课呢都没有没有怎么讲过他啊。

所以这个班讲的也是隔好久才讲的啊,我来看一下这个方法,它其实是用用一个站来实现后续便利啊,他说的是啥,那我们都准备好这些引用,你会发现这个引用它其实是只有两个很实质的,第一个引用就是h自身。

这个是我是我是其实我在不断的复用它的对吧,你看这个h有设置值的时候,所以我们先准备好两个值,一个是h还有一个值就是c是我准备好了两个引用啊,然后我就准备了一个站,也就是说我们看流程的时候。

只要关注三个东西的变化,第一个h的变化,第二个c的变化。

第三个就是站的变化好,我们先画好一棵树,又在搞后续是吧,只是后续炫技版是吧啊,看这些方法真的是非常妙的啊,他绝对能给你带来一些思想上的一些冲击,或者说coding上的挑战,给我们讲一讲吧,站准备好对吧。

那么还有两个变量没事,我用啊,我直接在这树上画是吧,h箭头指到了哪,c箭头指到了哪儿。

可以吧,那我们先开始一开始站中把h压到站里去了,c一开始等于空,也就是说c这个箭头没用到,但h是指向开头的对吧,一上来就指向开头嘛,所以h是指向一开始是指向开头的。

h一开始只想开头的战争呢,先把一阶也放进去,那么我们接下来h跟c指哪儿就行了是吧,c一开c现在没有指c,现在指向的是空,开始怎么实现了。

后续呢来看,如果不等于空就继续好,现在的确是不等于空的,pk让c指一下c去指指一下那占的pick是谁占的。

pick是一顶部,注意是pk没有弹出对吧,它只是让我指顶部节点c c指向1c指向一两个东西都指它,那我现在就可以正式c就可以登场了是吧。

然后看一下,左孩子不等于空,并且,h不等于c的左孩子,并且h不等于c的右孩子,看都成立还是不成立,咱们来看一下,你这我们先把流程转一转,逐渐你就知道c跟h跟c它到底是门道是啥了。

我是想用这个目的来说明懂啥意思吧,就是你发现规律。

你怎么发现,就给你先讲这个h跟c到底是干啥用的,一开始讲可能会比较困惑是吧。

所以我们先过例子嘛,那我们来看一下,那你成立吗。

c的左孩子是不等于空吗,现在是的不等于空,因为现在c指向的是头节点。

它左孩子是不等于空,然后再看,h是不是不等于c的左s是的,因为a是等于c,h是不是不等于c的右孩子是的,因为h现在等于c,所以这个成立成立怎么办,战中压入c的左孩子。

战中可没有弹出这个一,但是把他左孩子压进去了。

c的左孩子是二,所以压进去了,除此之外发生了什么变化吗,并没有,如果我中了逻辑分之一,其实我既没有去设置h,也没有去设置c c只是在第一条被设置了,接下来逻辑分之一跑完之后就重新执行while了。

所以我们继续看,所以c其实非骑士啥其实没有设置是吧,在他之后没有设置啊啊然后继续继续继续。

那就是在pk对吧,站中c再来到他pk的位置,所以c往下移动,它就会来到二位置,往下移动它就会来到二位置,其实还是没有弹出pk。

那么现在看第一条逻辑分支成立吗,c的组孩子是不是不等于空,是的,c是不等于a c h是不等于c的组子,废话h现在是c的负,当然不等于,是不是不等于c的右孩子已经说了,告诉你他是负了,当然不等于。

所以第一条逻辑分支又重了干嘛,c的左孩子进去。

a4 进去。

然后就没了,然后再去跳进这个while里面,来继续执行好的地域执行c又来到他pick的位置。

c在这,此时逻辑分之一就不成立了。

c的左孩子等于空了一道分支,跳过,对吧,第二个c的右孩子不等于空,并且h不等于c的右孩子吗,没成立,还是为孔,所以跳到第三个逻辑分支好大in,当前栈顶元素的值h来到c的位置。

所以发生了啥,弹出打印。

函数打印,然后h来到c的位置。

a是直接跳到c的位置。

这个while,那继续这个while,一上来c就会来到站pk的位置。

c会来到二,下面这个过程你就逐渐感觉到有门道了哦,c过来到二。

左孩子的确是不等于空的cv啊,h不等于c的左孩子吗。

不是的,h是c的左孩子。

所以第一条分支没中,右孩子不等于空,并且h不等于c的右孩子吗。

这条中了谁的业务,孩子的确不等于空。

而且h也确实不是c的右孩子,所以干嘛。

加入他的右牌子,那么接下来继续就是c继续来到战争pk的位置,一条逻辑分支没中,因为c的左孩子跟左孩子等于空。

第二条逻辑分支也没中,因为c的右孩子也等于空,c的左孩子为空,c的右孩子也等于空,所以前两条都没中,那就一定会中a死,打印当前站点元素的值。

都打印了。

然后h来到打印这个节点的位置。

这是蹦在这儿了。

然后继续重复弹出了五,已经弹出了,刚才重复啥呢,c回到pk的位置,哪个逻辑分支中了。

c的左孩子不等于空吗,是的c h不等于c的左孩子吗,是的h不等于c的右孩子吗。

没中h等于c的有孩子。

所以第一条逻辑分支没中逻辑分支,c的右孩子不等于空吗,a是不等于c的右孩子吗,等于也没中中了,第三个打印。

啥意思,他是这样搞的,当前来到的节点是c虽然他没弹出,如果我上回打印的节点h节点它正好是我左孩子,因为我想做出后续来,如果h永远跟踪的是上次打印的节点,没错h它会永远跟踪上次打印的节点。

在这儿呢是它会永远跟踪上次打印的节点,这个c一开始是pick,然后你打印的时候,它弹出节点本身它其实就是pk理解吧,然后h来到c就等同于是在跟踪刚才弹出的节点。

那么如果一个节点上回打印的是我的左孩子,说明啥,我该开始搞我的右数,弄完之后再打赢,我,如果上回打印的是我的右孩子,说明我左孩子和右孩子都打印完了,打印我之后往上反a就卡住了,当前打印c的位置。

具体解释的细节一点,具体解释的细节一点,它就是说,我想记录整个就说我来到一个节点的时候,不过我发现我左树没有处理过,我怎么知道我左数没有处理过,如果我左数都处理完了,他上次打印的节点是谁。

后续如果我左数处理完了,他上次打印的节点就应该是我的左孩子,可以知道a是会来到左孩子的位置的,这就代表我左数处理过了,同时什么叫我左数处理过了,还有一个条件就有可能是我已经把左数处理完,右数也处理完了。

这也叫我左数处理过了,那么如果是这种情况,那么你h就会来到他右孩子的位置,因为是后续,后续是先左再右再中,真的如果我发现h上次打印的节点是我的右孩子,我也代表我左数处理完了,什么叫我当前节点。

我怎么知道我又数处理完了呢,h来到他右孩子的位置,上次打印的节点是他右孩子的位置,就代表我右数处理完了,这种情况下,我就知道该打印我了。

大家看一眼这三个逻辑分支,你就知道了,我孩子不等于空,并且h不是c组函数的,这就是代表上次打印的h不是c的左孩子,并上次打印的节点也不是c的右孩子,那你这个c是啥听到的,这个c的左右两个数都没处理呢。

你给我去搞左数,去先搞左数,如果我左数弄完了,我已经确定我左数是处理过的了,我看看如果c的右孩子不等于空,并且上次打印的节点不是c的,幼孩子会代表我又数没处理处理右数据,如果前两个分支都没中。

说明左右两数都处理完了,搞你自己返回设置h跟c就是在卡逻辑,利用临近状态的关系标记当前节点,左右两处处理完了没,我同学打一,我没跟上思路,没关系啊,没关系没关系啊,你现在现在我们重新来过一遍例子。

有这么多同学答案,我肯定是要重新讲的,你就认为第一个逻辑分支就是当我左数没处理的情况下,我去处理左数,二个逻辑分支就理解为当我又数没处理的情况下,我去处理右数,有一个分支就代表我左右两竖都处理完了。

我该返回了,按照这个思路再过一遍例子,你看你有没有什么体会。

在哪。

一开始在头节点的位置把战中放入了。

hc指向的是空,其实这里面有一个处理什么,如果你从来就没有打印过任何节点,只要保证h来到一个不会,你该不会干扰你代码的位置可以了,听懂他还打一,如果你没有打印过任何一个节点。

你只要保证h处在一个不会干扰你的位置就可以了,用他来打一一,只有当我们打印完了之后,h才被正式赋予了它实际的含义,听懂这个意思吗,听懂他在打一,没懂打二,当我们第一次只有当我们第一次打印的时候。

h才被赋予了正常的含义,那么在这之前,啊你我们想要做到先左在右在头的便利,其实这个代码你也可以直接写成什么,我就先让我左边界进站行,然后你打印一个节点之后去接我们这个逻辑也是对的。

或者你让h处在一个不会干扰你的地步,你总走逻辑分之一。

永远是先处理我的左数。

懂啥意思吗,我一上来整棵树我是没有打印任何节点的,但我知道我需要搞后续的,其实你也可以认为我一开始不由分说。

先把我的左边界进站,如果你想写成一份代码,你就要保证是处在一个合适的位置,让你左边,让你第一个逻辑分支走到充分的条件,就是把整个左边界走完,对不对。

好,那么我们注意我a是为什么一开始不动,就是这个目的,我们看一下,先把一放到头顶,先把一放到这里去。

然后来看战中的pk节点。

一就来到了一,h处在的位置是不是不会干扰他走逻辑分之一,是的,我保证我处在一个很好的位置,我就可以去走逻辑分之一,别干扰我去先把整个左边界放到这里去,h一开始其实是无意义的。

你只要保证它不干扰逻辑分之一就行了,所以总走逻辑分之一就是我总是先处理我的左孩子对吧的位置,左孩子不等于空h因为是我设置的,不会干扰你的东西,所以当然不会干扰你,他不是你的左孩子,他也不是你的右孩子。

那你其实前几步就是很顺利的把它组孩子加进来,听没听懂啊。

这就加一发现h不是他左孩子,也不是他有孩子,他也有左孩子,二进来就会来到pk位置,二,是不是你的左孩子,是不是你的右孩子,你的左孩子又有四进来,1~4。

c来到四的时候,就是c现在等于pk了,c的左孩子不等于空吗,等于空,c的右孩子等于空,所以前两个逻辑分支都没中,这说明啥,这说明你左右两竖都处理完了,只不过它是空而已,别弄你了。

所以打印,出打印,是被正式赋予了一个含义,上次打印的节点是会来到四的位置,可是上次打印的节点了哟,好再来到pk的位置,c来到二,这种情况下,我问你,我左数处理完了吗,处理完了我怎么知道他处理完了呢。

因为h上次打印的节点是我的左孩子,就是说对我左数来说,它已经完成了先左在右在头部的打印了,所以他上次打印的节点是我的左孩子,我就可以忽略掉左数去搞右数了,他怎么知道我的右数处理完没处理完呢。

因为上次打印的节点不是我的右孩子。

我可以去找第二个分支,我诱孩子是不为空,且h不是我有孩子的,刚才打一,所以我们继续我就走了。

我的右第二个分支啊,我终于可以让皮克节点死十的c结点的右孩子去走了,你想一下,你现在是来到的位置,如果五下面有一坨节点,它整条左边界会不会非常顺利地进到站里去,因为这个h如果来到这个节点。

你现在来到五了,整条左边界在进的过程中,h是不会干扰到的,如果左左如果五左边继续有一大坨节点的话,在这里面他没有,我说如果他有的话,a是处在的位置,是不会干扰你继续去走,关于五这棵子树的逻辑。

分之一的听了打一,好那在这里面没有没有,我们就不废话是吧,没有我们就不废话,那干嘛呢,五开始进去了,五进去了之后就会来到pk的位置,五位置他既没有左孩子,也没有右孩子,说明说明我这关于五这个节点。

我处理完他左数了,处理完他又输了,只不过它是空而已,打印五,打印五,然后c再卡住pk节点的位置,c又来到这了,in 5了,h就会来到上次打印节点的位置。

我们只要打印就会来到pk的这个p这个c的位置是不是pk,你是不是刚弹出啊。

所以h就是来到刚打印的位置,再看我现在这个c卡到二上了,我左数处理了吗,处理了我怎么知道的,我那右数头节点都打印了,那必然是左数弄完之后,右数也弄完了,才出现这种状态的,所以根本就不用去管左数。

这就是为什么我们判断左数有没有处理。

要关心h是不是他右孩子的原因,右孩子代表连我右数都处理完了,你左数当然处理完了。

再看我,我又数都处理完了,所以我不用处理我左数了,我上次打印节点是我又输了头,我也不用处理了,我彻底他就完事了,你打印往上就得了,整个代码它就串起来了,听我同学打一,七打二的同学现在懂没懂。

就是在用设置这个h上次打印阶段的位置来标记此时的头,暗中的头节点,它的子过程有没有完毕,就这件事儿,啥意思啊,这是一种非常极客的写法啊,当时我写出来。

其实,因为我其实知道你用一个战士能够搞定所有的是吧,但是虽然他可能比较扭曲是吧,这个代码本身就是这么回事是吧,把逻辑分之一当做左数有没有处理的逻辑来看,也是右数有没有处理逻辑来看,当然这个h的解释。

打印之前你别干扰我去压左边界,打印完了之后,你要确保可以用你来标记我左右两个数有没有都弄完,基于这样一种设计去写代码啊,好可以吧,嗯那么这就是我们这个递归方法和非递归方法去实现数的便利。

尤其这种方法还蛮骚的,是我们现在看继续啊。

层遍历是吧,休息两分钟吧,休息两分钟,因为从距离我上次吐到现在也已经50多分钟了吧,休息两分钟,这个没关系,讲得慢,我们就拖一下,反正就课的时长,我一定要是一定会不够的,肯定会给大家讲完,好吧,还不够。

我们就讲了15节,16节啥的,两分钟继续啊,我把这个代码给大家看了,大家再看两眼好不好。

继续,我我我我下周肯定会把源代码搞到b的github上,太忙了,我总是找不到他是吧,他要么就是发发发验证码的时间早就已经过期了,搞一个我自己的gp,然后把代码传上去,你们直接down。

然后等到他们想起来之后,我再去用域名了吧,好吧嗯,就是就是企业版的那个b的账号好吧,其实公共资源是吧,关键是怎么解释,来看一下这个。

下面继续实现二叉树按层遍历,其实呢就是二叉树的宽度有限便利就是举个例子啊。

就比如说,顺序是1234567,这样来按层遍历是前面又有一个八,这边有个九,然后其他店都没了,然后九后面有呢八后面这有个十,这有个11 九后,这有个12,有孩子没有这样一颗奇奇怪怪的书。

那你下面就要先打印八九再打印,在打印八九对吧,然后再打10 11 12,按层一层一层的输出。

所谓的二叉树的按层遍历,它是用队列的啊,嗯用用队列的,我们在图的时候还会再讲一下图的便利啊,图图在图便利的时候,它就要加结构了,再加一个set,为什么,到时候再说是不需要二叉树,是不需要的。

一个队列就够了,可以通过用设置flag变量的方式来来发现某一层是否结束了,我们先看第一个啊。

先看第一个怎么实现宽度优先遍历,用队列的方式很简单,这就是这个这个数的便利,准备一个队列对吧。

准备一个队列啊,我们来画一下啊。

是吧。

然后就是同点进到队列里去啊。

一就进去了嘛对吧,一直接怼到这儿了是吧,他是一个队列排队嘛。

一进去之后干嘛呢,你你你你开始整个队列的判断,如果队列不等于空,就继续,现在对,这的确是不等于空的是吧,它方式巨简单谈,从队列里面拿出一个拿出就打印,先加左再加右,结束了。

真实是这个过程也是非常顺的,一弹出就打印,先加左再加右,所以2314进去,然后再弹出二打印4514进去,三弹出就打印,弹出就打印,671次进去,永远在玩队列,每一个节点先左再右,每个节点先走。

那你那你队列的顺序它就是按藏计时,按g是在队列中按层一层一层加的,也是在队列中输出的,就这么简单,听懂他在打一,下面我们玩一个比较骚的啥呢。

诶这个啊,这个题就是我现在有一个问题,就是请你统计二叉树的最大的宽度。

哪一层节点数量最多,我就认为它宽度最大,这一层节点数量是最多的,层的节点数量有几个,我就认为它宽度多大,你要告诉我。

他并不一定是最后一层,比如说我最后一层如果只有一个八,只有一个九的话,最后一层的宽度其实只有二,是这一层是最宽的,要求什么,这就要求我们不仅能够按层一次打印,我们还得发现某一层开始或结束能打一。

所以我们来看这道题,你你这种发现每一层的开始跟结束这件事情你得做好,他就会比单纯刚才按层它整体的东西还是按层便利,但此时你要加机制对吧,在这个在这个宽度优先遍历的过程中,你要加一个机制。

就是发现一个层开始了或者一个层结束了,我们可以说我们如果可以发现每一层的结束就够了,因为你这一层结束就势必这意味意味着下一层的开始吗,或者我我们可以用一种机制实现我们发现每一层的开始,这也行行。

你发现每一层的开始或结束可以限定在我,只要能够发现新层开始就够了啊,或者你我只要能够发现某一层结束,这也够了,因因为每一层的结束一定意味着下一层的开始对吧,这是一,所以其实只有建立一个发现机制。

其实也能够实现好,我们来看一下。

不不卖关子了,求最大宽度的代码,那我们先看第一种方法,就是用map的方式,我们去发现层数开始或结束,我们选择用map的方式,但是不用map的方式,不用mac的方式,就是我还是要用队列。

但是我用有限几个变量,我就可以发现每一层的开始或结束了,那么用跑的方式呢就会更直白一点,啥意思,大家看准备一个队列。

哦我们我们拿例子来过是吧,别别别,你搞乱了是吧,123下面是4567,下面来个八二个九吧,这棵树还是这么一个队列,此时我们要加机制。

加什么机制呢,我们看用用map的方式是一个经典面试题了,而且经常考啊,求数的最大宽度,那么有一个队列把这个头节点加进去。

这不用说啊,好加进去,一加进去是吧。

底下有一个level map,map是啥意思呢,它这个它这个map它是一个node,是key整数,啥意思,就是,从,这个信息它就是value,level map的含义。

你这个node它在哪一层都存在level mac里,那么你进队列的时候,我当然知道害的在第一层我就加入head的,他在第一层,那么底下这个变量是啥呢,就是,说你现在在统计当前层的啊。

你现在统计的层数是哪一,就用这个变量对吧,当前,正在统计,一层的宽度,就是当前层的意思,那么你当前统计就是你当前正在统计哪一层的宽度,那么这个宽度是多少呢,就他这个当前层。

就是上面这个current level层,宽度目前是多少,为什么是零一,我们约定好一个节点,它出来的时候再把它加到宽度上去,就是为什么我害得进去的时候,我不让他是一,我一律规定好,当一个节点出来的时候。

我再把它当前层的节点数加加,max就是你更新的所有层的宽度中的最大值,我拿max给它抓住,返回这个max,理解这个意思吗,这几个变量都明白,同学打个一,我们进去的时候,我们不统计出来的时候。

再把它的数量加加到当前当前层的宽度上,懂得对吧,这就是为什么我害得进去的时候,我不算它,它出来的时候我再算,大家看一下,那就下面就是对列,再要弹出了好队列弹出了一个节点好。

我们把它标记好,把这啊这这我们有一张map是吧,这这这这这是我们的level map,标记好一这个节点它在第一层是这个意思吧,我们建立好了这个记录了吗,同时我们有几个变量写中文啊,当前层是多少。

前层是多少一层,那么当前层当前层节点数是多少,因为这个还没有出来节点呢对吧,所以是零个,那么全分局的层数,就每次统计的时候,当前层的也就是全局max现在是零啊,你这总有总有更新它的时候,你不用你。

你放心是吧,好我们现在就开始了。

是便利了是吧,第一个节点的时候,current啊。

哦便利了,我就把一一给拿到了。

出了嘛对吧,他从这里面弹出了,弹输的时候,我因为我当时在加入这个节点的时候,我知道他在第几层,所以我当然可以把level map这个当前节点在哪一层给取出来,当前节点的层数是个临时变量好。

那我就取出来了,我有level map,我就知道他在第一层。

就知道他在第一层,他如果左孩子不等于空列中加入左孩子,同时标记一下左孩子的层数,我为为什么知道他是加一,废话,你当前在这个层,你左孩子他能不是加一吗。

以我们可以很顺利地把一的组s2 放到队列里去,并且直到二它在第二层。

右孩子也不等于空,把右孩子放到队列里面去,当然也可以建立他的记录,又孩子在第二层,所以这每一个节点它在哪一层的记录是什么时候加的,都在入站入队列的时候加。

我当然也可以知道三节点,它也在第二层,然后。

开始更新我层数的统计了,上面你可以认为是宽度优先便利,只是我把level信息也也要建立好吧,这很好理解,如果我当前节点所在的层数和目前统计层的层数一样,那你这一层没过期呢。

那你当然要把当前层的节点数加加,这完全没毛病是吧。

你看我当前确实统计的是第一层的东西,你这个一节点弹出的时候,它也是第一层的东西,那我当当然要算到目前统计上来好,我在当前层的节点数我就发现了一个了。

啊好我发现了一个的状态下,前层没有结束呢,所以我就不更新max了,统计完没有中else它就会重新执行这个while好,那么在重新执行这个while的时候。

你当前层是一,当前节点数是一max,没更新好,继续遍历,当我二节点出来的时候,禁他的时候,我就已经记录好它的层数了,我当然可以得到它的层数,他在二层上二层上啊,二节点也进去了,三节点也进去了啊。

这个一的时候二也进去了,三也进去了。

然后现在要弹出二,弹出二的时候的时候,它的层数就可以得到左孩子和右孩子,如果有的话。

进队列,并且建好level ma非常顺的,我既有左孩子,也有右孩子,所以四五进去,我在第二层,我的孩子都在第三层,就没有任何问题,所以四节点在第三层,五节点也在第三层。

注意看,我现在的节点在哪层,二层上,我中没中,第一个逻辑分支我没中没中,说明什么,上一层该结算了哟,上曾要结束了哟,所以干嘛把一层的抓到的节点数,你们现在可以结算了,怎么结算,拿去跟全局max比较。

我就抓到了目前为止的最大宽度十统计的层数,也就是说上从当前层的一我姐我统计完毕了。

我现在来倒是第二层的节点,我统计完毕了,所以最大宽度被我现在俘获了,当前层数把它给给max,我现在来到第二层了,ok当前层我就要变到二,是新层弹出的第一个节点,所以当前层节点数设置为一,你已经弹出了。

千层,当前层的节点数直接设置为一,因为此时弹出的current就是新层的节点。

二的工作就做完了,三出来的时候他也可以得到它在二层怎么得到level map拿到会把他的六,它的七加到队列里去,也会建建立六的节点数在三,七的节点数也在三,因为他自己在二层。

那么此时我二层跟当前层是不是一层,是的,所以说明我这一层还没过七,节点数变成二,还没有结算,所以不更新max,我在四层出现的时候,他他可以通过live vip知道他在三层,就知道我上一层统计是过期的。

我把我当上一层的统计去更新这个max,它就变成了最大宽度为二了,同时我新的层开始了,你是第一个,所以设置为一,利用这种机制,我每一次都可以发现哪一层是否结束了,新层是否开始了。

我从开始的时候,这个就是else逻辑,我就把上一层的最大宽度更新,这个max横加加,心疼的节点数设置为一,如果我当前层没有过期,我就只把当前层的节点数加加就行了,但是。

即每一层的最大宽度是否要更新麦克斯的机制,当你有最心疼的时候,你才能去把上一层的结果让他去更新max,那就一对着你最后一层其实并没有触发更新max的机制,所以你不要忘了,当while遍历完成之后。

你要单独再更新一遍max,因为你的最后层也没有新的层去结算它了,听懂同学打一,我们用map的方式,说白了就是很简单的一件事儿,什么呢,每一个节点在进队列的时候,现在进队列的时候把它的层记好。

我是可以知道它在哪一层呢,因为我知道它父节点的层,我就知道它子节点的肯定是加一层的东西,那么这节点弹出的时候,我就势必能够拿到它的层数,如那我当前统计的是一层的,那我这一层的节点数加加就行了啊。

它我当前的节点层和我当目前统计的层不是一层,说明新的层开始了啊,新的层开始了,你就把上面一层统计的结果让他去更新max,因为我要记最大宽度,同时是新的层数另起了一层节点数,从一开始继续统计。

但是这种机制一定是新曾到来去结算老层,每一个新层到来去结算它上一层的老层,那么就一定意味着最后一层是没有被抓过,那么你不别忘了,最后时刻你要单独抓一下最后层的记录,刚才说很懵的同学有没有懂,应该是啊。

小陈陈同学,你懂了吗,懂了是吧,嗯,好所以这就是我们用map的机制,还要给你看,不用map的机制,我不想用map,我就用一个队列,怎么实现也容易。

我们再来过,这个不用map了。

我们怎么知道一层结束了,就这件事儿对吧,用一个队列,用有限几个变量了,我们先来把这个变量都列一下。

叫current end啥意思,它表示的是,潜藏,前层最后一个节点是谁啊,层的最后一个节点就是最右节点是谁,或者这么理解是吧,当前层最右的节点是谁,什么意思呢,就是所有下一层的话,下一层最右节点是谁啊。

我们的全局max不不就是在这个过程中,我要更新最大宽度,这个节点,老朋友了,前层的节点数,唉少一个少,就是你到底现在在统计哪一层,对,其实并不关心我到了哪一层,我只要能够把每一层,见他结束的时候都找到。

其实我并不关心哪一层出现这个最大的宽度,你只要让我每一层都能够发现,结束的时刻更新一下麦,每一个图都能发生,结束的时刻更新一下max就行了,其实严格来讲,我并不关心我到了哪一层,听我同学打停。

我没有道理非得关心哪一层吧对吧,我我要的是最大宽度,你管我在哪一层发现呢,只要你能让我每一层都发现结束就行了,好那么所以我们看你你你你这个头节点进队列了,那你对于你头节点所在的层是不是最右的。

的确是,这不是显而易见的吗,你这一层是不是一是最右节点,是的,所以我们这电量怎么设置,一上来当前层就current n,它最右的节点确实是一,那么你说我下一层最右的节点是啥呢,我他娘的知道是啥。

我根本就不知道对不对,空,知道吗对吧,下一层我还没有遇到任何节点。

我当然不知道,所以怎么办,就设置为空,那么当前层为什么是零,还是那句话,弹出的时候统计统计。

所以我就那那么我我们当前层单层的嗯,note的数量,然后有个max一开始是零对吧,就这些变量,这是当前,这是当前层的最右节点,这是下一层的最右节点,当前横的note数是零。

好开始玩了,我怎么样能够标记一个一个层的结束,马上就来了是吧。

弹出一个节点没问题,弹出一个节点,我一开始把头低点加进去了是吧,一开始把头点加进去了,然后弹出一个节,弹出了一。

头节点加进去了,然后弹出了当前节点,好边不等于空加入左,右边不等于空加入右诶,你看,调整咱就不用说了,经典的宽度线便利,next的n总是在往右动,所以啥意思,当前层我永远在随时更新它下一层的最右节点。

我当前层出来一个节点,我的下一层的最右节点就会更新,但如果有我下一层就相当于移动到它左边,右边,如果有我就继续再往右移动,所以这个逻辑是啥。

就当我一弹出的时候,首先他们二三进去了,下一层的最右节点是先被更新成了二,三,进去的时候又被更新成了三。

然后呢,你当前节点弹出了前层加加没问题。

当前层的节点数加加变成一个。

那你是否当前节点就是当前层最右的节点呢,如果是唉,你结算吧,如果当前节点是当前层最右的节点,你结算吧。

你把你当前层的节点给max去更新。

即将开始的就是下一层下一层节点,你现在发现了没有,你还没发现没有弹出,你只是这一层的最右节点哦,下一层的一个节点都没有弹出哟。

所以零。

我马上要下一层了,下一层的最右它马上就要变成当前层了,设置我下一层的最右节点机制就转起来了对吧。

我下一层的最右节点是三,所以我即将要开始新的一层,所以我当前层的最右节点也变成三,再弹出就是心疼的节点了,于是周而复始,怎么周而复始,展示一下就懂了,出的时候二弹出的时候,左孩子进去。

再下一层的最右节点更新成四,又孩子进去,他在在下一层的最右节点更新成五,就是说我在当前层的时候,我要为我下一层最右节点做准备,一在我这一层结束的时候,我下一层的节点可以直接变成当前层的节点。

就是用这种机制完成的,每一层发现它结束的时刻,听了一,当你三弹出的时候啊,你三弹出的时候也一样,三弹出的时候,左孩子要进去,右孩子你要进去,同时下一层的节点从五会先变成六,然后从六再变成七。

每一个弹出节点,左孩子右孩子都更新这个下一层的最右,这一层打完之后,那我最右,那我下一层的最右一定会来到七的位置,我每一次都这么干,那不就对了嘛是吧。

就就就就就这么一个事儿是吧,你会发现这个为什么不用加,最后一不是新层出现才去结算老层的,我是每一层老层结束直接结算的,所以到里面完全做好统计,根本不需要加刚才的最后一行。

他就是对的,听我同学打,那么这就是我们这个暗层打印以及求了一个最大宽度。

问题就是你要建立一种发现曾结束的机制,这个东西这个东西其实经常考啊,你不是不会扣ding吗,我不是让你会吗,对吧好,继续聊一个,序列化反序列化,咱这个事就结束了哈,我们留在下午继续讲吧哈。

后面东西还是有一些的好吧,打印一颗二叉树的打印函数,这个事也不是一句两句能说的是吧,这也是一个常考题,二叉树的序列化和反序列化,大树的序列化呢是啥意思,就是你怎么把一颗内存里的树变成一个序列化的结果。

这话就是没有不挂的服务,你这棵树好好的画成那个样子,他是在内存里面串好的,你某一个时刻要停机,你那内存里面的东西做成文件的形式保留下来,你在开机的时候,你恢复成与你原来树的结构才有可能对吧。

但是你又不可能把整个内存做一个切片吧,做个shot吧,那代价也太高了吧,就要求而且内存里面好多杂乱的东西,没用的东西是吧,你如果把整个内存全部down不下来,那所以就要求你自己维持的结构。

你自己把这个你自己建好的数序列化好,最好是类似于字符串的形式或者数组的形式,总而言之是顺序线性的形式放到一个文件里下,你可以通过这个或者是数组或者是一个字符串的东西,给它还原回整棵树,而且结构也要一样。

这就是数二叉树的序列化和反序列化,听懂同学打一,非常考的内容,而且真的他他的变化太骚了是吧,它可以解决好多问题,很多很多年都不会注意,我们在讲k mp的时候,还会见到他在树上居然是可以玩kmp的啊。

你放心,我给你讲的是吧,我们看数的序列化,怎么序列化呢,你选择按先序或者中序或者后续或者层遍历的方式来学列化,全随你的便,比如说我们先讲按先序方式序列化是吧。

那这棵树它是这个样子的,这,这两棵完全不同的树结构不一样,所以知道单纯的你用先序遍历,后序遍历要记一个这样的先序中序,后序遍历结果的话,根本不可能可以先续后续中学便利的结果全是111。

但是对应的结构都是不同的,所以就意味着你用先序中序,后续的方式只是记录一个顺序的话,没有办法做到彻底还原数结构,所以,那就是我们把空节点加上,我们先介绍先方式序列化是啥过程,数组假设。

我们知道先会来到这个节点对吧,干嘛呢,在数组中进入一个值是先投在左在右的便利,所以下午会来到这个一节点,在数组中记录它,不要忽略空节点,你就会来到空数组下面就跟一个空,然后会来这个节点先去吗,再记一。

然后不要忽略空,所以一的左孩子我要便利,右孩子我要便利,不要加,不要忽略,忘了这个空也不要忽略,就是你彻底把这棵树啊,用空姐点补全建立的结果就是先序方式序列化,到底这棵树也可以这样干啊,这个节点。

然后一接下来不要忽略它的空节点,到这个节点,这个节点不越,不要忽略这两个空,在这个空,彻底的拿空,把这个书补全,这个空就意味着你占了一个位置,你标记它,可它结束了,对吧好。

这就是这棵树序列先叙方式序列化的结果,这棵树先序方式序列化结果。

听懂的打一。

说它能够反序列化回去吗,当然可以了啊,你这棵树是先向左拐再向右的对吧,不是先向右拐再向左的,我们看能不能还原回去,你用什么样的方式序列化,你就用什么样的方式反序列化,面对这个数组。

当时是按照先祖先头在左在右的顺序来搞的,所以我面对这个数组,我先用掉的值是来建头节点,所以我把这个一给用掉了,把一建起来,然后唉我要去见左输了哟,怎么建呢,利用剩下的值,你书也是先投再左再右的。

所以你用你下一个值建出它的头来,然后你再去见你的左数,一在左数也是先投再左再右的,所以你弹出这个空我就知道啊,然后你知道你不用再往后续了,这就是空的目的锁了,为啥,因为我已经是空间点了。

我就可以往上返回到一,再去见他的右数继续消费,再去见左数,继续消费,继续消费,二建又数,继续消费,这棵树就建出来了,同样你这个序列怎么去见它的二叉树一样的,我一消费整个数组,我是先投在左在右的方式。

我就先建立一这个头节点,然后我指望你去见左数消费掉了,直接怼有空,说明我左数建立过程完毕,我可以去见我的右数了,他消费完了哟,然后把一建出来,再去见他的左数消费,消费去见他的左数消费,空。

见他的右数消费,空见他的右数消费空,你看两棵树可以建立建立出来,而且结构不一样,它序列化结果一定是不同的,序列化跟结构完全一一对应,嗯。

代码也是非常容易的啊,离开先叙方式序列化,从头几点出发,请你把所有序列化结果你给我放到队列里去,可以吧,你把没有这个结果,你给我放到队列里去,可以吧,好那么这就是我的队列,那一开始是空的。

你在先连续方式序列化的时候,请你把所有的序列化结果依次放到这个队列里去,这就是我底下定义的这个先序方式是序列化的代码,好,那你看为空的时候,我当然加入空。

就是我先把我头节点的值给它变成字符串的形式放到在队列里去,然后左数也这么干,右数也这么干,序列化好了,你能你能懂,先去代码,你就能懂他啥意思,你不就是一一次先加头节点,把它值序列化了,去左数上该怎么干。

再去右上这么干嘛对吧,那么在利用一个先序序列的队列的时候,我想build出整棵树怎么做,那就是先序的方式,利用这个队列建出整棵树,并连好头几点返回啊,把你当前的值拿出来,如果你当前值是空的话。

那就要那就意味着我要建出空数返回头节点,当然是空,当时是先序列化的头,然后左然后右,我也要跟着他这么来,先把这个string类型的值转成我这个no的值,把这个node建出来,也就是我的头节点。

消费了一个油,它可弹出了呀对吧,然后我用同样的方式把这个对去见我的左数,把这个队列去见我的右数,最终肯定连好了,返回看还打,非常简单是吧,你你你你你中序后续就不用说了对吧,中序后续他就不用说了。

无非你要是中序方式序列化,你就调一下,在这个代码中调一下顺序嘛,你就先去搞它左数,然后把它的值序列化插在插在这中间是吧,插在这儿,那你就完成方式序列化了,如果你选择中序方式序列化。

那你在build的时候,你就先去建立它所述,把这一句它在这两句中间先去见他左,然后见它中间节点,最后去见他右数,这都同理的,这就是为什么我跟你讲递归序啊,递归序它什么都能弄是吧,递归序什么都能弄。

哪怕是便利的问题,还是什么打印的问题,还是什么序列化的问题,还是具体的处理的问题,全都是一样的对吧,不要忽略空嘛,不就这个意思嘛是吧,好我们讲讲特殊的,就是按层序列化。

层序列化,按程序列化的,跟他们代码不太一样,因为这个按层遍历它并不是递归实现的是吧,序列化,整体上就是宽度优先便利。

按层序列化的方式好,我们先说按层序列化方式,我们先想达成什么样的结果。

就是咱不看代码,你到底想达成什么结果,想达成这样的结果,中序列化的方式,123不要忽略掉空,啊不要忽略了空,不要忽略了空四,这也有空的,六也是这,结果是456之后,那结果就是还不忽略空。

你怎么暗藏的方式给我序列化好这个,啊你说的对,七八下面继续有四个空啊,没错啊对啊体,所以后面还是跟着四个空啊,开发方式啊,好啊,七八不能忽略,没错啊,不好意思,七八分不能忽略,没错啊,你说的对啊。

我怎么实现这个玩意儿呢。

你知道我要达成什么效果,我就写个简单的,因为太多的话,举个例子太烦了是吧,我怎么去序列化啊。

准备一个队列,录一个节点的时候,把它序列化的结果加进去,我们序列化的时机放在加入队列的时候,对吧,刚才我们什么求层啊,这种都是弹出节点的时候再怎么怎么怎么样化了。

我们把我们把序列化的时机放在加入队列的时候,所以你看一上来我就把头结点的值序列化的一个字符串,加到这个队列里去了,这上面就是一个队列嘛,哎如果他要是一开始投递点是空的,就直接把空调到这个队里去是吧。

头节点加到队列里去,准备好呃,呃头节点加到我的序列化结果啊,我们把分开来,answer就是序列化结果,虽然它也是一个队列,那么单独说加到结果里去,把头点的值加到我要便利的队列里去。

所以我们再准备两个一个两个结构,一个叫队列一就进去对了,另外一个叫序列化,结果就是我的answer好,你准备一个数组吧,你先把一放进去了,没问题吧,好我们现在开始。

做的时候就不用再序列化了,因为你加的时候序列化的好,你看弹出的时候,左孩子不等于空,序列化也加队列啊,孩子等于空,就只序列化,不加队列,左孩子如果不等于空,就继续列化,为空就只序列化不加队列。

那么好,我们就就就这个逻辑呗,你一弹出了冲啊,不为空,所以既加队列又序列化怎么干,幼孩子为空吗,不为空,所以既加队列又序列化,好继续,这出的时候也这么干,二弹出的时候,左孩子为空吗为空。

所以只序列化不加队列,飞空吗,不为空,所以既加队列又序列化,活动是要序列化的,无非就是你空了就不对,就不再加队列了,就这个意思,三出来的时候也一样,翻出来的时候,左孩子为不为空,即加队列又序列化。

右孩子为空,所以不加队列,只序列化,四五的时候就后面就是跟着四个空嘛,听懂他打一,二叉树完全二叉树哪是这个样子是吧,完全二叉树是从左往右依次变满,那个事儿,我们我们只是用空把它补齐,它不是完全二叉树。

理解吧,补齐之后他也不是你,我说我我说的是美层都得是满的,或者依次变满的结构叫完全二叉树,我们变一棵普通的树,拿它把它空补齐,它该不是二完全二叉树,还是不是理解这意思吧。

嗯好怎么反序列化呢,那同样道理,你怎么你怎么反序列化对吧,方式,就是我们看这方法,这个方法很简单啊,就这个这个虽然这是个还是个小函数,你给我一个string,我怎么借出节点来,如果是空的话。

我给你一个空节点,如果它不是空的话,我就真的建出一个节点给你,怎么理解这个,因为我当时加了空,所以我左孩子和右孩子,我是死活一定要建出来的,这个没有问题对吧,你不管你是空也好,你不空也好。

我左右两个孩子,当时我不管你加没加队列,我都给你建出来了,无非他就是拿空座占位符了吗,弹出的时候我见我怎么见整棵树,左右两个孩子是一定要建的,左孩子不等于空队列,加左右还是不等于空队列加右。

继续周而复始,给我建下一层去听,啊对吧,就是你当时序列化的,那时候你是死活都要序列化的,但是你只有不空的节点才去加的队列,那么当你反序列化的,就是你死活一定要建节点的,哪怕它是个空节点,你也要建。

但是不空的时候才加队列,不一个道理嘛是吧,这个啊就是我们这个二叉树的序列化和反序列化内容啊。

剩下还有一些题呢,我们留在下午讲啊,因为嗯打印一棵二叉树啊,包括这个或者三道题是吧,都不是很容易啊,下午讲完之后开始开这个数一批的新课好吗好啊,满分十分,然后我们休息,下午两点继续好吧。

系列 2:P8:马士兵老师JVM调优:8.根据压测结果调整参数值 - Java视频学堂 - BV1Hy4y1t7Bo

就问这种特别触及问题的,我只能认为你的基础确实特别差,我就稍微照顾照顾你,首先黑白灰是一个逻辑裸机上的概念,并不是他那个你打开电脑,它里边真的有黑色对象,比如说它有一个标志位。

这个标志位写的零一就代表黑色,这个标志位写的一零就代表灰色,写的零零就代表白色,到这里能get到吧,怎么把黑色,把黑色变成白色,你就把零一改成一零不就完了吗,气死我,好啊,朋友也不能回答。

因为所有人都是从小白过来的啊,刚才那个小白你也不用怕老师怼了,越被老师怼的人成长越快,所以怼两下又怎么了,不就丢点人吗,谁也不认识他,对不对,那个人叫什么,你们还能看,你们还能找得出来吗。

你就找不出来人名了,都所以他丢人就丢了,一秒钟,也就丢到了这个小小的直播间,这有什么不能承受的,别问了,再问一遍,老师生气了,受不了了,要炸了,黑色的不会再扫描,因为黑色已经扫描过了。

不是所有黑色的标记成灰色,只有新的黑色的诞生了,指向了新的对象,有新的对象指向的时候,这个时候说明它产生了新的引用,这个黑色的就得变成灰色的了,灰色的在下一轮的时候要重新扫描,黑色的已经被扫描过了。

ok看这里,这怎么完成的,它叫做right barrier,叫写屏障,咱们先把它略过吧,那个真的有点稍难了啊,我们先把主干讲清楚,注意看incremental,实际上它有一个非常隐蔽的问题。

incremental update,由于这个方案特别简单,但实际上这个方案呢会有特别隐蔽的问题,看你能不能听听得懂,认真听啊,在并发标记的时候依然会产生漏标,what它把它变成灰色的了。

居然还会产生漏标,原因是什么呢,标准黑色的下轮就不再不再扫描了,变成灰色的下轮会继续扫描啊,好看这里为什么会产生呢,仔细看b指向d的也又没了,a里面,如果这时候a有两个成员变量,我分别用一和二来指代它。

这个时候呢一这个成员变量指向了d,大家都知道a要变成灰色好,a要变成灰色,这个比较简单,但这个时候啊,你假如有另外一个线程,这个线程是什么呢,哎有人来就回收线程,垃圾回收线程在这轮是并发的。

会有好多个垃圾回收线程,那么这个垃圾回收线程干了一件什么事呢,他正在标记这个a呢,这标题这个a标记到哪,标到什么程度呢,已经把这个一给标完了,注意它已经标完了的情况,已经标完了,然后正标那个属性二呢。

这个属性二指向某一个对象,正在标这个在这个过程之中,在这个过程之中,注意一已经标完了,接下来标完了之后,又指向了这个白对象,被一个线程给标,把这个一标完了,标完了之后又指向了一个白对象。

就是另外一个另外一个线程把属性一又执行了白色对象,这个线程已经把a的属性一给标完了,哎但是呢另外一个线程又把这个一给指向了一个白色对象,然后呢另外一个线程把a标成灰色,那就会出现成变成灰色,为什么。

因为它指向白色对象了嘛,所以把它变成灰色,然后这个县城原来标这个现状,他继续,因为他标完一了,他马上又标完二了,把二标完了之后,唉又把它变成黑色了,因为它这个线程认为这对象已经标完了,我把一也标完了。

我我把二也标完了,这个线程肯定会认为这哥们儿已经是变成黑的了,对不对,他实际上不知道,在他把一标完的这个过程之中,另外的这个一只相了一个白的,然后呢它已经变灰了。

结果呢他二话不说又把它给变成变回是纯黑色了,一和二什么成员变量,好这段没听懂就算了,好不好,有点绕,对于有经验的小伙能听懂,对于没经验的小伙呢都琢磨琢,没关系啊,呃这种问题也没人问,听懂了吗。

没有面试官问,放心啊,没有人面试官问这篇论文,问他主要问什么问题,就是说incremental update,为什么cms里面用,为什么记忆里面不用这种解决方案了,原因就在于这儿。

因为它依然会产生漏标的问题,而在cm,c m s呢他自己也知道它会产生漏标的问题,所以在cm s的最后的remark阶段,在这个阶段应该得从头把那个什么的都扫描一遍,当然由于它进行了一个清理了。

所以这个扫描的过程呢没那么复杂啊,比原来那个简单很多好,所以它的s t w时间就没有那么长,但是如果你的内存越来越大的时候,这个阶段它依然时间会慢慢的变得非常长。

所以cms incremental update这个解决方案已经被close了,这个解决方案不再存在价值了,cms也在1。9之后被踢出去了,cm这个东西已经过时了,我这么直接讲,大家能理解了吧,那好。

下面我们来看g一的解决方案,还讲了太难了啊,就讲到这儿吧,要不然好不好,讲完级我们就不讲,不讲那个cdc了啊,c d c有十十的阶段,那个太难了,要讲完,咱今天晚上就别睡觉了啊,好看这里啊。

积极的解决方案是什么,积极的解决方案叫做i s a t b,所以请大家记住这几个名词,你跟面试官聊天,名词越多,面试官越懵,三色标记,incremental update s t b。

snapshot at the beginning,snapshot,快照at the beginning,刚开始的时候来个快照,这个呢呃这个这个这个解决方案相对就简也也比较简单,他是怎么干的呢。

他干脆就没有给a和d就没没没在这种a指向d的这个引用上啊,这个指针上没在这上面考虑问题,他考虑的是哪个呢,他考虑的是b指向地消失的这部分,这个指针壁纸箱地消失了。

就是说有可能你指向d的这个东西再也不会被扫描掉了,我只要保证这个地被扫描到就可以,所以呢它采用了一种解决简单的解决方案,这种简单的解决方案是什么呢,是这个,其实指的是做个快照,当b和d消失的时候。

把这个指针注意是把这个指针给保存一下,保存到哪里去,能保存到一个站里面去,我不管你这个d有没有被别人指向,没有关系,我只需要在下次扫描的时候,我能扫描到你这个d就行了,我看你这个d有没有被别人。

有没有被别人指向,你不就行了吗,好了,这个时候呢就把这个指针放到里面去,下一轮扫描的时候呢,就要看这个里面有没有被放进去的指针呀,那么如果有的话,把它拿出来,把这个对象拿出来之后重新扫描一下。

看看这个对象有没有人指向他,如果没有人指向他,就是垃圾了,如果有人指向他好,他就还不是垃圾,ok这个叫snapshot at the beginning,当然这里面更深的一些个理论呢就非常多了。

为什么这一会采用这种方案,因为这一点我概念叫remember set,remember that,配合这种方式配合起来特别方便,由于而且你原来有快照,你有这个快照的时候。

你可以用那个快照里面最根儿上那些个那那些个,那那那些个只扫描对头上那几个就可以了,所以它这个效率特别高,remember set是另外一个概念,我要给你讲remember set,还得给你讲cr。

还得给你讲,card table,没法讲啊,这这是到这吧好吧,我讲没,这真没完了,怎么被引用,扫描到自己就被引用了,这就是remember set干的事儿,ok但是我告诉你,在不久的将来。

所有关系这些个问题全都没了,不用了,所以有的时候我讲那些呢也没什么意思,但是不管怎么样,他还能撑几年好不好,所以听不懂也就听不懂了,过去也就过去了,只要你能坚持过这几年去,因为什么呢。

因为在z d c里面,它采用了更加牛叉的解决方案,这种牛叉的解决方案叫做color pointers,叫颜色指针,这个颜色指针说到这儿,我就简单给大家入个小门,颜色指针是什么概念。

其实大家知道一个java的指针64位,36 四,64个比特里头,他把这个指针里边的内容做了一个划分,划分怎么划分的呢,真正的只有42位的指针是指向java对象的,有18位是没有用的。

42+18已经60好,其中的四位拿出来做一个状态,区分状态区分什么意思,就是当我引用到这个指针的时候,我要检查这思维的状态,看看这四位是在哪种状态之下,我要做相应的操作。

哎你比如说你是个正在移动的过程之中,你垃圾回收器要移动,你移动的过程之中,我现在引用到你了,我去检查你这个指针,发现你在移动的过程之中,ok那我就稍微等一下,等你移动完了之后,我再用你。

我再用你里边的内容,哎,如果说我现在引用的这个指针,他现在状的没有动没有动,没有关系,我我就直接拿过来用,好了,这个叫做颜色指针,当然这里面涉及的概念呢就更多了,它会涉及到操作系统的关于内存映射的概念。

再说啊咱们再说呃,有一个非常简单的面试题,叫做为什么z dc管理4t的内存不是4g是四个t,为什么呀,为什么它是四个t呢,看这里二的42次方等于四个t o,怎么叫移动中,怎么叫移动中。

你想想这个指针它指向一个java对象,这个对象还记得我们的region吗,回收它的时候怎么回收啊,这个对象要被挪到另外一个region里拷贝算法吗,我们记忘了g一分成一个一个的region。

cdc也是分成一个一个的region对象存在region里面,回收的时候,按照这个region来回收,怎么会说啊,把这个活着的对象拷贝到另外一个regi里面去,整个region清掉就可以了。

拷贝的过程要不要移动对象啊,那这个指针本来指向这里的,现在要把它指向这里了,你这个指针里面要不要动啊,做这个标志位,那我的程序要用到这个指针啊,我就去读一下这个标志位,哥们儿,你现在在什么状态呀。

正在移动中,哎呀正在移动中,那我得小心点儿,等你移动完了之后再用,好来get到同学老师扣一有那么难吗,你自己看就会很难,老师讲给你听,就没那么难,cdc会指人家说吗,不会他都64位全用上了。

你让他怎么压缩大哥4t怎么理解二的42次方啊,他用42位来代表一个真正的对象的地址,二的42次方不就是四个t吗,老师可以推荐讲的好的g一和cdc算法的文章吗,你自己去找我跟你讲。

我我往外往内跨墙FQ出去,我找遍了,没有讲,特别好的老师,这讲的还不够好,中国内的讲cdc的,凡是上面的文章你自己去翻啊,基本上没有,现在还没有讲的啊,好了今天到这了,不多说了,现在已经9。

40介绍我们的课程好吧,今天给大家讲的内容是老师讲完第一版的课程中的一小部分,我们这个是哪部分呢,就是这部分,就gm调优案例是两款指导啊,这部分呃,当然了,我是调了其中的一部分了。

本来我是从最根本的概念开始讲,一直讲到最后才是jc和调优呃,我只不过呢把其中的一些细节全给大家先略过来,教了大家的梗概性的东西嗯,主要是给大家讲了调优实战的这部分啊,就是为什么会频繁。

dc到底怎么样进行设定么,因为dc怎么办啊等等啊,交了一些实践性的东西,上线之前怎么规划,像这一类的还没有给大家讲过,这是整个课程中的一小部分了,诶哪去了嗯,当然这里面呢我们课程内容比较多。

先给大家简单介绍介绍这个课程,这个课程呢主要是现在被我们搞成了一个超级牛叉的一个巨无霸,就是我们课课程现在成长为不知不觉之中成长为巨无霸了,就为什么我呃给大家谈一下这个历程,就我们现在提供什么课程呢。

提供现在就是a是java后端工程师,这个是什么呢,是零基础的课程,就是反正基础稍差呢,你从a开始学好吧,跟着我赵云山老师,跟着林老师从a开始学,记住参加工作的有ss sm基础的a是什么。

a a就是那个那个那个线下的时候,那个花1万多块钱,15000 6000是吧,可以教教你的东西,就是我们的a课程嗯,然后呢有s这么基础的,我们现在推荐的是另外一个格,就是做b加c,b加c是什么。

b是互联网架构师,c是大数据架构师,就这两个架构是合二为一啊,就是你刚才看到的这个课程,就这节课,这节课呢我们叫他从零到年薪百万,一步一步对标阿里p7 的互联网大数据的商量结构师。

这些课呢也是我们独创的呃,这个课程呢其实前前后后经历了很多很多的发展,我简单跟大家交代一下,就这个发展呢还是比较比较那啥的,就是比较比较各色的呃,我们那以前是一直做线下培训的,大家也知道啊。

呃作为转到线上来之后呢,就一批老师成为了线上的那个公司啊,公司那叫马士兵教育,就是以我名字为明明好,呃,其实除了我之外呢是有一大堆的公司啊,sorry一大堆一大堆的我们的呃。

老师把这些老师呢我就不一一的给大家做介绍了,都是在线下很有经验的老师,呃,除了现象很有经验的老师之外呢,其实啊一会儿我可以请这位大哥给大家见个面啊,这是我们特别牛叉的,也是我的清华的小师弟,是朱老师。

他是讲那个造数据这方面的,呃,除了我们自己的这种在线下讲了很多年的那种老师之外呢,还有一些呢是在这种企业一线的老师,这个也是很宝贵的,呃,为什么我们能请到b a t j所有的老师。

就是就是你你随便找个培训机构,你说那个b a t沟的老师啊,全都聚齐了,不好意思,你随便找没有,只有这儿有bt勾的老师在这全剧情了呃,腾讯的罗老师,他是原来腾讯新闻的ai的主管,阿里的那个黄老师呃。

是原阿里的常老师,是现在在阿里工作的,那么讲我们数据大数据项目的数据中台项目呢,是原来的阿里的中台死结,是一个p 10水平的嗯,百度的赵老师来跟我们聊推荐系统的这个京东的齐老师呢。

我叫docker cbatis,以及呢现在这个秒杀项目,这秒杀项目也是在京东落了地的,可是很不幸的是呢,齐老师现在就被隔离了啊,不然的话应该已经已经开讲了嗯就是我在外面呢请了一大堆的老师。

因为学生还是比较多的,在各种一线大厂都有,所以找到他们呢并不难,嗯有一些也不是我学生啦,就是推荐过来的等等啊,就这样呢我们就成立了这么一个一大堆的老师,大概有十几位啊,这些老师的水平。

清华两位老师一位伟大的多,之后右边这哥们呢是长蛆的cpu,他马上要开始了,下周就开始了呃,网游后端的项目的第二版就开始了,第一版还是广受欢迎的,这主要讲net的这个呃。

海宁老师那个原来呢他是想去那边做游戏的,有好几款那个月流水过千万的游戏就是出自于他的手,刚取元帅,我不知道大家听说过没有,还有一个叫什么什么三国志来着,我忘了啊,哎这位小姐姐呢也是特别牛的。

这位小姐姐是留学北美的博士,他主要教他们什么呢,叫他们英语课,后面我和他一块儿教英语,教点英语课,主要因为好多人的英语实在太烂了,有点看不过去了,稍微教一点儿好呃。

然后呢我们这些人呢大概在2019年的中间,6月份蹲到腾讯课堂,到腾讯课堂之后呢,大概半年吧,到去年年底的时候,我们已经是在腾讯课堂的课程到了第一名了,我们已经做到第一了,也就用了半年半年左右。

当时是当腾讯课堂的时候是这样的,腾讯课堂呢有很多的已经有很多的人在讲课了,这他们讲的课呢多数都是什么什么样子的,都是一个一个的知识点,就是类似于什么呢,类似于张图里面的一个一个的知识点啊。

当然我的知识点还是能点进去的,你自己去看就行了,对这个对这个有兴趣的,呃有一个知识点后来说我干脆,那那我们也就先找超管,因为线上到底怎么讲啊,现在也当时也没摸清楚行,那就照抄盘,那我们讲知识点。

后来我们就提供了一个第一版的课程,这个课程呢是一个八个月左右的一个知识点的课,然后呢多数人呢都是说每周三次课啊,每次两小时一共讲八个月啊,多数的机构都是这样子,我们当时也就是这样子。

但是讲着讲着我就发现,因为我个人比较喜欢讲课,周老师比较喜欢讲课,讲着讲着我就发现我课的时间不够用了,我想讲的特别深,比方说我真的想给你讲到z b c的特别详细的算法,我给你讲到这些,你不给我时间。

我是肯定讲不到的,后来说算了,我们扩课程,我们第一次扩展直接就把八个月干到半年到1年半到2年的,我是说按照每周三次课来讲,扩展完这个之后呢,有小伙伴当然很满意了,因为他们当初交钱是按这个来交的。

交完之后呢,我们就免费给扩成这个样子了,他们当然很爽了,但是有的小伙伴呢还是不满意,小伙伴说老师有没有项目经验,想跳槽,从传统行业跳互联网还是跳不了咋办,杨老师,后来老师说,那行啊。

我给你找那个一线的做项目的人来带你做项目好,扩了八个项目,又是免费,就给大家破了这八个项目,这八个项目呢我觉得我就不一一的给你打开了那个,都是呃就是实际当中运行了的啊,上了线的那样的项目。

你写在简历里头绝对不会丢人,不是那种demo的项目的东西,多人在线即时对战的游戏服务器,吃鸡的后台,大体的架构就是这样的,我告诉你和将于这两个呢是只针对于水平稍差一些的,那么商城大家都有。

我就加一个像网约车项目,晚车项目呢是阿里的常老师,他现在已经开始讲第三版了。

还有这个项目呢也是我们一个挺好玩的项目,这个项目是什么项目呢。

这项目什么项目,这个项目是原来啊那个常老师进阿里的时候,对他帮助非常大的一个项目,这是原来呢也是一个不是特别有名的一个二线互联网的,他在30多岁才进到进到了阿里,进阿里的时候呢,这个项目帮了他很大的忙。

然后他现在把这个项目分享出来,那么这个项目主要讲什么呢,这个项目其实主要讲分布式微服务的,就是分布式微服务到底怎么落地,因为很多人学东西呢总是碎片化学习,他学一个spring cloud。

今天今天学点注册,明天学点监控,后天学点儿限流好,总是不会联系到说我实际当中到底怎么落地的呀,好这样一个项目让你来进行落地的这样一个项目,好项目的架构图不一,给大家看了所有代码。

二三十个人写完的代码全都给到你,你不用每个代码都敲完,读懂就ok了,呃另外讲东西的时候讲到什么程度呢,源码原理,源码原理源码就是基本上所有的点我们都会讲到源码,凡是不嫌我们课程深的,不嫌我们课程宽的。

找我们来学,除此之外呢,我们又还有一个项目,就是这个对于咱们结构师来说啊,jav这边的结构师还有项目就是一级流量,这个项目一流量的项目解决什么问题呢,也是我们很大一项目。

其实问题呢就是解决你架构师这方面的理论和实践的问题,就这个项目学校的目标是什么,京东阿里淘宝天猫12306拼多多,他们这些架构到底怎么玩的一个项目全让你理解,就是很很很有价值的一个项目。

很多那个外面的有一些搞教学的这一个项目就卖你好多好多钱啊,cp定理到资源的隔离怎么玩,数学服务的限流怎么玩,系统到底怎么样进行扩容和拆分,各种各样的降级方式,分布式事务怎么去落落地。

各种各样的网关该怎么设计,客户端的缓存,浏览器的缓存,enix缓存,lure resting release,访问,怎么样去进行register缓存,就多级的缓存该怎么样进行来实践,好高可用。

怎么样进行落地,使用什么方式给你编出来好部署到阿里云上,怎么进行部署,好了,这是这个项目,当然由于我们这是双料架构师,为什么要双料,现在玩架构师的,你说一点大数据的知识不懂,太开玩笑了。

就没什么竞争力了,还有大数据相关的三个项目嗯,推荐系统这就不说了,这个要牵扯到一点点的机器学习这个这个呃,但就是说这部分的呃难度在于什么地方呢,是要带一点一点点的机器学习了非常流行的东西了啊。

流式计算flink中台项目是阿里p 10的那个中台四节,来带大家落落地的做一个中台的落地项目啊,这个秒杀系统呢咱们暂时先等等啊,等等等一下那个什么的呃,齐老师呢,这个这个出来了好吧。

从闭关闭关之后出来了,所以最后就变成什么了呢,最后我们这个整个的课程就变成了一个巨无霸,这课程怎么叫巨无霸了呢,嗯,从八个月开始到18~24个月,再加了八九个项目。

就是整个课程就变成了大概是1500个学时左右,妈呀我们从来以前没有算过,突然一算,我靠居然居然到1500个学时了,你们知道吗,大多数的人如果是八个月,每每每周三次,每次两小时,你自己算一下。

他们的学识是200个,200个不到192,我们现在学识是多少,1500个,所以这就诞生了一个特别巨大的问题,我到底该怎么教你,我真的不能让你从1500个学时从零。

你一直学完1500个学时才能让你干点事儿,这个我肯定是不能让你这么来学的,所以我就回想了我原来是怎么学习的,原来我们的学习是这样来学的,就是我个人的学习,包括我们很多老师的学习过程怎么来学到。

总结了一下,我们叫它pp教学法,pp教学法的概念叫做project driven,项目驱动,parallel study,并行学习,好项目均衡病人学习什么概念,就是我我用一一个项目来驱动着。

这里面到底有多少,用到了多少个知识点啊,有些知识点你掌握住了,那就暂时先放一边,有些知识点没掌握住后,优先去学这些知识点,一边学项目,一边学知识点,一边学项目,一边学知识点,好。

这个学习方式呢目前现在证明了没问题,大多数的人在3~6个月左右的时候,ok每月至少涨5000好吗,我说的是至少至少涨5000哎,本来我是说我们原来那个去年培训的学生啊。

就是多数人每个人真的涨5000块钱,最少的,我们所有的案例都可以做背调的娘的,今天有一个学生就告诉我啊,我刚开始跟大家说了,说老师我工作了,我说涨了多少钱啊,涨了2000破了我们的金身。

结果后来我查了一下,今天入职了,薪资才多少,17k诶,原来原原原来挣多少,原来挣15k,原来这15k那个我说他涨了2000,太过分了,直接把我们牌子给砸了,后来查了一下牙是3月16号入的血。

系列 2:P9:马士兵老师JVM调优:9.为什么一个百万级TPS系统会频繁GC? - Java视频学堂 - BV1Hy4y1t7Bo

近期会加强我们自己的一个服务,就是关于大厂这块,我们会推出啊,慢慢的会退出保进大厂的服务,好吧呵呵。

这后面再说啊,课程内容是一样的,只不过增加特殊的服务而已啊,好嘞,你竟然比不过一只猫的年薪,因为这只猫叫tok,所以你比不过他很正常,好了不废话了,我今天来来讲一个非常重要的问题。

这个问题呢叫gc pc这件事呢,我我觉得因为每个同学听公开课的这些同学呢,他们的你们的技术水平呢他不太一样,你懂吧,呃就是有的人呢可能是小白层底。

嘿嘿有的人呢可能已经是大牛了,呃我再给大家讲这些课的时候呢,重点照顾的还是有基础稍差一些的,但是呢我也一定让这些个牛人能够得到你们想得到的东西,总而言之呢,大家不要屁股,你的脑袋,只要你水平高啊。

就就想催着老师给老师带节奏,带不动不用尝试了,好吧好了,这是19年到20年咱们遇到的关于gmtc的问题,一般来说只要你在简历里头写了,说我用过了解过jvm调优,了解过mysql调优。

了解过sql语句的优化,我告诉你你这个简历多值好几千块钱,大家呢也可以大概的看一下啊,在现在这些这些这些大厂来说,他问到这vm的时候,一般都会问哪些问题,给大家十几秒的时间吧,你先大概的过一遍。

我呢我会从最基本的讲给大家听好吧,从最基本的,然后呢我现在我们现在在推行一个什么样的学习方法呢,就是我希望大家伙能够轻轻松松的来学习一些知识,而不是说非得聚精会神呢,非得说一点儿事儿都不能走啊。

111点眼珠都不能转,你才学到很多知识,我觉得学东西呢也完全也可以做到非常轻松的来,我们的目标是针针针对针对啊这个方向来做出自己的努力,大家也可以听听看啊,今天晚上呢大家都放松放松了,听你不用太紧张。

我一定要让你有很大的收获,好吧,很好,一个都不会是吧,干货呢干货肯定没有啊,这里全是水货,哈哈我不做笔记了,不用不用做了,没关系,踏踏实实慢慢听啊,你就躺着听都可以,好呃为什么我要这么讲呢。

其实我我们在做了很多很多的这种教育之后呢,可以讲课之后啊,就慢慢的感觉到学习方式呢实际上是非常非常的重要,同样的学习方式,有的人呢可能需要六个月九个月才能把这些知识学完,但是如果你换一种学习方式的话。

有可能就需要两个月三个月呃,我个人创的记录大概是这样的,有一个小伙就会html css,我大概在十天送他就业,java后端,这是我个人创造记录,所以想速成的,有的是方法也重音了是吧。

好了不废话了,我们开始今天的内容,好吧呃不要吹牛逼了好吧,王雷吹牛逼一定要吹的,人生都不能吹牛逼,你的人生还有乐趣吗,不要给自己设限,因为你做这件事你肯定做不到,方老师,这不是个税,全靠忽悠。

你说的太tm的对了,全靠忽悠,一会儿我告诉你怎么玩好吧,王雷不着急,你想玩,我可以告诉你怎么玩儿,惰性,哈哈哈哈,你好好听我说啊,呃面对面试官的时候,就是你慢慢的好好的吹好自己的牛逼,你的面试就过了。

来看这里,今天呢我给大家来大家讲gc的知识,有很多人呢他可能是一个零小白,所以我们慢慢慢慢讲,呃,我大概呢从到底什么是个垃圾,怎么找着它,垃圾的回收算法,以及呢在jvm领域。

就是java这个领域呢到底有多少种垃圾回收器,我们明天的时间我给大家讲具体的调优,这里面呢最难的题呢是关于算法的,就是每种垃圾回收器具体的算法是什么,另外呢像go语言。

它的这种垃圾回收和java有什么不同,非常好玩,它和java是完全不一样,那个像rust语言诶,他为什么连个jc都没有,而且还不用自己管内存,我都会讲给大家听,慢慢来,我先把这个牛逼的头像给它拖出去。

大家看这里什么叫垃圾,这件事情比较简单,当有一个对象有引用指向它的时候,这里有个引用指向这个对象,这个对象就不是垃圾,说明有人用用到它,那好如果这个应用没有了,这个东西就是个垃圾,我们需要回收它。

这里面如果从c和c加加开始讲,就比较麻烦一些,但我觉得大多数人做java的人,应该都知道这种东西是一个垃圾,所以这块我就不展开了,c加加是手工的对吧,而java java是自动化的。

java就相当于什么呢,原来你在一个房间里面扔小线团玩啊,一个线团一线团连着一个线团,这些都是有用的对象,玩着玩着有些线头就断掉了,它会变成没用的,c和c加加,它的回收方式就是我要手工把它给戳起来。

扔到垃圾桶去,但是java的方式是专门有一个垃圾回收器,这个垃圾回收器呢可能是你就理解为有一个人啊,你跟你的男朋友跟你的女朋友,你们三个人在这里扔来扔去,扔小倩团玩。

然后你的爸爸爸妈妈进来帮你把垃圾收走好,你的爸爸妈妈就是那个垃圾回收器,你只管玩儿,只管造,只管申请空间,你不用管回收,好这个就叫做垃圾回收器,叫jc,叫garbage collector。

当然还有一种gb gc的全称呢,还有一种叫gdb collecting,教了呃,垃圾回收那个动作啊,这个无所谓,好大家看这里,咱们说你知道什么是一个垃圾之后。

就是没有任何引用指向它的这种这种对象叫一个垃圾,现在呢我们来看怎么定位这个垃圾,就是你要你要想回收这个垃圾,对不对,那是垃圾,你怎么怎么怎么怎么定位它呢,你怎么知道这就是个垃圾呢,最简单的方式。

我相信大家伙拿屁股都能想得到,就是一个对象,如果有一个引用指向他,你就给他脑袋上记个数就完了,脑门上写了个三,这哥们有仨女朋友,好,脑门上写一三,有一个给他跟他分了,剩二又有一个跟他分了。

又有一个跟他分了,最后剩零的时候,这哥们儿变成一个渣男,变成垃圾,终于终于认识到了他渣男的本质,而这个时候呢大家就可以回收它了,这是第一种找到一种垃圾的方式,但是这种方式有毛病,你知道为什么吗。

这种方式的问题,它不能够解决下面这种循环引用的问题,你比如说,a的女朋友是bb的,男朋友是cc的,女朋友是a好吧好,一堆垃圾,一堆渣男渣女,没有其他的任何正正直的人指向他们一堆垃圾。

但是从他们每一个人个体单独单独拿出来看,每一个人都有一个引用,所以呢你按照前面的定义,你就不能定义它它是垃圾,所以这种垃圾就回收不了,因此在这vm领域采用的垃圾定位的方式并不是这种,并不是这种。

这叫引用计数,脑门上记一个数字,刚进来,话说老师的口音好奇怪,what老师的口音,那那那奇怪了,老师这口音哪里奇怪了啊,啊沧桑了是吧,来开玩笑啊,来看这里对,what are you弄啥来嗯。

还是那句话,我希望大家放松了听放松了,挺放松了,学学知识呢是一个很有乐趣的过程啊,我不希望大家会觉得灰头土脸的,这就没意思了,那么jvm里面是怎么定位这个垃圾的呢,注意它定位的不是说正好是那个垃圾。

它定位的是那些不是垃圾的线线团,就是我刚才说了,不是你们仨吗,你男朋友你你男朋友,你女朋友在屋里头扔线团对吧,扔着扔着跟从你们手里这根线往下捋,你手里线牵了个线头,这个线头可能牵着另外一个线头。

这个线头可能牵着另外一个线头好,只要能顺着这根线捋下来的这些,你们三个人,无论谁从他手里头往下捋,捋下来的这些这些全都不是垃圾,只要找到这些不是垃圾的,那剩下就简单了,再循环一遍。

看看所有的剩剩余的全是垃圾,清掉搞定,所以这种能调整root searching就是从根上开始找,凡是能找到的都不是垃圾,凡是找不着的呢,ok全是垃圾,这叫gc的root。

就root searching,当然我们讲呃,大厂呢他有可能会问你到底哪些是root,我个人永远建议大家学东西叫做先学脉络,后学细节,你今天听到这句话,以前不是这么学的,你按照老师的学,你放心。

你的学习效率十倍百倍的提升,叫先学脉络,后旋细节查漏补缺,找细节,先把脉络给掌握住,你去庐山,你不能够说先到庐山某一棵树底下研究某个蚂蚁窝,这样的话你脑子里建立不了整个庐山的概念,有一些碎片化的学习。

为什么它效率偏低,原因就是它建立不了整个知识体系的结构,我建议大家永远是坐着直升飞机,先把整个的脉络了解清楚再去了解哦,原来到底什么是gc root呢,甚至你放一边,别着急,等你明天的面试的时候。

今天看一遍,背过搞定,啊能够理解这一点,觉得有认可的,给老师扣个一,我们继续,所以今天我不太想跟你解释到底哪些是rts啊,哪些是歌歌对象,因为这里面牵涉到很多概念。

比如jm deck native methods stg以及run time constant pool,以及static references method area和class,嗯。

这些都是来源于java,最经典的书就是jav群里记,最经典的书是那本书,不知道大家了不了解,既然刚才有同学推荐书,说老师你推荐本书吗,推荐你一本java虚拟机,最经典的一本书叫java虚拟机规范。

就这本啊给大家打开来看看,如果你真想研究,朝这方向去研究,这书老师都是读过的啊,放心,我给你找一下啊,嗯嗯,算了你这样你去下载就行了,在oracle的网站上自己下这本书的全称叫jell verge。

machine,specification,ok java虚拟机规范应该最新的是第14个版本,所以你想了解最新的jav虚拟机,除了这些书非他莫属,别的都是抄来抄去好大家看这里嗯,刚才我们讲了两个问题。

就是第一个呢到底什么是什么样的东西,是个垃圾,没有引用指向它,ok这是个垃圾,第二个是什么,第二个是怎么定位一个垃圾,两种方式,第一种呢叫reference count,这种方式呢有毛病。

他解决不了循环引用的问题,第二种方式叫什么,第二种方式叫rt thirty,根可达算法,从根上开始找找着谁都不是垃圾,找不着的,全是垃圾,jvm使用的第二种,但是当回收这个垃圾的时候。

注意一共有三种算法,这三种算法呢比较简单,也很容易理解,你背过就完了,从上个世纪50年代发明垃圾回收器开始到现在,就这三种,没有其他565 60年代70年了吧,快70年了。

快70年来没有别的新的算法的发明,就这三种,这三种第一种呢叫mark sweep,记英文,希望你记英文,第二种呢叫copy,第三种呢叫mark compact,mark sweep叫标记清除,超级简单。

一说就明白好,这哥们儿是垃圾怎么办,把他们找出来,把他们清掉,就这么简单,青橙绿颜色的,大家都都可以用了,标记清楚有它的问题,因为你标多了,轻多了就变成一个洞,一个洞的,我把这也标了,把这也标了。

把这也标了吧,这也清了,旁边都是有用的,就变成碎片化,这个是碎片化标记清除的毛病,碎片化,但它算法非常简单好,这是第一种呃,这里面的每一个更详细的一些算法,我就不想先不详细给你讲,还是那句话啊。

先学脉络,第二种叫拷贝,拷贝算法的理解也超级简单,就是我不管你内存多大,咔咔叽一下分成两半,分成两半,只用其中一半,那用完我我想进行垃圾回收的时候,怎么做呢。

我只要把其中一半有用的那些对象copy到另外一半去,然后对上面这块整体性的进行清除,就相当于你们家一个大的房间,你跟你男朋友女朋友只能在这这边儿玩儿,当我进行垃圾回收的时候,我怎么做呢。

你们所有的人趁着线团跑这边来,剩下那些在原地的这些线头,我二话不说,把整个的全清除掉,这个叫拷贝算法,是不是很容易理解,没有那么难,拷贝算法,他的毛病一目了然,那大腿想想也应该知道浪费空间。

还有第三种叫什么,第三种叫不浪费空间,而且也没有碎片,就是那还不简单,当我们找到这些有有有有有垃圾的时候,诶,我我顺带着给它做个整理,你整理过硬盘的那种碎片吧,把那些有用的呢全往前堆堆到一起去。

把那些个没用到的空间全放到后面去,就是一边做标记,一边做整理,当然这种呢就是效率比较低,这种叫mark compact,所以就这三种叫mark sweep,copy和mark compact。

好各位听我说,我觉得这三种算法呢到现在为止我讲速度比较快,应该是都能跟上的对吧,来能跟上同学老师扣个一,跟不上的,给老师扣7563,开根号再开根号,good不错啊,大家伙都不错,好下面我来讲,嘿嘿嘿。

下面我来讲讲什么呢,就是讲到底这些个算法是怎么进行运用的,那么jvm的到底是怎么管理它自己的内存的,呃为什么要有分带模型,没有分类的模型,就我说啊,所有的垃圾回收器就是爸爸妈妈帮你做垃圾回收的这些人啊。

你的保姆你在里边随便让他来帮你做回收,这些人是怎么样子运用这些算法的,听我说,他们会对这些算法进行各种各样的灵活运用以及综合性运用,呃所以每个人和每个人呢他用的算法都不一样,他的工作效率也不一样。

他各方面关注度也不一样,每种不同的垃圾回收器都是有它不同的算法,大家记住,以前有面试官会问说你们你你了解jvm的这个内内存的管理模型吗,仔细听我说,jvm内存管理模型,如果你想回答完善了。

一定反问面试官,各位小伙伴们记住了题,不会答的时候就反问他。

系列 3:P1:互联网P8架构师的工作内容与能力重点是什么? - 马士兵_马小雨 - BV1zh411H79h

什么是P8嗯,大多数做传统行业软件的小伙伴呢,他是比较熟悉这种传统的CD的,这样的一个软件的结构,但是很多人其实并不熟悉项目,互联网相关的这些软件的架构,它到底是怎么搭建的呃。

我们的G8课程呢主要就是集中在互联网,三高这样的软件的结结构,从一个高层上它是怎么设计以及落地的啊,这个落地呢也非常的重要,我们是专门搭建了自己的几十台的服务器,花费上百万给大家模拟一个最真实的环境。

然后用一行一行的代码来教大家,怎么样有一个项目把这个互联网三高,也就是说唉高可用高扩展嗯,还有呢就是高性能,互联网三高的这样的一个软件结构啊,一行一行代码用在真实的环境上,怎么让他给落落地。

这是我们的P8课程,为什么要设计P8架构师课程,呃我们当时考虑这个是P8,这个架构师的课程呢,呃主要是看到市面上从来没有一套,能够把P8的这种理论,把架构师的人类理论完完整整带给大家。

一行一行代码来落地的这么一套课程啊,实际上是没有这个东西,在这个方面呢我们是绝对的原创呃,也没有人肯花一个很大的成本啊,这个几十台的真正的服务器,在线上来模拟一个云的云环境啊,把这个东西呢搭建出来。

所以呃我们就讲的就是任何一个理论,你讲出花来,如果不能让它落地的话,因此在这儿呢我们除了P8的这种,就是架构师的理论课之外,大概有十几篇的理论课啊,涉及到分布式的方方面面。

唉在这个之外我们又搭建了真实的环境,让他们有这种落地的这样的一个呃学习机会啊,这个很多人呢做传统的行业里,实在是接触不到的好,呃,在这儿呢通过一个完整的课程,让你来了解一个互联网的流量特别高的啊。

这样的一个项目,它怎么样用好多台,几十台,上百台的服务器来搭建起来这样一个环境,并且代码还有分门锁呀,分布事务啊等等这些方面是怎么落地开发的哦,就是这个东西呢对我们很多的呃。

做传统行业的小伙伴呢非常有纪念意义,所以这样我们就设计了我们的批判教程师课程,学了P8课程的程序员能获得哪些能力,有什么好处,学习了P8课程之后,大多数的成员不管你是什么样的语言。

你都会有这种加工性的思维和开始,可能呢在咱们每个程序员来说,你的开发的语言的方方面面,java c加加的做gold,做点net做PH等等,但是每种语言如果你学到一定的程度之后,没有这种架构性的思维。

软件结构高层的这种思维的话,那么你的向上的空间是打开的,所以P8的课程,就是为了给大家这么一种加厚的感觉,呃虽然说我们整体的落地呢是以java为主,但是呢站在一个比较高级的架构师角度来看。

其实语言并不能够不可以限制你的个人发展啊,就像你造一所房子对吧,你的这个柱子绑成水泥,那更合适啊,两门的话那就得用用用用用木头可能更合适,所以说合适的比放在合适的地方,这是一个比较牛啊。

非常牛叉的这样的一个架构师,应该啊所考虑的这么一种一致一种思维,所以呢不要让不要让语言,局限于你自己的架构性思维的发展,希望大家伙呢也能够,每个人到达一定的天花板之后,考虑往架构的方向往上走一步。

你能够把握整体软件结构的时候,你的向上的空间就打开了,程序员以后的职业发展和瓶颈,大多数成员呢到一定的年龄之后,我会感觉到自己的一点压迫感,一些中年危机存在,但是P8的这种架构师能让你消除这种危机感。

呃,一个在市面上来说,你的技术能够达到架构师这层级,并且管理水平再跟上来的话,在所谓的35岁啊,所谓的40岁,也可能就是你新的职业生命的开始呃,在这方面呢,我们有过很多的那种传统软件行业啊。

他有的是甲方公司,比如说他专业不是做IP的,他也需要有很多这种有互联网的方面经验的,有这种高并发大数据量处理经验的,这样的一些架构师,给的薪水也非常非常高啊,白药基本都是百万以上这样一个薪水。

所以你能够做到这一点的时候,就说技术上能够有架构师思维,同时和人类沟通啊,然后再加上部分的管理,这样的几条腿开车一块走路的时候,你的新的成长空间就打开了,当然按钮是温水煮青蛙,然后只是天天cr it。

就是天天crud10年,也就是个熟练工种而已,所以希望大家伙能够放弃这种温水煮青蛙的,得过且过的这种佛系思想,给自己一点点压力,让自己在这软件这条路上越走越宽,提升你自己,就在今天。

下周我们项目如何落地。

谈到我们的落地的项目呢,我们也是选了一个大家伙喜闻乐见的,就是再造淘宝这样一个项目呃,为什么这么选他呢,是因为呢淘宝这个项目综合了很多很多,现在在互联网领域里头,就是特别受欢迎的那种技术。

比方说它的并发量都非常高,他在双11的时候,他在那个过节的时候,他在秒杀的时候,它的并发量会非常高,比方说呢它的数据量会非常大,比如说他会牵扯到推荐系统,这种初步的人工智能。

比方说他会牵扯到智能聊天的机器人啊,这种智能客服等等,比方说他会牵扯到各种各样的分布式锁,分布式事务等等,就是关于分布式的方方面面,这样的一个呃项目来讲的,就是大家伙很明白它的业务逻辑。

这样就能很快的把这个关注点的,关注在哪个技术上,那么在这个时候呢,嗯你如果能把我们的整体的这种赛道,赛道淘宝的项目跟下来的话,那么你就是一个淘宝级别的项目,是你可以想象一下你的价值观课程太长。

如何选择课程。

呃我们这个架构师的课程,他的课程非常长,长达1500个小时左右啊,为什么这么长,其实你要了解这一点,就是呃从你参加工作开始,到成长一名P班级别的这样小老师,需要长达五到10年才能造成到达这种水平。

所以我们在授课的这个方面上呢,我们是考虑到嗯更有水平的人,就是哪怕你水平差一些,我可以带你从头慢慢的走到这个级别,所以这个课程呢肯定是要做的比较长,如果不能够做特别长的话。

你相应的这种技术点我也讲的很深,所以这个呢课程的长度是必须的啊,当然呃,课程长度呢,不是说就是代表了我们课程会非常贵啊,我们在缩减了各种各样的有线下的成本之后呢,其实我们课程的性价比是非常高。

只有课程比较长的时候,然后才能够做到你的课程非常的深,我相信大家都能理解这一点,但这个时候呢会有有有同学会有些问题说,呃老师啊,我有一些其中的一些课程的基础,我已经有了。

那么这个时候我来跟这个课程应该怎么来跟呢,针对我们现在这种课程的设计,我们给出来的是定制化的学习,所谓定制化的学习,就是能够根据你现有的这种水平,然后以及你短期的长期的诉求,由老师来给帮助你。

给出一份这样的学习路线,比如说先学ACDE,然后达到你短期诉求,用剩下的时间里慢慢的整体性的提升啊,那么你水平稍微差一些,我先给你一个初级的版本,以前慢慢成长到一个哎,稍微那个那个弱一点的水平。

在达到你这个涨完薪水之后,你可以慢慢的再用其他的时间来,把自己的整体水平再升上来啊,我觉得这是一个非常不错的,比较友好的这样的一个学习氛围和设计,也是我们的特点,在这个哈我也是我们的首套。

希望大家喜欢我们教研团队。

讲师团队优势,我们呢有非常牛的这种教学团队,呃,像来自于阿里,来自于美团的,那么以及嗯嗯比较有名的算法的老师啊,还有呢北大的读书后,我们两位清华的老师。

dit go的老师在这全都有,然后除了这个之外呢,因为我以前有很多学生呢,他们在大厂已经呆了很长时间了,但是呢他们水平虽然很高,讲课可能未必适合,但没有关系,他是我们的,他们会是我们的教研团队。

那么教研团队呢,会给我们提供各种各样的解决方案,以及呃这个呃课程上的各种各样的这种课件呀,呃这个答疑啊,呃咨询啊等等这方面的图,所以我是相信这一点,就是在一线,尤其是在一线大厂有过实战经验的。

这样的老师才能带出比较牛的学生来,嗯其实效果呢我估计大家伙也都会慢慢看到,我们现在有很多很多的学生,都已经通过这样的一个学习方式进到了大厂呃,这是第一点,而且呢我们现在的教育水平。

也得到了各路大厂的认可,像以前的有很多学员出去说,很忌讳的说我是培训出来的,但是在这儿呢告诉你,有嗯N多的大厂的人找我们做内推啊,这个呃百度的,阿里的,腾讯的,京东的这个我们都全部都有自己的那堆渠道。

拼多多啊,头条全都有啊,甚至头条呢会有专门的人,就是专门给我们做的定制化的内推呃,为什么,是因为认可我们的角色质量,现在呢你在这学习的话,其实完全没有必要忌讳说我是参加过培训的。

那么你在这儿参加过培训的话,在大厂会受到欢迎。

我们都有哪些特色售后服务。

我们现在也形成了自己的非常有特色的服务,比如说一对一的简历指导,一对一的职业规划,有很多很多一线的老师,包括在就是在这个行业中待过很多年的,讲的前辈,来帮你规划你以后的学习路线,升迁路线。

职业发展的路线,这是非常有价值的一件事情,除此之外呢,我们还有自己的内推服务,以及合作的猎头公司,来帮大家寻觅更好的发展机会,另外你在你的整个的工作期间,如果遇到了各种各样特别难以解决的问题。

在这儿还能提供给你技术咨询的服务。

第一点开了可以吧,嗯呃搜索,然后存储,然后分布式锁事务,分布式的配置可以更新吗,注册与发现网关路由浮雕,用负载均衡断路器分布消息链路追踪,预警监控啊,以及其他的一些常见的问题,呃我讲到这儿啊。

我不知道大家伙有多少人能有把握,说我能到P6的,有能到P6的小伙伴,你举个手扣个一说,我非常有把握,这些东西我掌握了嗯,mp5这要求我们公司怕是一个月招不会的,不会的啊,P5都够呛,没关系啊。

就我相信人这一辈子不可能,这哥们天生下来他就是P5或者P6,不可能都是从头开始学习的,和练习的没有关系啊,感觉掌握了不错啊,感觉掌握了你就有批流水平,P6水平的话呢,在哪里来讲的。

他现在应该是年薪在40万到60万之间嗯,应该很少比这个少,也很少有比这个高,我记得是还有一个VIP,他是个特例,他去了阿里的哪大厂,年薪90P6P6P6呃,我给你看过那个例子,就在那接着喜报上是吗。

嗯哎哪哪哪和顺丰科技,他都拿到了将近100万的年薪,P6水平,为什么这也比较特殊啊,当然像这种特例呢,你也不要太在意,你还信90,你搜90应该能搜到是吗,九十九十六一个就是进腾讯的那个呃。

那你搜一下百万百万百万,咳咳咳是这个吗,虾皮不是,这个是什么,这个盲盒是不是不是这个,现在九十百万不是这个美团唉,这个是这个吧,这个嗯,这个你来说吧,我我我我对这小这小伙还真不是特别熟,P6加薪水。

年终股票大概80,这是P6加的,这是阿里的哪咤大的诶,我一会专门跟大家说说,这个P6加这个加号是怎么回事,就是为什么还有P6加这件事,你们想听吗,嗯那咋的对,呃,怎么说呢。

我给你稍微讲讲这个加号是怎么回事啊,这里面其实就涉及到了你的晋升的路线了啊,我们想到哪就讲到哪儿了,那个你说我我想问你啊,假如说你进了一个大厂的体系,我们假设假设你进到阿里,你现在定的是P5好。

我现在想问你呃,你作为屁股来讲,你应该怎么样才能够升到P6呢,它的流程是什么样子的呢,好卡好卡嗯,这三家已经定薪酬嗯,客户端不卡对,好你们,你们好好想啊,KPI我看到有小伙伴说了啊,说是KPI。

我把咱们聊天窗口拖进来吧,盖着咱们一点没关系,可以看看大家的聊天呃,能力积攒加上人脉嗯,其实你说的都挺对的,都挺对的,就是你怎么才能升到P6呢,它实际上在阿里内部应该是一个比较科,比较完整。

现在应该是一个比较完整的流程,就是一般用适应你的领导开始提是吧,哎我我我手底下如果有十个屁股啊,我今年想提三个人,想让他升P6,那么他就提上去,提上去之后呢,下一步应该是要做一个出了审查了。

对答辩答辩要答辩评审,答辩答辩评审,然后呢,最后还需要沟通,如果有意见的话,我记得原来阿里内部还可以公开的投诉,还能投诉,对他是一个特别完整的体系,那么在这个里面呢,它就会涉及到一些怎么去评判。

你这个人能够达到了下一级水平,我告诉大家,你们说的什么人脉啊,什么KPI啊,你们说的都特别对,他一定会有这方面的指标,你比如说最简单的就是说嗯你你的绩效什么样,我说绩效这俩字大家都都能理解吧。

绩效这俩字,绩效就是说呃,同样的这个同样的这个这个这个完成完成度,那么有的人完成的特别漂亮,他机会就会好,有的人完成的不好的绩效就会低,一般来讲,这个绩效工资在你的工资水平里头,都会占一部分。

嗯嗯那么绩效就是绩效要好,对不对,呃,完成度要好啊,然后呢你具体教给你什么东西都都能完成了,那么像这些东西是不是就定了呢,其实不是,一般来讲呢你这个人能进到下一集,就是你要第一你要具备下一级要求的水平。

你如果要下载的水平,你到不了的话,那肯定是不行的,那我就想问你了,你怎么样才能你在P5里面,就大家伙100个P5现在都想升P6,指标只有30个,你怎么才能做到,你就是升上去。

那个你们想想塞包颜色不排除有这种可能性,你要个漂亮的女生现身,没准也有可能性,但是你要靠这个上去,我相信你也待不住啊,我告诉你,你仔细听,我就跟你说一句话就行了,提前做P6的事,能不能听懂。

我现在是P5,但是我对我自己的要求都是按P6来的,明白了吧,是不是老师一句话就给你就给你搞定了,来能get到的,给老师扣个一,啊马老师一语中地对,记住很简单,提前做漂流的事儿,就是你现在薪资20万来。

多承担30万以上的事儿,你相信我,你一定有一天啊,或者你起码得干,你升上去的概率要比别人大得多,所以我现在跟你说,叫P6plus,你现在是不是能大概能理解了P6plus,这哥们儿是P6水平。

但是他能担任P7的一部分的事,听懂了吗,这个就叫P6plus,原来原来阿里内部有一句话,先做上一级别的事,再做上一级别的人啊,对啊,这个就是这个意思没错,你比如说说一个最简单的。

我们说P6升P7的时候啊,P6升P7怎么升呢,P7要求的是带一个小团队的,这要求的是带一个小小的团队,这个团队的可能不太多,初级的P735个人哎,你就是那最核心那个你就是那个P7了。

那你如果P你在做P6的时候,已经有这样的经验了,那你说P7的可能性是不是高很多,听不听懂了吗,就是这个东西呢,当然我说技术是硬指标啊,你说你技术上必须得到位,那个很正常的,就是除了技术之外啊。

当然还有还有很多很多的技巧和东西,我们都是有迹可循的,这个这个不急,我们我们我们讲到哪了,刚才刚才讲的这玩意,之前我们聊点讲的那个职级的薪资,职级各职级要求的要求,C,大家可以看啊。

嗯就是有把握能够做得到的,那挺好的好吧,你要想P6P7升的时候,来先把P7的这些东西呢给搞定了啊,就是呃我记得曾经啊,曾经以前就是拿那个技巧和调优来说,我们说P7里面的这个要求,那么对于P6来说。

我记得曾经以前有一张表格,他会列特别细,这是啊啊这是阿里很早以前的表格了,是我以前很老学生学生发我的很早以前的标杆,它它会它会把一个东西呢列特别细,他说你如果你是P6,那么对于JVM这样的技术点。

你应该掌握到什么程度,这个大家能不能理解,对于存储这样的技术点,存储里面的MYSQL应该掌握到什么程度,存储里面的REDIS应该掌握到什么程度,存储里面的大数据相关的,应该掌握到什么程度好。

同样的还是这些东西对于JVM,对于存储的东西P7应该又掌握到什么程度,这画图图画有点不好看,换一个刚才那个那个那个PPT,在这里啊,我简单给大家伙列一下,他这个要求呢是很早很早以前的一个要求。

就也也也挺挺细致的,哎这是一个P6,这是一个P7,那么对于PP6,对于JVM的要求是什么,对于多线程的要求是什么,比如他熟悉能应用好了,这就P6的要求,一般来说是这样的,熟悉啊,能能能应用能调。

好像是存储啊,你这个MYSQL熟悉也能用,能分库分表,那么到PC的要求往往就是精通,精通的概念是什么呢,知道原理出了bug之后,知道怎么样进行深度的调试,P6对于NT来说。

它的应用很可能是哦我我能熟练熟练运用,没有问题,到了P7很可能是你必须得知道原理,所以P7和P6第一个的区别,在以前的这个标准里面,叫做你要懂得更深的原理,不知道我说清楚没有,这就是我为什么啊,我们。

有一门课程叫做嗯spring的源码,我把它叫做P7的课程,很多人理解不了,说老师那个你讲的spring源码怎么就到P7水平了,呃这么大家说,这是调优不那啥了嗯,视频源码课就是嗯拿spring源码。

源码源码课程来讲的,就是为什么说spring源码,就到了一个什么P7水平了,原因是什么,主要是把spring源码讲的什么深度视频上讲的,这种源码的特别多,我们源码也很简单,我们大概讲了80个小时左右。

注意就这一门课啊,大概讲了80个小时左右,为什么,因为我想让你就靠这一门课,就直接给面试官留下一个P7的印象,因为这门课可以让可以把spring做到定制化开发,就是你拿过spring了。

你改的源码编译好了之后,是一个你自己定制的spring,能理解的意思吧,好了到这种程度,你如果正好被问到了,你答的不错,那么在你面试官的眼里,你就是P7水平,这是技术水平啊,不知道说清楚没有。

能get到这一点,同学老师扣个一,当然我讲的这儿呢,也顺带着给我们,给我们黄老师呢做一个小小小的广告,呃,黄老师最近讲的另外一个,一个特别牛逼的源码呢,叫做同K源码,好像最近刚刚刚跟上来啊。

诶到底是哪个呀,也是大概有一个很长很细的一个内容了,顺带着做点小小的广告,就是老师这个课呢就是同样的课程,源码分析和架构思维,同样的课程我们会讲的比外面深入的多啊,也许你看到别人的大纲特别浅的时候。

说我也有这个,我也有那个,但是我直接告诉你,这是深入的多得多,一个课很可能就让你怼到P7了,当然靠运气,有一定的运气啊,你得把那个P你要想特别完善的那个P7,就把P7的要求全部拿下来就行了。

我们回到刚才那张那个图啊,大家看到呢,现在这里是大3W2,我原因是什么呢,因为新版的这个直接的体系和标准,我们也也也跟随着大厂的东西呢,进行重讲的更新啊,痛点怎么规避啊,祖父悖论等等。

完全穿透各种言语啊,还有一个全局意识啊,百万设计师就是在我们课程里头,有一个叫做架构设计的课,就是没有没有这架构设计,我直接告诉你呃,你可能到不了年薪百万的,那这个呢也简单也简单介绍。

就刚才90万年学习那个你腾讯这哥们儿,他呢你看到他那个腾讯的面试题,你就知道了,就就就这就这个面试题,呃你可以拿过来做设计做练习,你把这玩意儿练好了之后呢,你基本上就是腾讯的那种。

九十九九十万年薪左右的水平啊,嗯当然这个东西不是很容易呃,它的难点在于,你要深刻的考虑互联网的三高思维啊,原来讲三高现在快进行到四高了,三高思维高可用高扩展,还有高性能,你要深深的考虑好。

在三高思维的指导之下,像这样的东西我们应该优先考虑哪一高啊,你可以思考一下好吧,当然我们现在呢也在正在直播的是一个三高课,我记得是吧,嗯对在那个不it,全面封就是抽奖对能搜出来三个在同一课程上。

嗯正在直播的是一三高课,也给大家伙儿调来看看吧,就是我们现在呢呃,现在正在直播的是一个互联网,微服务的分布式的三个落地的其他项目课,呃这课呢是那个所有的知识点的一个综合运用,那么在这个课程里面呃。

从嗯基本简单的开始吧,到我们呃,我们特特别邀请了阿里的P8的老师,来给大家分享一下十多年的电商发展史,就是以电商来举例子啊,我们最终的呢把这个三高的一个一个课程呢,来进行落地。

后面的都是一些落地的方案了,呃这个课呢目前正在直播,然后在你当然你要学习这个课,我真心建议你先把什么呢,先把我们课程里面的关于这些课程的,那些支撑的技术点先搞定,那么你跟这个课就叫做事半功倍好了。

实在的介绍了点我们课程啊,我们继续来聊这个,就是你先把你先把这些东西啊,先把这些全部都搞定之后,再来跟这个三高课事半功倍,你很可能靠这一个项目就达到P7水平了啊,我们说到这儿,这是P6的40万到60万。

这是P7的,我们聊聊聊一下简单的薪水啊,P7的话,那就是50万到70万,800~1000 250,1250,这个好像是最新的数据吧,这好像是最新的数据啊,这就是P7的一个大概的水平呃。

但是呢其实有好多人最后最终定位的是P7,他的年薪呢是过百万的,这个这个原因是什么呀,就是P7plus就是快到P8了,这样我们从头呢我们简单说一说,就是你怎么到P5,怎么到P6,怎么到P7,好吧。

三高课程学完主要解决什么问题,现成的像京东阿里呃这一这一类的大规模的,能够接受大规模的大病发量的,这样的网站到底是怎么设计的,就是干这个事的呃,让你的薪资超过50万,干这个事好吧,哦我看有人问课程。

我简单稍微回答一下VIP多少钱嗯,去找一下咱们小姐姐问问,因为今晚上应该是有活动的,学完这些呢,如果每天安排两小时,正常来说大概需要多久呃,建议是周一到周五两个小时,周末你是要翻倍的呃。

如果你看你的基础啊,如果你是零基础,从P5开始学,我估计你全部学完要一年呃,但是呢老师这边的教学方式比较特殊的呃,我们是一种定制化的学习方式,所以你会看到有什么呢,有那种特别时间特别短。

我就搞我我就搞定的啊,有时候这是我们帮他设计的一条路线,叫6+2,这以前很早的路线了,只只看了自己感兴趣的部分就涨了,涨了新了啊,好了好了,我们先不做这些个广广告什么的,你像这个的话。

那就是两两个月就涨了50%,就是说你你寻求如果全学完,我告诉你一年左右时间,如果你寻求你说以目标驱动,说我目标我就是想涨个薪水,那就那就简单了,所以就看你想干什么,取决于你要花多长时间听懂,听懂了吗。

VIP跟MC什么区别和关系,那个VIP就是VIP学习的课程,叫做MCA他俩是一回事啊,哦我们还还继续说这个直接这件事啊,一会儿如果大家有兴趣的呃,你想说我想达到什么级别,想跟老师聊一聊的都可以啊。

我跟我跟曹老师都在这,超老师也指导的学生,指导挺多的,我觉得曹老师最牛皮的是一个高中生,是给弄进阿里去了是吧,我觉得你你别就这种事还是少宣传,以免有很多高中生真的想过来全头发里去,因为今天就有。

我们不是有大厂必进班嘛,然后有一订单已经满了,今天今天就不说这个大厂,毕竟嗯嗯好像已经满员了,不也没过也没关系啊,就是说如果,就是那个那个高中生,你说说看他他是怎么能进到阿里的。

我说到这儿说点学习上的事啊,就是说你你知道有很多的大厂啊,大厂这件事儿呃是特别在乎学历的,你说你高中肯定没戏的,我告诉你有哪些大厂,你要是高中肯定没戏,其中一个呢下载华为啊,另外一个呢叫腾讯。

还有一个叫百度,还有一个快手,还有其实还有挺多的嗯,其实还有挺多的就是特别特别看重学历的,这些个会特别多,然后呢那个还有一部分相对没有看到,那么那么那么那么大学历的啊,其中有一个呢就叫阿里。

阿里为什么不看重学历啊,原因是啥,你阿里为什么不看重学历,因为老板学历不高是吧,对对对,因为马云大专毕业,马云大专毕业啊,然后原来他最开始的时候,那个18罗汉好像很大一部分人,学历都都都比较差。

我记得呃安马云的讲法是原像那个18罗汉说,我要按照现在的标准啊,我们阿里的标准来招人的话,你们一个都进不来哈哈,他学历并不能说明一个人的能力差,他只是在你面试课程的大大厂会偷懒呃,我学习好的。

我已经够挑了,我就干脆不费劲去从那个学历差里面挑人了,他这么他是这么个逻辑,但是阿里呢他不太在乎,还有一个不太在乎的,那叫京东,京东着急的时候,什么大专呀,这个这个全要啊,嗯我一会儿告诉你。

一年里头最好进的时间是在哪儿啊,就是什么时候他会着急呃,前些日子,因为我们现在跟京东合作合作比较紧密,我记得前些日子就京东嗷嗷嗷叫的找咱们,要人就找我们要人就要到曹老师,这京东数科。

京东数科的京东入口发过来的岗位80多个,全是集中,没一个不着急的好,这种时候大专生是最好进去的时候,嗯嗯但是我们VIP好像比较那啥,当时那个京东还没有涨涨薪资好多看不上,好多看不上京东薪资。

现在应该京东涨起来了,基本16星了吧,涨涨了一个,涨了一个月的薪水,我记得是,还有一个不太在乎的呢,滴滴稍微的那什么点,但这个比较特殊,它这个分项目组啊,你像我们大厂班里有一个带高浪的老师。

就是高浪专门带人进大厂的啊,我们的高原老师他呢是滴滴的,他说呢像在学历这块呢,在滴滴来讲的是主要是分项目组,项目组不要着急,也不也不在乎啊,当然还有一些像顺丰,还有一些二线的厂子,像什么五八呀。

那个就这这一类的2223线的厂子,他们也会不太在乎学历啊,行,那高中高中生是怎么弄进去的,我当时也比较好奇,我都忘了忘了忘了问题,首先第一点是进技术足够强,因为大厂他招人去了,毕竟是要出活的对。

第一是技术足够强,第二是在外面干到一定的title,就是可能一些小公司,你就是小公司,他最开始招人不挑,然后你进去了,然后在里面的技术也非常好,管理也非常好,然后可能你干到一个架构师或者。

技术总监的岗位,然后你再去面试大厂,那么就是你原来的职位或者你原来的薪水,已经能证明你的能力了,就不需要学历去证明了,这个时候也是特别容易进去的,我不知道大厂听,我不知道大家伙听清楚没有。

这里面就包含了大专生,怎么样才能进入到大厂,我在前面讲大专生的时候呢,我就强调过一句话,我说你作为一个大专生的在校生来讲,如果想规划好好自己进大厂的路,你的前三连一定要走好,大厂最喜欢要的年龄三到5年。

这是最喜欢最喜欢要的,你的前3年一定要走好,你前三项一定要走好,怎么走,在座有大专生吗,在校的比较年轻的,工作没满3年的,有没有那个郑大建是吧,郑大建还在吗,郑大郑大建是今天刚报名的哦。

嗯两年是ok good,研究生研究生相对进大厂要好好进的多啊,我们就就是把握性要要高得多呃,吴大伙这是OK嗯,大兴庞各庄毕业是吧,小岳岳好呃,我我给我给大家伙那个现在你在校的大专生,还有一个啊。

呃你现在工作没有满3年的大专生,我给你指条路,沿着这条路走,你是有很有一定的概率进到大厂,这条路怎么走,如果从驾校来说,你的第一次就业就是你毕业的时候,那次就业你首先第一得进得了行业。

尤其像我了解很多的大专,如果在没经过培训,不管是线上还是线下,你其实很难进到行业里去的,所以第一件事要进到行业好,进到这个行业的时候,你尽量的要多拿一些offer来挑了,这是你的技术水平了。

但是这个时候最不应该看重的叫薪水,就说我挣个五千八千,跟我挣个1万21万3,不要太看重那个几千块钱那点区别,人这一辈子不可能靠第一份薪水你就致富的,没有这种可能性,你就不用想了,你随便找案例行。

我第一份薪水我就靠它来支付,扯淡不可能,所以你的第一份主要看什么,看你看重你将来的发展,这个发展主要看什么,如果说这个企业能它有很很好的一个空间,能够让你在里头待够3年,这是最最完美的企业。

同时它一定要有长对应的涨薪机制,就是你在三尖头上想进大厂,那会儿最理想的情况,刚才曹老师说了,你有一个固定特别好的一个薪水,证明你的能力,或者你有一个特别好的title,证明你的能力。

所以你要在刚进去的时候,如果有一个厂子说容忍,你能够在3年之内成长到一个比较好的水平,那太好了,Very good,但是大多数的厂子实际上不具备这种水平,尤其是你们刚毕业的时候。

很可能就拿到多少8000块啊,1万块,1万2,这种薪水你就不要想了,进不了大厂,大厂一看你这薪水,第一个第一个反应就是啥水平,一定是这样的,这样的,你一看你薪水就证明你能力不行。

所以一般来讲大多数的人要走一年,在第一年的时候,你给我好好学习,好好攒经验,项目经验,技术经验,按按照我要求的这个能力,你和我好好攒,攒完之后,在你一年毕完业一年的时候,跳第二家要注重薪水。

这个时候就要注重薪水了,不知道说清楚没有,我再说一遍,一年的时候,最开始薪水可以不太好,一年头上结束,跳第二家的时候,一定要注重薪水,薪水将前途并重,就是你这第二家的选择。

一定是建立在你第一年好好学习的基础之上,你的选择那会特别特别宽,然后呢,当你有了这个选择之后,你在第二家选择的时候选什么,必须注重薪水,建议2万以上,必须注重前途,这个前途指的是什么呢。

就是你要考虑到你在这里要做,做足两年之后的下一步大厂的上升空间,考虑这件事儿,然后呢呃理想的情况在你两年毕业的时候,你这个时候的薪水呢应该在2万到2万5,甚至到3万,这时候进大厂,你的大厂的概率。

怎么着也能提升到60%到80,我就真认为是没事,没问题的,就是你就是打转手,那么最在理想的一个情况,在你这个期间还拿了一个学历嗯,概率高多了,在座的大专生不知道我说清楚没有。

如果工作的1~3连是拼多多的前三连。

那就那就不用进大厂,对对对,我们看你看看哪个大专那里,我觉得老师原来有一个呃,这个是有这个大专生不幸错过案例,入职申通,申通其实也还可以,你说二线厂的肯定没问题,他当年他这个时候是初中的时候。

主要是主要是正面那个申通的时候啊,那个阿离给打了,打了几个电话,打了八个电话,打个电话一个都没接着,正正在面试申通的第四面,第三面忘了啊,第四离第四面啊,这属于比较倒霉,但是他水平一定是到了。

不然阿里不会给他第三遍第四遍的机会,那个我记得原来超老师手底下有一个学生,他是大专,刚刚应届生,是拿了21K我没事,我没记错吧,是在广州,广州是一在it行业来说都不算一线了,其实嗯就搜我搜不着了。

那这个你看这个小伙是大专学历,受到多家大厂的offer,他当时给的那个跟这个描述啊,你仔细读是肺腑之言,他说明哥非常感谢帮忙批改简历,这是我们服务之一,也感谢我们教育的课程指导。

学的接触了接触不到的东西,安卓老师的说法就是认知偏差,我之前的简历呢很少有面试邀请,现在基本每天可以排满,经过三周面试,已经收到不少offer,后期会记得学习啊,他说真是讲的大专学历的。

我也不再只是那些中小型公司喊我去面试,就你最差最差,你认真的学习和准备之后,就算你是大专学历。

你没有进那种超一流的大厂,但是你绝对不会只是在那个中小型公司在混了,明白吧,嗯很多时候呢,就是它会有一个自我的认知的一个偏差,这个偏差呢一般我们称之为叫达克效应,感兴趣你自己去搜。

我希望你们从这个效应里头一定要走出来啊,注意是达克效应,也叫邓宁克鲁格效应,不要不要不要叫达克宁就行好吧,开个玩笑,把你自己从认知偏差里走出来,你这时候你会发现人生广阔,天地皆宽,跟你的学历关系并不大。

记住马云什么学历。

系列 3:P10:【多线程】synchonized实现过程 - 马士兵_马小雨 - BV1zh411H79h

第一个,首先我们在java代码这个层级,java源代码这个层级其实就是在你源代码里头加了synchronized的吗,大家知道这个代码这个你要执行的时候呢,就需要对它进行编译,编译成什么呀。

编译成class文件,class文件叫做java的字节码,好在这个字节码层面,这个srt又是怎么实现的呢,我给你分层角,你就更容易理解,因为网上有很多人呢讲这个东西的时候,它不是分层。

把那个操作系统的概念和你gv m那些概念全混在一起讲,所以你看不懂,我给你分层讲,你写一个java程序。

你在你的代码里写了synchronized,当你编译的时候,他干了件什么事呢,大家看这里。

比如说我这里加了新功能o好,当你编译它的时候。

view show by code啊。

然后再拿出去去看他的字节码的实现,main方法里的字节码实现这个字节码实现,你会明显的看到这个东西,你把sirt去掉就没了,这个叫monitor enter。

monitor监视器退出的时候叫monitor exit,所以它在字节码层级的实现相当的简单。

他在字节码层级就干了这么一件事,就是monitor enter加了这么一个指令,字节码的指令,然后呢整个synchront的代码执行完了之后要模拟it is it monitor监视器啊。

这个监视器我能监视你这把锁呢,现在我进入锁状态了,然后现在我退出锁状态了,就这么简单没了,但是在整个执行的jvm执行的过程之中进行所升级,自动升级,从六楼来进入到偏向左,从偏向左进入到自旋锁。

所好在更底层的时间,lot,compare and exchange,这是用我们更底层的一个事件,在cpu汇编这个层级就这么来实现的,所以一层一层一层single laze就是这么来实现的,好讲到这里。

关于synchroni的问题,你是不是可以吊打面试官了,感觉可以了吗,来有信心的同学给老师扣一吧。

好了。

现在是09:50,再讲点儿,面试官不会也不会问吧,我讲完了,今天听的没有面试官吗,今天来听课的没有,面试官一定有啊,我不我不信没有,哈哈哈,再讲一点好吧,09:50,讲着讲着讲的不困了,所以再讲一点吧。

给大家就能多讲一点,就给大家多讲一点啊,但是关于volatile的话呢,其实它比synchront要难要难啊,我先跟你说一下,volatile其实要比synchront要难。

呃首先第一点model有两个,有两个概念,第一个呢叫做线程可见性,第二个呢叫做,阻止指令重排序,这个,关于线程可见性这一点需要老师讲吗,需要老师讲的,同学给老师扣二,哎呀县城肯定性也需要老师讲什么。

可见你对wallet就一点都不了解,应该是,所以我就想想我把程序放哪儿了,还得给你看看程序,the best locking,可中断的。

hello volt。

来先读一下这个程序。

先给你这个了解一下小程序。

来,看这个wallet的基本的概念呃,比如说我们有这么一个小程序,这个小程序呢你可以理解为就是一个游戏服务器,这游戏估计运行还是停止,用一个布尔型的变量来存储它的状态,running等于true。

如果说你等于出的时候,它就不停地运行呃,在我们有一个m方法在方法里面的while running,只要它是在不停的运行好,那么呃他就不停地执行了这个m方法开始的时候,i'm stm方法结束的时候。

and,那么我们呢做了一个线程,尿了一个新的thread,在这个新的线程里面来执行m方法,这个方法里边是一个死循环,看到了吧,所以它它一打入进了m4 点之后呢,它不会停止,不要让他start。

我把这个running设为false。

当然你想一下,我把running设为false代表什么一个概念,就这个while循环应该就结束了吗,while循环结束了,你整个m方法应该就结束了,还整个小程序啊,最基本的概念都不懂的。

你好好读一下这小程序写。

来读一下,十秒钟,好看这里啊我乱起来,run run run run,快点,啊因为我整个项目比较大,所以它run起来的话,得把整个项目全编译一遍,太客气了,当然你不用等了,你不用不论等多少秒。

他也不会结束的,他接受不了好,你往这儿看,我要是把这个变量给加了volde,停止我重新跑,把软件给变量给夹了,脖子条,stm结束了好这里是因为什么呢,因为model最基本的功能叫做保证线程之间的可见性。

或者保证cpu之间的可见性啊,本质上是一样的,因为cpu是跑在不同的线程,是不同,跑在不同的cpu里的,来我们解释一下,大家知道我们有一个值叫running,它在平时在哪啊。

是在我们的内存里running,这时候能等于true,一个县城对他进行访问的时候,是把这个值复制到他县城本地去,线程本地内存,这个县城本地内存可以理解为就复制到自己的那块cpu的寄存器里面去。

我把这个值读进来,它是一个true,这个线程是t一的线程,它不停的执行m m里面只要y这个true就行了,well发现他外号为处,它就跟着不停的执行,不停的执行不停止,虽然在另外一个县城里。

我们的主线程里把这个r值读出来,然后给它设成了false,但是呢这边看不到,知道吧,那怎么让他结束啊,给这个直接问了他们,word上什么概念叫做保证线程可见性。

保证线程可见性的意思是一个线程对这个值进行了修改,马上给我写回去,而且另外一个简中要用到这个值的时候,下一次循环我要用到这个值了,重新给我读出来,这边改了之后,下一步它重新一读,读出来了。

读出来之后就结束了,还有这叫做保证线程可见性好了,同学们,所以wallet的第一个概念叫保证线程可见性好。

系列 3:P100:【Redis】redis中value类型--list - 马士兵_马小雨 - BV1zh411H79h

我们开始讲课,简单回顾一下,简单回顾一下,我们在学redis,我们在学redis,redis在一台服务器里面,它是一个进程,然后它里边会有默认16个库,然后你可以在一个库上创建很多的兼职。

对着对着对着队,然后呢建都是为都是一样的,这个k啊都是这个k都是一样的,只不过歪的里面有很多的文章,它的类型有很多种,我们之前讲的什么,之前讲的是string的一个类型,数值的操作,还有bt map位。

图,二进制位的操作,没有声音的话,我给打个字吧,我过完这个视频啊,到了就当做英国同学之类,马老师一块,没事这样的处理下客户端好吧,这是这是之前讲的,那么spring算收官了,给你讲完了。

他有这么多案例跟你说过了好吧,这篇翻过去之后说第二篇,其他的也行,比如说下面要讲一个list,然后讲一个list的类型,首先你要明白的是,还是那句话。

这个value reky当中那个value的类型是list,注意它的value的类型,list k还是一个字字节数组,一个字符串一个类型,那么一提到list,一提到例子你会想到啥。

就是每每提一提到历史的时候,如果你是一个coder做程序的,你会想到什么呀,什么是历史的链表了呗,首先你要想明白它的一个链表,这个一提到链表的话,列表的分为什么呀,列表分为单向链表,双向链表。

然后有环的和无环的,对不对,对对吧,它是一个线性的,也就是说这个我技能从前面找到,你就能走后面往前找,那么这双向的如果再来,然后最后一个就是首歌,不知道知道有10年以上的a一说这4年一个这个双向链表。

然后如果从最后一个我还能回到第一个开始,从第一个还能直接去到最后一个,那么这叫做有环的,那么一般我们很少去用用到那种有环的,就是一般就是无环的双层电表,这个列表,这个这个是你要知道第一个点可以。

比如第一个存了一个a,然后这里面存了一个b,这里面存了一个c,然后在rei当中,它的value如果是list list类型,你像这个value里面放了很多元素的话,这些元素就是这样去存储的。

然后这个时候注意它有一个p release key当中,我特意的在这都给你写一下,他的key当中有两个东西在key身上,一个是hi,一个是t,那么同位指针在k当中有这两个两个乘属属性有什么好处。

这个i的话可以指导你这个y的一个链表的第一个元素,太阳的话是可以指着它最后一个元素,那么这样一个好处就是如果你仿了一个key,然后它的类型,它的value的类型是list的时候。

你可以通过qq有的有的两个属性,快速地访问这个value列表当中的第一个元素和最后一个元素,先把这张图画出来,这是一个基础,当你对这个人对他这个类型为例子的value这个设计感知之后,我们再来聊。

比如说在这里面我们可以用help你放我出来,但是今天我们要讲历史的话,命令当中有很多,比如说b开头的,然后左边的什么弹出啊,右边弹出之类的,然后还有一些l开头的,那么还有一些是r开头的。

在这里面第一个开头什么意思,开头有一个俗称,就是其中有一部分命令l是left左边的意思,r是右边的意思,然后呢还有一些以l开头的代表的是粒子这个类型的命令,就是通过这个字母就知道啊。

这个后面这个命令是只能操作外表类型为list,第二基本上right当中后续几个类型的value,它的命令都会拿他这个类型的首字母拼他那个那些个所有所有的子集,这个命令啊,这是他的一个特征。

你看好我一会给你讲,通过这个have,我现在先带你走一遍,照你那么比如说现在看我图一个简单操作,如果我想对一个链表往里增删改查,添加元素那个比如说就是list,然后说这个兔使。

那么注意这个l是左边的意思,从左边,然后往里推送对一个key,这个key你随便起,然后主要是value y轴往里贴什么,注意它value是一个可以多个,比如我填a b c bf,我可以添正多元素进去。

哎,都哪些注有点多啊,我先清一下库,flash这个问题问你家,重新退一点,拿到这边来,这里有几天卡,那么这个命令就是我们的粒子命令,这是push往里压压。

把那个key代表那个粒子往里添添了a b c d e f添了这么多元素,然后我们先不考虑别的命令,如果这个程序是你设计的。

你觉得在内存当中它应该是怎么码放的,如果这个k就是k1 。

我感觉就是一个链表,我通过了一个命令往里推了a b c d e f q了很多很多个元素进去。

请问它的内存当中,这个双向链表里边a b c d e f是怎么放的,咱们可以刷一下,在公屏上,在公屏上,他的这个在这个例子列表当中,它是怎么去怎么去存的,这个过程是怎么做的,相关的一个这个吗。

那就是两个,你直接把顺序给打出来,那是a b c d e f吗,第一个叫一个王者还是f1 dcba是哪个方向,这点很重要,啊你看这不同的声音了。

那么这时候你来理解一下,注意它前面是不是带了一个l是不是左边的意思,是不是就是后续的元素是在链表的左边往里放东西。

对不对,放的时候是比如说先把a放进去了,那么这个位置是比如就是a了,假设后面没有东西啊,那么表里如果一个元素的时候,你光放a是不a就进去了,然后注意是不是还得往里放,b b的时候是不是从左边开始放。

从左边开始放的话,其实找到t就可以从had当中,然后找到这个a然后在左边放一个b,然后had指向b b在指向a然后tab指向a就可以了对吧,所以这周放的元素应该是f一等等,这个顺序听同学来刷波一各种挑。

这个时候大家想一下好吧,来那么这时候让你放有有一个方向有l的,是不是应该有r,因为它这个链表双向的嘛,你看有l从左边放的,就有r放的,那么这个r不是k2 的话,还是a b c d e f也推荐一个元素。

然后这时候回说,那么这个k2 里边放的例子,其实先把a放进去了,是从右边先放一个a,然后从右边往里放一个b,其实就是找个tell,然后在后边追b追c追d追眼这个k2 里面的a b c d f k1 。

里边是f e d c b a那个顺序好吧,这两个非常好理解,这往里推送,那么推进去了,我如果想把金的元素弹出来取出来,注意它有个成对的命令,有push,还有一个那个pop还pop,比如说这两个。

比如说这就定个k1 ,我就对了一个k1 ,我可以用l pop,然后对着k1 ,然后没了,这一把就是你对哪个k弹出一个元素回车,它弹出就是f,因为我对k一放的时候,因为从左边放的,所以f是最后压进去的。

然后泡泡从左边弹的话,弹出一个f,如果继续弹,会把e好,把d弹出来,看到了吧,那么这时候注意听我在给你讲list这个类型,但是霸现在我用左边推左边弹,你发现他在描述一个我们编程当中的什么东西啊。

这个f是什么时候进去的,什么时候出来的呀,lf是不是最后进去的,但是他却被第一个弹出来,然后一直弹出来,d的弹出来,能理解吧,没错这描述的是一个站啊。

所以list这是这个例子是非常好玩的,两个类型的专业当中,这个例子可以描述我们java开发当中的一些数据结构,除了它自身可以是一个类似的类型,这么一个数据结构之外,它还可以描述这样。

那么站你总结一下是如何时间站的。

它的规律是什么规律啊,那我想对k2 实际实现站的话,我想对k2 刚才压进去这些元素也是先把f弹出来,我下面怎么去写,是不是要用r炮k2 才能把f弹出来。

对不对,所以这时候你可以找一个规律,什么规律同下,这咋回头啊,下面是不是同向命令,这个这个这个总结的很到位吧,就是在你使用例子的时候,如果你使用的rl的push和pop的话。

那么你在对着那个类似做站的使用。

但是有头像之后还有逆向就反向,如果说我对着这个k1 ,你l推进去的,我r泡泡k一他们就把a弹出来了,那a是不是先进去的,a是不是先进去的,然后a现在如果一直使用r的话,是a先a的先出来了。

是先进先出,对不对,所以他又能描述什么样啊,类似的描述可能在加上当中,我们可以用什么东西就自己不用去写了,直接连接redis就可以完成那些java jdk api的东西,是不是队列好吧。

那么它的特征什么特征,反向命令各种事物的时候,要么全部对数,是不是含有变量,那么这时候一定要get到一个点啊,就是你当发现rex的东西越来越丰富的时候,找到丰富感之后。

你会发现未来你的程序可以不用new jdk的app,因为那个在你的这个java进程的堆内存里边,你这个进程消失,这些东西都没有了,为了数据的可靠性,你完全在api层面的时候。

不用java自带的什么map啊,什么队列啊,什么list的,什么数组之类的,完全就是接release,然后所有数据从你进程写到rarely去这个词,这个听同学来刷波一。

那么这是一个最简单的一个概念啊,那么除了那么刚才是一个元素,一个元素,如果你想看里面所有元素呢,有一个l range,但是这时候注意了这个l就不是左边的意思了,这个l是类型list的首字母。

list首字母后面可以给出一个key,然后给出一个star store,又一个起始和结束。

然后在这儿还要必须记住一件事情,就是right room做的非常巧妙,他都有正负所引,那么面向我们刚才维护这个,如果他一个电表,那么它的索引值是零,它的索引值就是一对吧,然后他的所引值就是-1。

然后它的索引值就是-2,基本上redis会被后续的东西都维护这么一个负向的,就是政策所引,这这个前面学那个string的时候没有字节,这应该非常好理解,那么这个时候再来看。

根据过往经验,如果要拿出所有东西的话,后面接t1 ,我后面可以接什么呀。

star从零开始,从左边的零开始,然后里边队伍元素不知道我在取回所有。

是不是直接给出右端-1是不是可以了,大家可以看这些没看清楚,但是不使用交叉曲,听不见了,我说我说我说我说了也听不见,听不见了,就总结一下,你能听见我说话了,对不对,哈哈哈好了。

那么这时候看l range,然后k10 -1是不是就把里边cd取出来了,然后咱们来刷一下吧,刚才在那个支点的验证一下袁绍,然后还是我对着k一压刚才的一个元素,对于k一从左边压的话。

是a b c d e f回车,然后这个时候你用l o n g验证的话,我k一从零到-1是不是就是f是第一个,因为它是f从左边最后进去的f1 ,然后如果是刚才的k2 从右边推的话,然后l让你然后k2 的。

然后从零到-1,那么拿到就是a b c e f,它里头在内存里面打的顺序是不一样的。

但是第一个叫好,就是这个又增了一个正负正负正向缩写这个知识。

然后这个锦鲤练就熟悉了,其实有战和队列之外,他还有一个能力,比如说我们可以看一下,他还有一个index的能力,什么都会搞,这还有一个hour index,然后给出kindex。

get a limit from a list of bug,就是根据它的索引,你给出一个索引可以取出丽兹的元素,有这个可以取的元素,还有一个l s一个都是成对的,还有一个l set给出一个索引。

给出一个value,那么这是对着某一个索引更新的,这个值除了可以跟按照索引取,按照索引更新,然后后边还有什么删除之类的再说,我们先来演示一下哈哈,比如说l y让你看到k一里边从零到-1的值。

我想把d取出来,我怎么去取,然后index就是t1 ,d是第三个,也是下标为二的,问给出下标index取出来就是d如果对列表我也不知道多长,我就想取出最后一个,那么这时候只用l index。

然后k一的-1就取出最后一个a对员工能看懂,同学们哎,我说这个时候注意我比如说再再做一个,我想把c我想把c变成x等于做是l set list set,在对着t一去设置是谁,这是c 14,那么下面就是三。

因为咱们下边缩引从零开始的变成x多写几个x回车,然后l range,然后配一从零到-1,那么乘着4g就变成x那么现在回答我同学们,现在回答我一系列这样的命令,就这样的,l什么index什么的。

l set是什么东西的,然后操作所有这种形式的。

其实这是历史的,又像什么的呀,还有可以代替你曾经计算机当中使用什么数据结构啊,这话有结果应该是放的,按照新公司没错,数组,如果你一直对着它的索引操的时候,它其实就是好像是一个数组嘛。

因为数组是频繁使用下标的啊,好吧,那么再多说几个命令。

除了可以这样,还有,remove啊,那么一个l是list的意思,remove是移除的意思,就是移除一些元素from list,但是注意语法是移除某个k这个k他对另外的一定是粒子类型的。

然后count多少个那个外表,那我在这补一句,在list当中,list这个类型去除吗,list去除吗,链表驱虫吗,公屏刷一下链表,是不是不去虫没错,这一点一定要知道,所以才有这个财务会有这个命令。

比如说我在设计一个k啊,l然后push了推推着k3 推推一个一个推一个1a b2 b,然后3a4 c5 a6 d好吧,我这么这么一个操作之后,l one对我们的k3 从零到-1取,那么取出这些元素之后。

这里边有一个a然后两个a3 个a,然后我做这么一件事,情,如果l remove主要移除移除k3 ,移除几个,我想移除两个,移除谁移除a这个语法对都应该能看懂,是不是都应该能看懂。

那么请问我这三个a移除哪哪哪三个a移除哪三个a,你说了数据是不可以用的之后,那么在这要注意了,先给你剧透一下这个数值,这个count这个数值它分为正数,负数和留三种情况,如果它是正数在底层链表的。

从左就是还得头开始向右找它次数各,然后移除也就是为正二的时候,移除的是第一个a和这个a,然后b这个这个二一之间那个a是不移除的,比如回车一共两个,然后再来看一眼,也就是二级店那个a是没有被移除。

这个qq同学来刷波一,咳咳然后这时候我们要模仿刚才把这个a再贴回去啊,他还有一个命令,比如说还有看一下list,咳咳咳,是否算有四个,但是还有一个规定是可以在水前面插入一个l insert,插入。

插入的时候分为before前after后,你给出一个元素要差的是哪个,就是你面向那边都用哪个元素,在前面或者后面插入一个什么什么值,这个是l a s,比如说像刚才l orange我们的k3 。

然后从零到-1,我想在,六的前面插入一个a,然后三个四的后面插入一个a也非常好,你说在六的后面,他六的后面插入一个a吧,咱六的后面插入一个a是l insert,然后对着我的k3 。

然后index indesert,第一个对着我可以三,然后再after,然后在谁是在六到后边六,注意这六不是索引啊,是这个元素六对吧,是这个元素在元素六后面插入一个什么,插入一个a回车。

然后这个时候l range,然后我的k3 的零到-1个a就在六下面插进去了好吧,再补一个,补一个是在三前面插,你拿过三的前面插入一个a这就是before,before写错了写错了,然后再l range。

然后k30 到-1,ok这个a是有三个a了,当然正数的时候,如果l remove k3 为周二的时候,移除a是前两个,那么为-2的时候移除的就是我们的后两个好看,前面那个又住了,后面两个也被移除了。

好吧,那零的那个零的那个如果两个六的话,他就在第一个后边追加,他不能在第二个后面追加,这个问题的确的确很值钱,如果两个六的话,他只能在第一个,它换成第一个位置,差不能在后边了,好吧。

ok这个知识点听完的同学来刷一波六,所以说你那天说的都是对,然后相应的常常见的,比如说在我们的字串当中也有统计,就是style los,在这也有一个l l lse。

总结我们k3 和杠精一共有多少元素等等的一系列的这个命令,好吧,这是最基本的,最后list里边除了这三个,还有除了这三种方式,还有一个功能就是b开头的一系列b开头的内容。

比如说b pop和b pop或者是b的push,哦不是这个是是都是b炮的,无非就非一个l和1l两端的端,那么它是什么意思,他是阻塞弹出元素,无论你是否存在,比如说我把库删掉,flash全清掉。

这是我的一个标签,然后随便再找一遍,再开几个redis plan,再来个6379,然后再开一个redis杠client,我现在一共有三个客户端不听。

我有三个客户端都连接到了同一端口的统一进程的reid身上,然后注意看他不是避开的话,比如说先看看pk这个库里是什么什么简直就都没有,什么数据都没有的,但是bl p翻的其实无所谓,然后对着一个圈圈叉叉。

那个key不是一个key,那么是l这个因为那个mate来自于例子,未来肯定是一个例子才才可以啊,然后我要取取取东西,然后这里面注意你可以可以可以这个可以多个啊,可以一个后面还有一个time out。

time out,超时时间的意思也有阻塞多久的意思啊,组合多有意思,如果你组你写的是一个具体的一个时间,就组成这个这个这个描述,如果你写一个零,那么它一直会在阻塞,等着这个里面有没有数据回来之后。

首先第一点全家是不是不存在,里边也没有,他说不能耐,也也也里面没有数据了,绝对是他想泡泡他的话,他根本都是乱,然后由于你生成零了,所以他一直在那等着他,阻塞了这个他的未来里面有数据,这是一个。

然后我再开几个还是一个b,然后pp还是圈圈叉叉,然后我还是阻塞零,那么现在第一个是它阻塞的,第二个是这个客户端阻塞的,然后看那边如果有一个客户端说突然有数据到达了。

随便一个r push对我圈圈渣渣放了一个hello,那么这个命令是不是像那个队列里边去这个例子里边去压一个元素,哈罗进去,对不对,往那去压回车,啪压进去了。

然后这时候看两个阻塞也是第一个紫色的拿到了数据,他在这个队里面拿到了哈佛那个,然后第二个且没有推出阻塞,然后这时候如果扣某一个客户端,再向里边生成一个数据在上面,那么第二章就拿到了,那么综上所述。

他其实还支持一个什么呀。

通常来说一个简单的组词队列,对不对,这个作弊或者单播单播订阅,注射的单播给送两颗星,是作为各位业主说的话,下次有微信啊,之前我们应该做的提交大部队列,这句话什么意思,同学们还是挺好用。

什么叫紫色的单播队列啊,因为如果消息订阅的话,有可能我一个人的消息可以被十个人订阅,100人订阅,我所发的这十个人同时都拿到,但是刚才有人发现,我发现哈喽到这个这个历史里边,谁第一个阻塞的,他拿走了。

第二个人根本不知道有这个东西出现,但这个人还在那等着,没有意思,而且这里面得出一个结论,结论才是特么force force out先解,对不对,拿到我组错了,有了我拿着我走,这是一个简单的。

为什么先埋他一笔,因为后面redis有一个特征,它是支持小订阅了,所以订阅了那个那个最后讲。

先先说说这个这个质量,还有一个小命令,还有个小命令,这个小命令挺好玩的,还有一个是l tree tree,我看一眼,然后是剩下的意思是你给出一个stars store,比如一个起始。

然后它会对那个list那些原则中的stars stop stop,两端的数据进行移除删除,它会对两端进行删除,你一次打造中间的东西是不会删的,好吧,我来演示一下,咳咳咳咳,然后push一个k4 。

然后a b c d e f我就往里往里放东西了,放完之后随便放,放完之后l orange,然后k4 的攻音开始到-1去这个元素,然后这周注意我做这么一件事情,还trim,然后对着我k4 从零到-1。

请问我回车之后删多少个元素,公屏刷一下,所以到后面里面发展,所以按照你来的时候,他姐夫不会强行说点回车,然后再l range一个元素没删,为什么,因为他是删你这个零和-12端的零零最左端的飞行。

最右端了都没东西了,那这时候如果把前面零改一个,把后面改一个-2和车,那么删掉的就是他首尾那个元素可能看懂吧。

当你出生先生的命令了,我就不给你往后写了,然后自己一定要拿着我的给你那个比这个图的框架,晚上补补这个笔记啊,补这个笔记,然后你你自己操作一点点笔记,我给你写一个轮轮廓的一个笔记。

你再补一个你会实操的过程,让你记得会更清楚一点。

系列 3:P101:【Redis】redis中value类型--hash - 马士兵_马小雨 - BV1zh411H79h

然后除了list子,再来讲下一个list子这这段收了。找下一个。能保证。reice5种外能类型,除例思,还有一个还有其剩下几种,还有比如一个哈西哈西是什么意思?其实就像你们曾经学的那个扎亚东的哈希麦。

然后卖了它一定是什么呢?坚持段少。KV。但这注意了,这个哈希类型说的是raice建职队里的value的类型是哈希。然后哈希的话代表这个value里边,它自身又是一个键值对,就等于你们在账号当中。

哈希 mapap里面那个value里边又放了一个哈希 map。😊,非常非常简单这么一个一个一一个理解,好吧,然后讲他之前。

我们来讨论一个事情,如果面向一个用户,他有姓名、有大小、年年龄,有有地址。然后这三个维度每一个人都有这三个维度,让你使用readies存取的话,你怎么去设置怎么去存?每个人一个一个公司有很多用户。

每一个用户有三个维度或4个维度。存出来有那种建段的数据库。如果没有学哈希,他们给你开发这个K,你可以怎么去用啊?我希望可以这样去用。就用我们的简单的间别句,比如说set一个肖恩。

然后name中间你可以用这两个冒号来隔离。前边是肖恩这个人,后边这个是他的名称,但是他整体算作一个T,一个字符串,它整体是一个字符串,它只能就是一个value,它个valueview就是说。周磊啊。

这有一个一个周磊的名字回车。取的时候你要get肖恩给出K的完整的名字。就能把里边那个层那个值取出来了,这能看懂吧?哎,如果。除了有。How8。然后比如说18岁。Kt Sean。诶。就是18你也能存能取。

而且你从K上是不是也可以也可以区分出来,对不对?啊,也能区分。然后case用这个命令的时候,你还可以肖恩星号拿出关于肖恩开始的后缀的所有的这个K6是吗?你把这个拿回来之后,你扣端是不是可以询问电力。

分别对整个完整的K发起这个概的请求,你你也可以想拿谁拿谁。是个成本。这个车呢其实是极其。及第阅为什么?如果这个肖恩有100个字段,什么姓名地址啊,一W堆100个字段。

那么其实你可以先用一个case发一个指令,从你的客户端发一个消息发到服务端,服务端给你返回了一堆的关于这个这个肖恩的这个所有的K。然后呢,你可以通过一个more get再发一次多个K的取值,对不对?

你可以说可以通通过moremore get,你可以一个一个取,也可以通过more get发一次。但是这时候你会发现一个case取回,然后再一个more摸 get多次的多个case读取。

你有两次对服务端通信,对不对?😊,这个理解吧?而且你的个case触发这种模式频面的查找的话,其实成本是很高的成本很高的。所以这个时候解决它的问题就完全什么呀?我的K可以是肖恩。

然后如果它的value是一个间定对数就好了。😊,那么这个就是所谓的啊要是要引这个哈气的概念。注意看哈希的命令一般都是什么开头,是不都是H开头的。那么基本上就是小学或者一这个这个幼儿园大班的这个英语水平。

你见到A开头呢你就知道啊,这个肯定是哈西的相关的命令,这个有哪些比如删除啊是否存在呀,然后取里边的值取的是你要取value的话,肯定跟着K和那个fe因为这个value也是一个间然后get取回所有。

但是get什么the andvalue对吧?这个K名下的它所有的那个value里面那个间段给你取出来。然后他也支持相应的计算,对着value,然后还有kis取回所有的K。

取回取的就是有多少个间对这个value里边还有more get取出相应几个你指定的那个这个fe。还有有摸掉的就more side,你可以试置多个或者H side,只是其中一个。

然后还有一个不存在的时候才可以被设置。现在读起这些单词就已经见名之义了。因为其实和我们曾经那个单词符上的操作一样,只不过是在字符串,那些命令前面加了个H。还有一个strlu,这是字账里边,前面加了H。

那代表就是建立段里边的we间立段那个操作压力级。我们来演示一下。还有1个HY的是属于所有。那么比如我们准备把刚才那种单一的多个K能表示一个人的数据,用一个K一个K来表示。比如说Hs一个K。

一个K就是肖恩,然后呢它会有name name的话就是周志磊回车。那么这个时候其实你是对着这个K里边只做了一个间对。那么一个K里边的Y6,如果是这种间对的话,它其实可以有很多笔,只要K不一样就可以了。

所以这时候你还可以H more set。对的,这个已存在这个key,然后给出间立多少,建立多少间座少,一定是间对成对成对出现的。好吧,然后比如说在age,然后18岁,然后address。

然后比如说北京回车,然后往里放了,如果想往下取的话,注意是H get。其实你把H抹掉之后,是不是曾经建立队的那个那个sprint操作,只不过现在描述它的ve就是那个哈希的。

然后给出key给出给出field。你们可的话,就是肖恩这个人。然后比如说取出它的name回圈,就是周志蕾,然后取age。这是18等等的,这就不多演示了,还可以mgan。给出肖恩,你要给出K。

给出K之后要给出几个,你要取择一个字段。比如说有name age,他那两个都取出来了。还有比如说H kiss,然后对着肖恩,我只拿回它有多个字段,我要生成一个表头,然后或者是H kiss。

然后我们就H values。然后对于肖恩,我只取分的一个value来填充下分成jason来封成封装一个固定的一个表的内容,或者是H。Get他 off了。get到追着我这个肖恩。

那么这样的话我会取出这个key,它里边Y的那个间职对,所有的那个间职对儿,它们呢既有title又有valuetle valuet value。那么这样我在封jason的话。

给到前端现段就可以绘制绘制出一张表了。哎,那么这是我们关于哈西这种建支队儿的YYY类型为建支队儿的。他还支持数值计算,在我们使用类型当中,是不是支持字符串这种操作,也是不是支持我们这个数值的计算。

你比如说在这里面一般有一个小故事,就是你要问一个两三岁,刚说话的小孩,送三四岁的啊,你问他你你你多大了,这个小孩一般回答年龄都是比如说这个3岁半或者5岁半,有一个半,对不对?几岁半。

那么其实啊你像我的名字叫周志来,然后我的年龄是18,但是其实我这个年龄不是18,我是18岁半,那么这时候要不然我年龄我东记错了。如果要变的话,他怎么做,你可以覆盖,直接覆盖一个覆盖成18。5,对不对?

他也支持计算。比如说H。Increase by flood。你把前面盖住了incr increment by float是不是增加单丁的那个问题,对不对?对着肖恩对着他的age,然后增加0。5。

然后再Hge肖恩 age。回车就是18。5没毛正版。是不是刘老病?哎,那么这个时候其实哎我说错了,记错了。其实我17还不到18岁呢,我还不到18岁。那么怎么办?是不是要给它减掉一,对不对?

然后这时候有H吗?有吗?是不是没有是不是没有。那么其实这时候加法也可以做减法吧,increase in increment by float,然后对着肖恩的age做一个-1。要减一的话,其实是不用fl。

就直接办就行了。这面能能看到吗?就是虽然是inclement增加,但是我增加了一个负数,这就是减减掉了是。哪错了?Hashveo is not an antiger。発信が。哦。

它是一个它是一个一个一个一个一个单晶的,因为这里面已经变成浮点数了,对不对?而且还是要加上那个f。因为这个win类型不是引Ter,它是一个浮电值。

所以这时候你前面命令一定要是你的命令一定要随着那个value值要要要一一对应上去。因为这个命令间接掉底层方法啊,它传单的传对,所以这样做就对了。H钙 shown的 age是不是就是117岁半了?

当你对隔系有所可以。好吧,那么说一下,简单简单介绍一下它的应用场景,应用场景在哪。首先你妹妹res是内存的数据库,对不对?像这种所有对值的操作的速度都非常的快。那么当你有了这种。

比如说像我们的这个商品的详情页。那么客户端打开一个页面,关于这个商品会有很多很多的字段的信息,对不对?然后这个时候你的客户端要请求这么多数据的话,这一笔请求请求一个接口的时候。

你接口是每一个数据然要访回一次数据库呢,还是说我给出肖恩就拿出了它所有的Y6斯,然后呢,给客户端返回页面,你刷新就出来了。

然后这是第一种,就是数据整合的访问这个总量,调调用次数会变会会变低。第21个,然后数据的话都会随之变化。比如说微博当中有关于我这个人的关注,然后点赞,然后商品详情页当中有这个页面被浏览的次数。

被收藏的次数,被加入购物车的次数,那个数据既要被查询,有的时候他要发生计算,对不对?所以这时候他的哈西这个类型当中还支持这种数值计算。是我们而且还能统一取回的一批数据面前的一个对象的。

这就是它的应用场景。好吧,我先不介入更多的技术,就拿rease来解决这个问题,是不是可以解决了?进入选型的时候,你可以选选型这mongo这种document类型的,也可以使用这种建制对儿的。

因为它其实这种就是一个简单的哈西,其实就是一一种简单的document,只不过它的value就是reice的value是哈西哈西里边这个里边这个存的这个建职段儿这个age0。5,这两个类型就死了。

它就不能再再分叉了,它是单一元素了,所以它做不到一个复杂document,但是它自身它已经是建队,已经是doment了。😊,这个这个共同点能能能列吧。好嘞,那么。简单的做一下笔记。

就在讲了哈西的时候。这块好像没有什么可以可以说的。就做一个吧,可以做数值计算。可以对数值进行计算,一般做的应用场景。比如说各种的点赞啊。然后收藏啊。然后详情页。等等的。

面向一个人或者一个事物的一个页面的等等的,好吧。

系列 3:P102:【Redis】redis中value类型--set - 马士兵_马小雨 - BV1zh411H79h

有16类型、粒子类型、哈希类型。那么它还有什么类型?再往一下再来一个类型。Okay。我把这三个。我还正这个。最后把。还有一个类型是set。sad类型那么注意听前面是不是有过一个list了。

list是不是就是等于一个向量,然后它里边放可以放很多元素。那么side其实它也是一个可以放很多元素的一个一个数据类型。那么这个时候为什么有了这样的一个东西,还有这样的一个东西,它俩不是重复了吗?

没有reice在学数据结构的时候,是不是也要辩证这个问题。那么其实每种数据类型有它自己的特征,对不对?这以时先对对比着来描述一下,list是可以有重复出现的,是不是可以重复出现的,且list是有序的。

but注意听。或者你们先给我解释list有序,这个序描述的是什么序啊,什么顺序。这是么小能力的。我不要听。没错,是存入的插入的弹出那个顺序,对不对?它并不会去做排序,对不对?

这个list没有给你去做排序。所以这时候把它描有清楚之后,然后再来看ss是一种什么呀?去重的一种集合,它是去重的,它是可有重复,它是必须去重的,而且它里边不维护排序。

也不维护存这个插入和这个弹出这个这个这个元素的变化的一个顺序。它完全是会这个这个乱序的。但是它里边最致命最优势的一点,就是去重。如果你能够去重的事,用它就可以了。找到每种类型的特点了吧。

OK这个定完之后,我们再来继续聊这个s可以做什么事情。这写。能干这个节奏吧,没问题吧,我觉得觉得其实应该。应该算应该算比较慢了。首先它的第一个特征啊它的特征。あも。是无序。然后去虫。

这是它非常值钱重要的。因为你要在不同的场景下使用不同数据结构的时候,你要选选选它,那么就一一一1依据它就可以选。

回来。😊,我们来看一眼s有哪些命令。一定要我现在没有讲API开发,但是你们一定要。这个先拿着这个命令行这多练习,多使用,多看帮助,把它弄明白了。因为你基于命令行这个都弄明白之后。

其实像这种no circle口基本都是原语的。也就是说它的命令的方式比较单一,然后呢,功能比较比比较简单,然后它的API的一端和它是基本是一一对应的。

你在这有这个命令到API那也点一个对象身上也可以点出这个命令。好吧,所以你只要会一个,先拿着一个面,会了之后,其他东西就好学了。那这个呢比如说S艾可以向你这个key。

然后里边去这个这个s里添加添添加元素,你可以给一个,也可以给多个。然后又因为它是s类型的,所以你把你即便有重复元素,它也会给做一个去重。这可以往里添加。

然后Scar这个Scar的话是可以给出几个当中的元素的个数。然后像different different store和in这个。interect,然后还有一个un等等,这是关于集合的一类操作。

就是交并插集,这个很重要。然后下边的是S is member,你要给出一个member,看这个集合当中是否有这个元素啊,使用这个元素。

然后还有S membersge the members个 side就是可以取出它所有的元素。但是其实在我们使用s的时候还真不要刻意的客户端调这样的命令,因为你可以可以给s放很多元素。然后要它做元素时候。

其实会消耗ready所在主机的网卡的吞吐量。那么这时候这台主机上其他的进程,其他ready实力,那些个链接请求的话,可能就是请就变慢了。所以使用ready的时候,虽然它给出了很多的功能。

但是你要知道什么会影响性能。这句话听懂的同学来说一6。

所以一般如果说哎我这个还真得存很多的东西,真的就是为了让未来来取,还不把这种请求压到数据库里边的话,没办法,也就是单拿出那么几台服务器,就专门就放几个这样的一个集合,就专门负责这件事情就可以了。

就要在它的一个功能里边把它单切出来,不要特别的这种其他的些KY要混在一起使用。然后常用的还有S run member。然后还有一个来讲吧,一个来讲吧,基本的添加删除这个事儿已经可以可以可以操作了。

我们把数据填津再说。S艾,然后添加一个,我刷一下裤嘛,那是。D。先清一下,然后SI的1个K1,然后里边添tm,然后肖恩,然后peter。然后圈圈扎扎,然后套。然后再一个叉叉深针。好,听见。😊,S算来算。

S算添加添加完之后,注意添加了几个元素啊,一共1234566个里边只添加了5个,对不对?那么这时候我们可以S。members,然后对着K一来看一眼这里面它是对谁做了驱重,对了我们那个tm做了驱重。

这不是只有一个了,好吧,这是比较简单的一个事情。这个林老师那个声音我也是醉了。然后除了。嗯。移除吧,还有应该还有一个移除Sremove,可以有增山改查,可以往里放,可以查。

还有删除移除K里边的一些元素的时候,比如说remove我们的K一里边的,比如把圈圈叉叉和叉叉圈圈。移除掉回车,然后在S members。给出K1。那么就可以把两个移除了,有增山改查的操作之后。这个。

我现在还可以做它最重要的就是为什么要使用集合这种s类型,主要做的就是它要算它那个交集并级和差级,他们得准备两个元素,比如说SI的1个K2吧,231个21个32个K,这里边放12345,放5元素。

SI的1个K3,然后里边放45678。那么这样的话,我得到了S members1个K2里边上的元素和S members1个K3里上的元素。做交易差题的时候,什么叫做交定差题?比如说我们的S。因此。

然后给出相应的给到。你一看有两个命令,一个是。带就带不带那个story,带不带这个story。那么如果你后面不带那个story的话,如果不带的话,就是直接给出一个K2个K3个K4K给出一相应的K。

那么它就会做一个嘴的集合间的一个交集。对对吧?如果你带了一个,就是直接它会输出。如果你带了一个s的话,你要先给出一个目标K。就是交易的结果会存在你服务端的K里边。我来演示一下,比如先对我们的K2和K3。

回车,然后他就直接把结果给你打印出来了,就返馈给你给你的客户端了45,这是他的交集。明白了白?但是这时候如果你接了一个。S story。然后给出一个目标KDST回车,然后你客户端拿不到。

然后这时候你可以单独的去弟么Smeers,然后DEST回车可以拿里边这个交集的元素。好吧,那么这两点其实也是一个作者的比较细腻的一点。因为带不带st,它可以不开发,它完全直接开发这个单一命令。

然后你但是如果你想让readd里边既有K2K3那种全量级,又有它的一个交集。那么你客户端必须要先执行它取回,把数据邮走到客户端,然后再把这个数据,然后再S艾到你那一个新的那个目标K里。

等于数据会有一个来回的交互的过程,这叫移动数据。如果有了这个命令的话,你等你客户端出发这个命令,只需要给出两个数据级作为参数,给这个目标的。然后所有的做交集和生成新的K的过程是在服务端一步完成的。

数据是没有进入IO,对不对?能白吧?啊,所以你不光要知道这个命令,要知道哎呀,我我知道这俩命令,你不光要知道你在面试的时候还要多说了多说么这么两句,你多说两句,他就知道你会做这个这个选型的一件事情。😡。

那么除了可以有这个胶集焦敏差,然后还有病例比S。Yeah。uni然后给出也它也是可以带不带这个story的这个概念。分带和不带这个story,比如说我们就不带啊,就把我们的K2K3。

那么什么叫做那个病级啊?回正之后是12345678,它也会给你查的结果也会给你做一个去重。好吧,那么这个焦急病级是非常好理解的。然后注意看还有除了这种的疾合,还有一个什疾格,是不是就差级了?还有差级。

差级是哪一个命令来着?啊,different差级。那么注意差级它只有一个。但是我们知道集合的差级是分为什么呀?左差外差的对不对?啊,前差后差中差后差的对?啊它有它有这个方向的概念,但是只有一个命令。

所以这时候呢取决于你怎么用这个命令,它是有方向性的。不理解我的意思吧?然后比如说你把K2放在前面,K3放在后边,那么得到的是123,如果你给它换一个方向。K2,那么得到的就是678,所以这时候没办法。

作者没有给你设计过多的关于差级这个带方向的一个概念这个这个参数选项。但是你只需要调整你要做谁的外插是不就可以了。想在谁里边取到数据,就把这些都放到左边去,右边往后的时作为它的参考,好吧,哎。

集合操作是我们那个s用的比较多的。

下个里边现在支持一个集合操作,集合操作。这个用的是相当多相当多。有说的场景,有说到的场景。除了有这个集合操作,它还有一个操作。因为集合里边有一个命令可以产生随机事件,随机事件。

Oh。这个位是什么?是S run number。As our member。这个S remember,然后后面给出给出一个K,然后给出一个count的次数,取多少个。注意,这个count呢也分为正-0。

分为正-0。我们举个例子,先添加一个元素出来嘛,那是。哦,然后呢添一些元素给。比如说这在讲个sideI添加添加1个K1,里边多添几个元素啊,添一个。tm,然后圈圈叉叉叉叉圈圈,然后叉圈叉圈圈叉圈叉。

然后叉圈圈叉,然后圈叉叉圈。好吧,这是一个、两个、3个、4个、5个、6个、7个。7个元素对不对?唉,回车。那么用S round number给出K1的时候。

比如说我要在里边取出5个或者我现在写出来-5个或者10个或者-10个或者0的0个先不说啊。那么前面那种是有四种情况,对不对?是吧?四种情况,注意,如果是为正数的时候,为正数的时候。

它会在你已有集合当中尽量满足你的数这个数返回一个不会重复出现的结果集,如果为5的话,它可能把前面5个挑出来了,或者随机几个5个独立的元素返回。如果你给出正十,它也是取不出来10个。因为你才有7个。

它不可能把某一个变多拼拼成10个,这时候就会出现重复的元素。为正的时候有这么一个概念。所以事验的时候,也就是在用S member这个命令的时候。

然后后边会有一个key,会有一个烫子。然后主要这个抗抗的若为正数。为正数的数候,然后这时候取出。嗯,数量取出一个去虫的结果机。然后这时候无非就是什么呀?取多对不能不能超过。超过。右急。规避规了。

已有即合。这个非常精精精精辟,对不对啊?非常简单,然后如果是负数。

睇下。负数里边你有可能取的比他少,对不对?哎,负5啊有可能负十比他多,有可能比他多。那么这时候其实。

负数是首先它可以取出一个带重复的结果机。然后一定满足你要的数量。一定会满足你要的数量。好吧。如果为一空,那就是不返回。不如果为理由,如果。为理由,你说不返回。不给返不给返回东西了。好了。

当这个能听准之后,那么其实这个随机事件可以解决什么问题呢?我在图。他可以解决什么问题?来,我们可以遮肉刷一下,看可以解决什么问题。就随机试件的时候。正常。有强迫症都有。他可以做什么做什么事情。抢红包。

除了小红包呢,小红包其实不太不太不太准,你个抽奖,因为最多的是抽奖。抽奖是不是这种随意随意概念?那么抽奖分有很多种抽奖。比如说。如果我有10个10个10个奖品。10个奖品,但是我的用户。可有两种情况。

第一种情况是小于十。就是小于1或者是大于10个用户对不对?用户可能大过奖品数量可能小小过奖品数量,而且用户中奖。用户中奖又分为重复和不重复。重复。重。补充。是否重诉?没有什么意思?问们。而且除了有抽奖。

还有什么还可以解决。家庭。争斗。这点其实很重要。

我一个一个一个来说。如果我们现在。假设一个场景。假设一个场景,微博你有很多的粉丝,然后呢你准备了几件礼物,比如准备了三件礼物。你想让这些粉丝中备三件礼物,那么你可以怎么去做呀?首先如果用reads的话。

这个里面你需要准备一个数据集,请问这数据集里放的是什么呀?是放的礼物,那几件不同的礼物还是放的你的粉丝那些人?来都刷一下。那一定要注意了,你要放的是粉丝,你要你要放的是礼物的话,你抽出仨礼物来。

还是得撒礼物。你三你知道就得撒礼物,给仨礼物,你给谁啊?你说还还是不知道对不对,所以集合里放的是人,然后呢,无非就是抽三个或者是抽正三或者是抽负三的概念了。能理解我什么意思吧?如果你抽的是正三。

他就一定会给你三个什么呀?给你返回三个,因为三个小于他对不对?而且这三个一定是去虫的,你无怎么抽都去虫的。所以这时候符合一个语义,就是一个人最多只能中一件礼物。啊,不是。如果你给的是-3。

会有一个现象出现。如果你给它负3会现象重呀,比如八抽了,就你们没出现,然后再抽。再抽概率呢概率呢唉,这出现了,是不是为复数的时候是不是可以有重复的?也就你奖品就仨这三个有可能被一个人抽走。

有可能被两个人抽走,有可能被三个人抽走了。就是在抽奖的时候,你可以这么去设置,这是是符合实际场景,对不对?哎,就无非是一个正负的一个这个控制了。然后再来听还有一个场景,还有一个场景就是。

这是一个实际的一个场景,就是曾经我上班的时候,我在好多年前了,还没有raice,还没有raice时,然后是工行。这个工行找到我找到我们的这个公司,然后说他们里边一个人跟我说,因为他们自己的开发团队。

但是他们想自己部门自己自己造一个软件给他们抽奖。为什么?因为其实银行银行是做这种理财,就是贷款这种方式来来盈利的。就是他们我们存进的钱,这个钱在那放到,他长毛了,还得把这钱贷款贷出去。能理有什么意思吧?

所以他们工行里边很多的部门,很多人,他们每年一翻过年来,脑袋都大了。因为这一年要带出几十亿几百亿去,每个人都有很多的这个这个这个这个额度指标。然后那年年终的时候,那个部门他们领导人领导就找到我们这边说。

哎,你给我写一个抽奖的软件。因为我们是超额提前完成了这个任务,然后行里边上面的这个领导说给我们一些购物卡作为奖励。这个购物卡的面值有100的,300的、500的1000的。啊。

但是注意这个部门才十来个人,这个小部门才十来个人。对道吧?但是这个卡卡将近几十张卡还是一两两三百张,我忘了,他说卡特别多。能理白这么意思吧?也就是说抽奖中奖的人少,但是礼物会很多,对不对?😡,唉。

那么这个场景听明白了。如果想抽奖的话怎么抽?而且这里边还有这么一个规则啊,这个规则多说一下就逗你们一下。其实当时找我的时候,他们说了说这个卡很多,面值有大有小。然后您设置一个抽奖的程序。

尽量的让每个人都多抽几张,那均衡一下,别一别一个人就抽一张。然后呢,我们领导那多让他抽几张大大大面额的。明白什么意思吧?当然如果这个加上这个需求的话,我们用reies就很难实现了。

就很难实现这个公平公正的一个这个效果了。能令我什么意思?能令我想表达一个什么意思?这时候你必然要手写一个程序,因为程序里面要附加各种什么呀暗箱规则,对不对?那么我们不讨论那种这种黑规则。

我们就说正经的就是拿re公屏抽奖,人大于人小于礼物数的时候,应该怎么抽?有。小于礼无数的时候,应该怎么去抽啊?😡,是不是直接把后缀数放大就可以了。我刚才集合当中是不是7个人,对不对?

我是不是有20件礼物或者2张卡,我就让那7个人去分这二张卡,就是一定要加个负数,因为负数才能返回一个重复的一个数据级。回车。是不是就这么走的,但是这里边为什么说它是公平公正的,你看有套沫啥事儿吗?😡。

是不是top里没出现,对不对?你再抽一次,就就你抽的时候就有可能出现t了。哎,这是不是有T了?特别重奖卡。能解吧?就几种条件,几种框框。如果人小于礼物数,那么你用负数让那个一个人多中几张。

是不是就可以了?

然后这你课门之后,我说他可以解决家庭问题。

可以解决家庭斗争问题,什么斗争问题。比如说在座的未来都会结婚生子,或者你已经有孩子,有孩子咱就不参与这件事了。未来你会结婚生子,结婚生子的时候,其实孩子哪个东西非常重要,洗碗也算一个。😊。

因为这个孩子取名字是不是非常非常烦,对不对?因为你你想给孩子叫张三,你媳妇想管他叫李四啊,然后呢,你婆婆不是你看丈母娘吧,还是怎么的,你家里边的,反正各个人都给他推出了一个名字。

然后这时候那应该选哪一个呢?应该叫哪个名字呢?这以时候其实你可以比如像刚才我们那个。S numbers。K一里边假设这就是你家孩子的未来的名字啊,假设就是名字。然后这时完全你可以做这么一件事情。

你非常坦荡的说说这个东西我们我们那个一定要信这个什么呀,信这个这个缘分,然后呢,你可以给他一个打大点,比如说25个,然后你疯狂的抽,疯狂的抽,疯狂抽,你说哎大家看看那个名字抽的字数比较多呀。

就就他就叫这个名字。😊,好吧,那这事儿就跟你没有关系了。因为你要你你你说你向着谁是不是很难做这件事情,对吧?开个玩笑啊。那么抽奖这个抽抽奖抽奖这个环节当中,其实刚才都是抽出一次性抽出多个多个奖品。

但是还有一个抽奖环节,还有一个抽奖环节,比如你公司年会年会的时候,其实年会,如果通知你,咱们说或者那个年底要开个年会了。你咱们说实话,你是愿意去呢,还是不愿意去。啊。最换这一块。

其实大部分人是就反正有人愿意去,有人不愿意去。其实这个就看公司什么样,这年年会就抽奖抽啥了,对不对?是不是公司一般会抽奖?然后这个场景再再问你,公司如果有500人,请问奖品公司会准备多少个奖品?

如果您会抽奖的时候,奖品数一定会小于什么呀?参会人数,对不对?尤其那个他奖品这分一等奖、二等奖三等奖奖大奖是不是最终就可能有一个或者一个团队或者几个几个一等奖。它一定会小于什么呀?这个这个人数的。

只有这样的规则,人们才更愿意去这个。这个这个年会啊,每个人其实心里都说这这个一等奖肯定是我的,我不去的就浪费了。咱去之前都都是这个想法,对不对?那么这时候怎么实现这个功能呢?

一定要注意PO怎么实现用reis。刚才用那个。S刚我们显示各。run那个memory还适用吗?那么这时候其实你未来设计程序的时候,你要看了数据被抽取成随事件之后,是否要重复让它再出现。

一般我们在年会的时候是这样一个流程,每个人进门的时候会给你一个数字号,对不对?8号、9号等等的?然后那个号有一个副本会放到一个箱子里。是不是放在一个箱子里,然后呢写这个抽奖啊,他一次只抽一个人。

而且还是演这个交替去抽。为什么呀?因为抽奖与抽奖之间要加上什么经理讲话对对不对?然后每个人中奖之后基本就没你啥事的,所以他每次只会抽出一个来,而且这个抽出那个日候正常拿出来之后是不会放回去的。

像使用它的话,它是不会对数据造成增删改的,它只会在这个样品当中往里抽东西,所以它其实不太适合,所以还会有另外一个命令,叫做Stop。🤧S泡这个泡的时候,你可以给出K1。然后这时候会弹出一个。

然后再抽再抽再抽再抽再抽再抽再抽再抽再抽,没有了。其实这个才更符合年会的抽奖的过程。没错,它是这个取出的过程啊,就这。好吧,ok我们小要总结一下。😊。

在随机之前抽奖的时候,有Sme,还有一个Spo。然后这个是取出一个取出一个,一般我们会用的场景是取出一个这样的一个随这个这就不叫这个这个应该也算作随机事件里面。因为它指定抽哪一个,对不对?哎。

就只会抽一个,像上面的时候就是根据这种组不同组合方式,后边你还是我要请你们自己去补笔记,补什么,它有多少种组合方式,就是人多还是奖品多,你想抽重复的,还是想不抽重复的。我课时都讲过,到时我给你写出来。

你要必须回去实操,然后便把这个补上这块由你们来做。

系列 3:P103:【Redis】redis中NIO问题解决 - 马士兵_马小雨 - BV1zh411H79h

三楼。有赛哥。你除了需要这。

哪个不太懂。

这个轮巡吗?对就是你代码里面会写一个死循环。然后呢,你肯定是你了一个sso。然后呢。当那下面接收到一个一个一个一个链接的时候,多了一个就多了一个那个slide是吧?一样一样slide。

我跟你说说说side一样。

起莱的里边。你程序里你用搜消费的时候,肯定拿到了,假假拿到了一个文件妙服,拿到了一个1个8。这是不是别人连接的那个文件面符啊,是你那个要监听80端口时候你拿到一个。然后你们放的这个s选择器当中。

然后监听的事件是as是同意就别人接进来。然后这个时候你现在就循环用中间,为什么要发生轮发生在用户间的轮虽然都发生在用中间,的成本不一样,它是成本不一样的。这边是每一个文件妙符都问一次,这边是循环一次。

我会掉一次slash,我会把1000个文件标传给他。现在第一次的时候你只有一个文件面符只传了一个传完之后,然后他进来内核状态之后,s拿着那个那个8,然后去看有没有这个。有没有这个这个这个连接到。

有到了之后给你返回,然后你就发现。拿到这个8号里边,谁就可以去去接收一个一个新的连接socket一个新的连接就建建立上了。然后这时候你再拿到他的文件标服,然后还得把你曾经那个监听的和那两个再调sag。

然后都放进去。然后一个要监听有没有有没有新的连接到达。另外一个设试状态的时候我要监听有没有数据到达。对吧。然后这时候你第二次录西的时候放了两个,然后只掉了一个s。

但是内盒去给你编利两个是否都有各自的事件。有的时候给你其实有了就给你返回了。返回之后,然后你会对着这两个便历一下。哎,是是第一个接收到了呢,还是后边那个数据到了。

然后数据到了之后调readd来读那个文件面符。如果又一个新的连接,等于现在你先听一个文件面符,两个连接,一共三个文件面符,你再循环是把三个压到这个side方码,内核拿三个有了扔后给你返回。😊,要先。

奇骏理解了吗?就前边也发轮询了,但是拿着一个电标服问一次,拿一个问一次,这是发轮询。轮询的时候,我拿着一批问一次,拿着一批问一次,拿着一批问一次。咱们VIP的课都是有回播的,录播的。

你到时候在页面上直接回看就可以了。一泡一样,一泡也是轮胸的。

系列 3:P104:【Redis】redis中value类型--sorted_set - 马士兵_马小雨 - BV1zh411H79h

最最常用的最常用这个最基本的类型,RA当中是5个。最常用的基本的是5个类型,我们讲了4个了,一个str,然后list哈西,还有set,还有一个还有一个讲完这个类型了。

咱们可以讲后边持有化和集群相关的这个这个知识了。另外一个类型就是有序金。

sing的 size。

不用我老大。然后一个是有戏机,那么这个集合这个农存数据的单元素的哎,无非有list啊,它是可以重复的,然后放入有顺序。然后有s。s是放无数放无这个顺序没有乱放的,然后呢,它还不给你排序,而且是去虫的。

它是去虫的了。这俩都有的时候,为啥又多一个sy side?因为我们更需要的什么呀?数数据被去重了,且它得有多一个排序的事儿。注意这个序都叫序list有序,叫做放入的插入的这个顺序。

这个s side是对元素排序的那个顺序啊,排序那个那那个顺序。Oh。这个用的其实也是相相对比较多的一个外y类型。然后要讲它之前要讲它之前,我们先。会这个引入一些概念,就是先铺垫一下。

你才能对它非常的理解。因为它这个说价格是最难讲的一个东西,最容易让人懵的。首先你明白。它首先是s是集合,明白没吧?集合的话就会有很多的元素。比如说这里面有苹果。然后呢,有香蕉。还会有。鸭梨。就有三个吧。

这三个如果放到一个排序里,你想让他按什么序排序啊?想那按什么序排序啊?想让他按什么序排序。或者想让他们怎么排序。这点很重要,你把这个之点写完白之后,这个色下我给你讲的是好讲了。啊。

那么有人听过大数序或者听我课的时候都知道啊,一说排序就有两个序字典序和数值序,对不对?把这个层次再往上抬高一点,再抬高一点。不是说的底层这个排序这个事儿,你想拿它的哪些属性去排序?跟着我的思路走啊。

Z side和so side是一样的,是一个东西,类型是sy side,但是使用的是Z开头的了,到时候给你解释。跟着我的思路走,你想让他们按说排序,其实是强调的排序的依据。

这个排序的依据可以按照他的名称排,对不对?是不是可以就按照平平箱压,按照名称去排,对不对?这是第一种,就是直接按名称排。这是我啊。第一个是名称,也就是字典序去排。除了可以按这个名称去排,还可以按这个排。

含糖量。可不可以?你是不是就想让他们排个序,然后按照含能量,含能量含糖量是重要的吗?未来你是想看到含能量含量含能数值吗?你也看到是他们的顺序,对不对?含能量是一个隐藏的一个一个一个东西,对不对?😡。

你要ge到这点,虽然在排序的时候,含能量很重要,但是未来你这辈子可能在前端看不到他们的含能量,你只是看到他们的排序了。这一点要能理解了,这个所以下一个你就你就非常容易理解了。😡,🤧那么除了含金量。

还有什么呀?😡,个头大小。价格。然后这个粉丝数就是这个根据全国媒体调查,醒苹果的1万人相蕉的10万人压力个俩人。根据这个这个那个数据是不是也给他们排序,然后前端展示时候。

你可能就是想让他们按照顺序排出来,然后底层的一个维度的东西不想展示。所以一定要明白,就是这些东西是不是有可能重要,有可能不重要。在未来使用的时候,只要你拿着它们能让他们排成序是不就可以了。关系。啊。

吃货热度啊,吃过热度吃货热度。收货。Good的。好吧,很开心吧啊。😊,一定要ge到这一点啊一定要盖这,就是排序规则。提是这个意思。所以这时候如果这个东西你能听懂了,你能听懂了,能盖到这点了。

我再给你讲原理啊,salty set在使用的时候有这么几个维度。第一,它是个set,你就必须得有元素,且这个set它是salty的,所以它就需要有一个维度,叫个sscalecall分值。

第一个他就对需要有一个维度,叫做分值维度。如果你不给出分值,谁都不知道他们应该按照什么去排序。如果不给出分值,因为能够给出的分值的东西太多了。计算机他是个傻子,他怎么知道你是要按热这个吃货热度。

还是按含能量去排呢?所以我们在使用造价的时候,既要给出元素,一要给出分值。能盖到这点之后,再来看。如果先说一种场景,如果分值都为一的时候。你没有给出含能量,什么都没给,你就给出权为一的时候。

这个时候它是按照什么呀?名称那个字减序排的。😡,所以我需求。🤧好吧,4个那么除了。现在除了有分值维度啊,一共有很多个维度,除了元素,有分值。因为它已经是有序的了。那么在有序消集的当中,其实还有一个概念。

就是这个序是正序倒序呢?是按大到小呢,还是按小到大的顺序,对不对?还有一个顺序的概念,其实顺序概念里边就是它的ra排名,排名的话,无非就是其实再说白就是索引。所以其实每个元素它还有自己的正负向所引。

这个东西也正向作用为0,然后负向的话就是负极了,负X。哪一套房子要。然后这个正向左以,然后就是负X减1。然后呢,它正向缩引。正向缩引就是2,然后负向缩引也就是-1。这我直接直接下面写吧,-2。

开照负担了,你要学。所以当把这个图画清的时候,你可以得出几个概念。第一个元素。未来我们在使用超级赛的时候,有一些命令是关注的元素,你可以给出参数的元素,我可以给你排名,给你分值。或者是参数是。

scall分值分数分值。你给出分值区间,我给你取出哪些元素,或者是你给出run排名,或者下调索引。就是所以。你比如索引,我根据索引给出一些元素,而且能带着元素,同时还带着分值。

普通话这个描述的过程能听懂了?朋友们来再去讲这个命令。

没说。这个没当中。一系列的命令都是以Z开头的。那么这时候注意,刚说ras命容命名规则就是取你类型的首字母。像sy赛呢,它也是S开头啊,但是赛当中已经把S占用了。这时候它很巧妙。

26个字母取最后一个拼上这些命令,就这么简单,就这么low。最后一分钟。这个同能理解的同学来双个一。Z side呢就其实就是就是就是对它因为S没法用了,被那个s用了,那有有有有SM的,对不对?

他他就他就得用这了。😊,那么相应的,比如这里面有Z add,就是像那个语形添元素,当然注意看看语法,要给出P。

后边给什么sco members member score member下的时候是只有mem没有sca分值的。但在这这个有序集合当中,有有有序的一个数据当中,你是必须要给出scall分值的。

但是你说了我不想给出分值,它们分值都是一样的。我就想就想让那些元素按照名称排一下,okK全给一。去个一就可以了。就刚刚讲的一个特殊情况。然后呢还可以统一的数量。

然后呢可以Z count给出一个keyme max,然后看s members in个什么s side,然后with scale,也就是说后边其实你给出最小值和最大值的分值数。

然后按照这个分值区间给你统计有多少个member元素,那个数量。还有incre byincrement by就是可以增加一个key的,什么呀?

这个分值就是那个那个那个它的分值给他这按这元素给他加加分值加几。然后还有相应的。range的the range给出一个key,给出star stop,注意上边给出的会出现me max。

这是要给出的是分值t。然后这作为参数,下边如果the range的话,给出的star stop的时候,给的出它的索引或者排名。

所以这时候其实它好讲也不好讲,不好讲,就是因为它比别的东西都多了一个维度多了一个维度。然后下面这个更准确的比如说ze range by score,你可以给出这个分值,因为上面拿的是这个排名索引。

你还可以按照这个分值去取,然后ze one key member。

等能很多玩reremove。然后除了上边这种名称之外,你会发现这样的名称到下边时候会出现一些前缀。你像Z曾经的Z range又带了1个LEV就是反向的意思。

然后run这个the range by score啊等等啊,它又前面带了一个反向。那么这个其实说的什么意思?说的是有的时候我可能是按照正序去去取前三名。正序前三名什么意思?就是小到大这么的一个曲度。

从从小从最小往大哪方取出前三。但是有的时候你是希望什么呀?取倒序的前三名。前三名,你给出索引就是012,这前三个这个这个范围。但是这个数据集是正着取的,还是倒着取有两个方向。

所以它是靠这个命令当中是原命令还是带着R1列反应命令?会这种情况,好吧,你先把这个东西压到身底,压到身底,我们来演示一下。比如说我们增加元素flash。哦。Z and。给出U个KK1。

然后呢给出相应的smesmesme。比如说呃8apple。然后7banana。本单的是这么写吗?然后大气跑。给一个低点的,给一个2,然后三是orange。好吧。得回得回仨就够了,你再多一个。

我都不会写单词了。回车。啊,回收我现在手里得到了一个数据集。其实有序的。那么默认这个树于,这个apple啊,banana orangerange的那存要存的话,其实先说话简单说。

它就存了一个列表的一个方式了,而且它肯定是有序度呗。那么标准的是默认的是从左小右大的物理摆放方式。

这是一句话听懂啊。是上第一个就是物理内存是左小右大。物理内存左小。又大。又大一个顺序,按照你的scocall分值,在内存当中把这些元素拉链式的给你排好了。然后可以怎么看这些元素呢?

你可以通过Z range。

然后给出K1star,然后比如从0到-1来来显示,是不是人呢就排到了第一个,然后第二个是orange3,然后8的话,apple成到最后一个了,还可以带一个选项位置。scorse分值。

就banana是238。跟我说的描述一样,一层一层的把这枝铺上去啊。跟着节奏走,机器的这个大号不容易乱。ok当你知他了,还有一系列命令。刚开始取出相应的所有。如果你想取出的是。嗯。所以。

Rangnge by。spe啊,按照分值去取。刚才是取出了,按照这什么按照索引,按照索引去取的这个元素。那么如果想按照分值去取,那么这么写也可以了,也是给出一个P,比如说给P1。

然后注意win maxax提示的时候就给出分值,分值的话有二有三有8。比如说我想取最小是3,然后最大是8,然后这个范围,那么取出来就是orange和app。好吧,这个理解吧。

然后这时候其实如果说我想取按价格由低到高取出前两名的水果,应该怎么写?价格由低到高取出前两名的水果就可以就就就可以了。那么应该取出别 orangerange呗,那么应该怎么去写?

有时候知识和语义并不是同时出现的,你只要能分控的去就可以了。怎么写啊?朋学们。Oh。难吗?由低到高去取,就取出本来的orange,上周取出所有了。我现让你取出前面脸牙怎么写啊?

Z rangeK1从0到1,这是俩。这不曲分了吗?有时候不要因为老师给你讲了一个东西,感觉一看就好复杂了,你就不会做技术选型,不会不会不会答题了。😡,能看到吧。哎。

但是如果我想按着由高到低取出前两名的水果,要取出apple,然后再取出orange对?那么这时候怎么去写?根据刚才我们这个陈述。旁面有一个特征,什么特征?是不是还有1个REV轮?是不是这样取的话。

取的叫apple和orange。哎,有人说我可以通过Z orangerange后边跟什么呀?-1-0这个-1-2对对。-2-1-2-1。来一样吗?俩一样嘛,你用正向命令从小到大的。

然后取负2取-一取这啥呀?跟我这个这个哪个应该对呀,是不是这个是对的,就是apple它是最大的应该排在第一个orange次大的排在这儿,你这么取还是有小单,有小单,你根本没有改变这个方案顺序。

千万千万要注意这一点。

好吧,那么在这儿演因为演示到这儿,你要知道一点,我为什么说物理内存左小右大且这个东西不随命令而发生变化。就是无论你是正向并流,比如说Z orange或者是ZREV range。它不会随着你使用什么命令。

比如你要使用资源的时候,它物理内层作用作用大。你使用这个反向命令的时候,它给你翻个分转左左大右小。reour是就就这个意思。这句话能不能get到这个点?😡,那么这时候有人就会问了。

那么如果内存不不翻个方向,它怎怎么做到的,它是不是会有一个什么呀?逆向缩引逆向缩引是不是可以从大的往这边去取,无非就是REV的时候,会把你那个。

把你那个这个这个这个这个这个你给出这个这个区间,它翻译一遍。当是取值值的时候,一定是按照这个大小,这这个方案这么这个顺序给你取的。

先举出负一,再举出负二,再举-3,然后达成前这个由大到小的一个前三名。这点一定要注意啊。因为有的时候面试官会刻意在这块难为你啊,或或者或者给你带坑里边去,你脑脑子里只要知着就可以了。

H。那么还可以通过这。rangech,然后这呃。还有一个是Z score。这carK1,然后比如说我们的apple。你还可以通过元素取出它的什么呀?分值还可以通过ZZ rank。排名吗直接run。

最ra的K1,然后apple。然后取出它的排名,一定要记住它有三个东西。元素这是元素,然后呢一个是分值,一个是排名啊,一个是排名。好吧,然后它也支持数值计算。如果它不支持数值计算的话。

这个这个这套这套Y的类型是很难被使用的。比如说像现在然后Zrange,然后我们的K1先从零取到非球一缩有元素,然后with score。Scars。啊 CEO。取出所有东西,然后这时候注意啊。

我想做一件啥事儿,我想将banana增加2。5,增加2。5怎么做?很容易想到,就是Z嘛增加就是increment,然后bu abroad。没有法的,直接直接可以加啊。加谁加我的K1。然后增加多少。

比如增加1个2。5,然后memer是我的banana。回车,然后这时候再用Z run。K1,然后0到-1拿到的再加上这个位置SCO。car。这时候你会发现它的顺序是是发生了变化,orange因为是3。

本来的净值变成4。5了,它俩是完都发生了一个变化,对不对?这位看懂吧?就是说它叫sty了,它会实时根据你给定的分值维护元素的顺序,而它支持这种增增深改啥,就这个增减一个数值的这种操作。

你给出复值就会减啊,你给出复值就会减掉这个值这点很重要,为什么举一个场景,举一个场景。比如说歌曲排行榜?啊,歌曲排行榜歌曲排行榜如果第一天上线,所有的歌曲的分值,排行榜是按什么去排名的。

所请大家来来来来刷一下歌曲排行榜按什么去排名,热度热度的话一个数换成数据是什么呀?下载或者是点击或者播放,对不对?不管怎么样,也会取出其中的一个值,对不对?那么请问它是倒序的还是正序的?

排行榜前十名说的什么呀?是不是倒叙播放量点点播量下载到最高的,对不对?但是这时候这些歌曲从第一天诞争的时候,你准备了一堆一堆歌曲,他们的死高分别看是多少?死高分针是不是都是零或者都是一,对不对?啊。

可以说都是0。哎,某一个人对某一个元素播放了一次,是不是加一。可不可以入我们的Z in incr版。就比如对来的这个歌就个增加一个一可不可以。然后这时候不同的人对不同的元素增啊增增啊增增啊增。

这里边所有的元素是不是他们的顺序在调调换来调纹句,调换来调换去。突然你一刷新,我要看看榜单的时候,他们到最快对实时的速度告诉你。前十的是哪哪些,而且是倒叙。倒叙的话一定是REV这种反向的命令。

就是我们可以用reice根本就不需要用数据库,因为数据库那种对数据的增删这个增加增加这种操作和减减减减震操作会触发事物,尤尤其在并发下,太麻烦了。你用reis,因为单进程单线程。

所有人对不同各类的增或者对同一个级增,他们排队进到的一个一个进程一个限程给。所以安全性的把这些所有数据的变化。而查询的时候,因为剩下自动会也能排序,所以可以快速取位这些数据。

就这么一个简单的一个应用的过程。而且你可以要这个最最次排名榜和最最优排名榜,无非就是正向命令和反向命令。好吧。能把这个点ge特清楚之后。他我们先来说一下,再补一个质。

补补完一个质点就可以讲它这个底层原理了。它是怎么他你要因为你要思考一个问题,它这一直排序,一直排序的成本是多少?或者你对这个集合放了很多数据的时候,它的查询速度或排序速度应该差到合适的位置。

这个成本是是度大用的是什么底层的数据结构类型来完成的这个这个排序这件事情,对不对?

但是先讲一个别的。它既然是个集合,除了这个特征之外,它还有一个最基本的一个特征,也就是它也具备。集合操作。啊,病急或者交急。但是这时候注意你刚才学s的时候,其实交并差机都已经学过了。

size的交并差还比较好好理解,因为它是单元素。但是你在学三s的你就发现这哥们东西太多了,因为两个集合里边可能都出现压力。然后这边的分值可能是一那边分值可能是8。如果做交集的时候,应该把压力取出来。

那取出来的时候是留这个一的差留这个8的,这个分值应该怎么去处理,是加上呢,还是取大取小还是求一个平均。😊。

那么就我在表述啥?😡,朋友们,所以这时候其实两个集格都做交对这个事情,它有一些差异的Z比如说做一个。病例。然后通过它可以因为带这个story可以存到一个目标K里边。然后注意看后边这个所有的命令参数啊。

第一个number case。要给出你参与这个妹,这个这次计算,要有几个可以去参与有几个可以参与,然后权重。权重是一个负数,然后呢又可又给几个。然后这个权重是和你的K按顺序买的。

你比如让第一个K的权重是一,第二个K的0。5,第三个是是一,那么你就要挨个的,你那个你后面写一0。51,你要写的第一个一就对对应第一个K,它们有一个顺序的对应关系。然后这步完事之后,这是一套完事之后。

后面还有一个相应的一个聚合参数s mean max。所以这时候其实当这种有序集合带分值那种这种元素,他们这个就命差的时候,其实更关注的是那些两个集合都有的元素,它们分值怎么处理,可以把分值加起来。

可以取最小值,可以取最大值。好吧,这个位能看懂吧,然后能模拟一版。🤧比如说准备一个Z艾。准备一个K先清下裤。所哎1个K1,然后呢往里贴元素的时候,肯定是scall分值。这scall原始元素。比如说。

80是tom考的分数,六0是肖恩,我考的分数,然后70是这个baby考的分数,就这三人考这么一个分数回车,然后再Z艾。1个K2,然后呢top考了一个。6060吧,胖妞考了1个60。然后肖恩考了1个80。

肖恩考了1个100吧。第二次考试考的高一点,然后后边还有1个40分。比如说一鸣一名老师好吧。He hey。😊,没看到啊,现在是不是两个数据集了。😊,是不是两个集合,对不对啊。

两个集合我是不是可以发生这交集和并级,对不对?😊,然后先放到,你要先给出一个51K,比如说UNK,然后呢后边number case配音量,比是给出这个这个这个这个几个KK的数量,有俩K。啊。

第1个K是K1,第二K是K2。然后呢权重的话啊权重的话可以给可以不给,我们先不给权重走一个默认的。默认的话就是这个两个人的权重都是一,对不对?然后聚合聚合呢我们先不给啊,也先不给。

然后回车得到了一个目标K,然后可以Zrange我们的。这个K,然后给出从0到-1,且看它的权重。不是那个那个那个分值回车。那么。物理内存因优是从左到右的,一个是正向面的嘛,就是从小到大排序的。

第一个是一名,因为一名是一个两个都不存在的,所以它的值是直接存进去了40分。然后babybaby70分,baby也是这边不存在,是独立存在的,就是70。

然后非就是tom跟肖恩tom的话注意它是有一个60分加1个80分。这个你也可以看出它默认行为什么行为,应该重要选项的,是一个什么呀?是一个s的过程,所以会有8060加起来变成140。

然后肖恩的话是60加100是160。能理解吧?如果把上面这个命令再补全的话。比如说加上这个权重,权重的话,比如说第一个人是不这个这个单词录写权重。因为你给出了两个K,所以等它读出两个之后结束。

后边再读出来的那一个数值代表着他们那个权重。比如说这个K1的权重为一,然后K2权重为0。5。然后呢,默认后不险应该是求和,然后呢放到一个新的。碰们一个新的,比如说一个一。上写吧。WEIJATPS。啊。

这就要要写这个N词啊,加这个权重,这只是告诉你要取几个K。然后取完之后还是Z range,然后我们的U这个unic。一、然后从0到-1,然后带着位置。scors回车。那么这时候大家看这个权重是什么意思?

如果这个一对那个K1K1里边的权重,这些分值,它的数是保持原原有不变,所以baby就是70分。然后这个0。5对应的是K2,K2的都要除以2都要除以2,所以40就会变成20,所以一名就变成20了。

然后在计算的时候也一样,比如说t开始80和60,第一个权重是80,第二个因为0。5,所以就是3030加80应该是110。然后我这边就变成了50加60110。这能看懂吗?同学们。一直接20,这能看懂吧。

然后这时候还可以,比如说。😊,不要全重。因为全都带权都算的太麻烦了。然后后边还有还有一个什么呃个rety,然后我们他默认识一个s求和的过程,我还可以求max最大值。回车。😊,车有点出错了。AGGRE。

A。BJ别题。啊后给覆盖了,那就直接写吧。Z range,然后我们的uniK1,然后从0到-1回车,能看到了,然后带上死道分值的。那么这里面是取的一名40,baby70tm取他那个,因为t姆有两个分值。

他们是1个80160,这是其实取最最最大的80分了。然后肖恩的话取的最大是100分。这是因为你带了一个max取值的最大值。好吧,OK这应该都都可以理解,这是做了什么呀?病级,对不对?除了病级。

还有一个所谓的一个交集。交集的话,其实就是取出他们中间交深交的部分,然后不不存在就直接踢掉了。😊,直接踢掉了。

就是它也有一个集合操作。这个操作的命令当时要注意一个点就是。啊,权重。和聚合。这。就是我就是求和求大求小。Okay。O当这个还能轻松中。当这个能理解之后。😊。

系列 3:P105:【Redis】redis中value类型--skiplist - 马士兵_马小雨 - BV1zh411H79h

再来思考。啊,刚才那个问题这个问题是面试当中问的相对较多的一个问题。相对角度的一个问题。都在使用read的时候稍计散的时候。排序。是怎么实现?比就它的排序这个顺序如何实现那么高效,那么快速对不对?

然后以及它的增生改查的速度。这常感的速度快不快呢?速度是一个什么样的速度?其实就是间接想考你它底层的什么权重结构,对不对?这里面注意它用到了一个存储结构叫什么呀?什么时候结狗?Sキバ。Please。

有说这样一个list子。没错,这个例子叫什么?跳跃表。唉,它就是一个跳表的概念。好吧,链表应该都知道对不对?是不链聊肯定都是知道的,对不对?

🤧简单说一下跳表是一个什么概念啊。那么我们先来描述一个场景,如果是链表的话,比如有X这样的元素。然后呢,列表其实就无非就是这样的去一个一个又一个一个一个又一个。我用X代表为知元素了啊。

会有很多元素在个列表里边。但是你如果给它排序的话,排序的话,怎么怎么怎么怎么去把它排除这个序位。其实当有第一个出现的时候,在第二个元素这个的时候,这要跟它比较一下,无非就是放前放后的问题。哎。

第二个元素来的时候很容易理解。第三个元素来的时候怎么办?这个元素来的时候要跟第一个比较,我者比你大呢,还是比你小呢,对不对?哎,我如果比你大的话,我跟后者比比,我说给你大的跟你小呢,放到中间就可以了。

这个非常好理解,最后最最容易实现的。但是随着那个列码越来越长1万个1万个元素。那么你再进了一个元素之后,它可能最大可难度是变了1万次。😊,特别找和合适的一个位置。是不是复担率变高了,就是欧N嘛,对不对?

这个理害吧,那么能怎么能把这个这个事情降低一点呢?😊,有人说二分。啊,二分那么二分的话,这个元素谁是中间这个呀?因为它是链表嘛,它并不是数足。你要找到中加的元素,是外从第一个遍利过去。😡。

同学们们有什么意思吧?那么这个其实各种事间都有复杂度。那么什么叫跳跃表?当列表你知道是一个什么概念之后,其实它是加了一个什么呀,垂直垂直又多了几层。都多了几层,比如说这里面有4个元素。

假设假设我们先给它排好序啊,先给排好序。第一个元素13。第二个元素。17。然后第三个元素是22。第四个元素。145。因为这么四个元素,什时跳一点,其实它还有一上面几个几个几个层次。比如说。

又一个它的出现。这个话其实不太严谨啊。哎,那么又多了一层,一层,最底下那层,就是零层零层存的就是真实元素和那个那个东西,无非就是这个元素曾经在列板里边,它可能只有两个指针,一个指向前面的一个指向后边的。

就有两个指针,指向前指向后。那么在跳转当中,这个元素除了有前后首尾的链表的指针之外,还又多存了一个存了一个其他的一个层次这么一个一个指针。那就是等于又多了一个S3出现在这个位置,然后呢它们之间会相连。

然后呢。这个元素它。出现了这一层后来也多了一个层,这个元素没出现,它只有一层,这有两层这有两层。那么它们两层里边会一个指向。然后呢,还有一个再多一个元素吧,假如这个元素也多了一层。然后它一个指向。

因为只要是一层呢,它们就会连起来。那么显然下面是4个元素,上面是三个元素。然后再往上的时候,可能只有这一个元素。这层再再往下再往上一层,层可有一层或者多层,这个层直接指向后边是一个一个空。

因为莫伟莫伟他没有指向最后那个元素。因为这个层只有两层。那么当这样一个查找的时候,如果有一个随便一个元素,随便一个随机元素要是插着的话。这个元素比如说11。当11想像那个跳转插的时候。

就注意它是在我们的K当中啊,K当中会维护着第一个头还第一个氦它的元素的那个指针。因为跟那个电点一样,从K当中可以找到它它里边是不是有一个每层的一个各层的那个指针那个元素,对不对?

所以这个时候当元素找的时候,是从第一个元素,这个害当中的从最高一层,找它跟它去比较,如果小于它就咣当插就插进去就就可以了。因为它第一个如果大于它看看它指的那个它这一层里边跟它下一个去比较。

来来我一看是缪,那么直接就是这层后面没有,那么这个东西还大于它,那么应该往后差哪个位置呢?降低降到下一层。就到下一分之后,它里边往后只指的是22,所以这个元素跟221比就到就到达这个这个这个元素了。

到这个元素之后发现哦,我比你大我比你小,那我就不用看你后边的,对不对?啊,我我肯定比你小比你小的时候,其实。😊,降到它下一层。就下一层,因为下一层才会有一个指针。向左的一个指针啊。

如果下边还有很多层的话,你就一定要下一层往往往左找就可以了。像现在个比较简单,就到直接到这层,直接到这层之后,其实就是按照这个向左这个指针找前面跟它比。😊,如果比它还小,那继续往前走。如果比它大。

直接把它插就可以了。刚才这个上面一个过程,就是这个我如果你插的时候。找到位置,这步找到位置,就是从最少的那个列列表元素,一层过虑到最终那个最长的列表元素。来这么着,然后你能听懂他的话,就间接啊。

你间接的先听懂一下,因为这个里边还不完整。因为你只是刚才完成了一步什么操作。我找到你在哪了,但是这时候其实我为什么说上来,咱们得直接先造这么一个跳业表。那么最重要的是这元素如果放在这儿。

这元素如果放在这儿的话。😡,他要不要再制造几个层次出来,对不对?😡,最终是不你如果说这个元素只要能插成功,完成所有的插入操作之后,因为你刚才找到它比较的过程,你还非非常容易容易理解。

只要在完成它出现在这儿,且其他从那个那个指向在一搞定,是际是你就你就才能明白。所以第一步它如果能找到这个位置,要放在这的话,其实很简单。

因为它的过是不是来自于它往左找指向它从它身的边你是不是既同时小于它又同时大于它了。所以如果放在这儿的话,要修改谁的指针,是不是要从它里边取出它指向这个指针改成什么样,改成它,对不对?

并把它里边指针附在它身上,所以会出现一个什么效果。在它那个点上是不是会。😊,打出这样的一个效果。这能看懂?同学们嗯,然后它放在这之后,注意我下面给你简单写写一下,每个元素被插入的时候随机造成。

会随机造成,就随机的。我应该这个元素出现在跳表这么多层次当中,我应该是出现一层呢还是两层呢还是三层的。我要不要在未来别人插入的时候,在其他层帮助别人做一个中间左右一个判断的事情。

它会有一个随机造成的一个事情,就是一个随机数,有可能两层用的一层又三层又的四层。当然这个时候根据优化肯定会有一个初始值,就尽量不要超过多少层。这个随机造成这个事儿能不能理解?

就是因为每这里边一个跳转当中不可能每一个元素都是三层。那这等于这个数据放了333倍,对不对?所以一定是什么呀?间接的跳着,每个元素各出现了不同的高度,其实就在牺牲什么,牺牲存储空间来换未来的查询速度。

这句话听同学来说波6。好吧,当这个点能知道之后,其实就是尽量的拿出一部分空间牺牲一下,但是又不是成倍的去拿那个空间去分倍啊,因为你等于你每次都发完之后,最终找找谁还是很麻烦。越晚上这个城里出现的点越少。

越晚上从里出现的点越少,概率越低。所以那时候其实就有点像树的这个这个变利的过程啊,就成本很低了。那么随意造成造成车突,假设造分层。这的四楼啊,假设造了三层,那么它是不是在这儿出现。

它未来在上面是不是也会出现?是不是在这里应该会出现,在逻辑上表述,对不对?逻辑表述时它会出现在三个三个层次里。当它出现之后,如果这些指针都被修正的话,未来别的元素在定里的时候,是不是找他在如果比它大。

是不是找他这儿就可以左右左右判定了。😊,这个结果是这个结果,但是这些指针是怎么找到被修正的呢?😡,因为太森。目前在一,他这边找2。找二的时候,它是不是要向左去涨?😡,是不是像左左去找找到它一看。

它也是一,然后从它的指针接往前找,还找到一个终于不二层了。好,然后在二层这一个节点从按键点中取出指针,这指针可来指要22,对不对?直接把指针指向它自己的这个元素。😡,只要他自己。

并把它里边存的指向22那个22那个那个地址附在它的指向,指向那个指针上。所以这个复杂度就是从往往前找找到一个他需要这个层的元素,然后找到一个层,把那个指针修改去修改它的指针,修改它的指针。

他用的他说不用懂,因为他的地址被他指被曾经被他指用,现在改成被他指用了,所以就是一些指针地址的修修改的过程。😊,改2了,是不是他他是要要要制造三轮出来,是不是一个三吨来?😊,问当前你是不是要三啊。

非有三好找到你了,然后把你的指针指向那个的直接改成指向它。😡,然后并把你曾经指向那个指针那个那个地址放成它的指向的一个地址,就会指向那了谬了。😡,这块耳Q就最最终这三头是不是就出现了?😡,唉。

一出现之后,这就是所谓增成感往里增对不对?😡,说我得插入一个新的元素。哎,那么出现之后,然后如果再出有一个元素,假正再有一个元素,你这时候再来看。就比你刚才听的时不明白了,你只懂怎么你放着了。

假如再出了1个33。😡,这个33往里放,是不是相当于三比角,唉,比你大。😊,跟那个一跳就跳到1一上了,一看哎,比你大,但你没有了,降级。哎,比你大找到你了,比你小okK从下边一层往左往左往左收敛,哎。

比你大比你小放中间再完成刚才那过程。😊,这个流口听得听懂了吧。😡,朋学们。那么有如说如果我想将其中的。我能其中的22。😡,改为爸怎么办?你是不是可以对22可以。

因为它有inin increment by,对不对?可以增正正负数,对不对?哎,我给它减减减到就变成8了。其实你对一个东西修改它的值等于什么呀?把这个元素从这儿P出来,指针重新修正。

因为直接把它的指针交互到这个这个上下游就可以了。然后让它重新走一遍插入的过程。😊,所以只你你你只要把插入这个事儿,这个逻辑能听明白了,是不是修改这个值的过程,你你你也懂了?😡,被告问同学们。😡,没错。

现在在登。开始。因为你你都会往里增了,增之前是不是一个查询的过程?😡,增之前是不是得查,查到之后,然后是不是再完成增的这个所有指针修正的过程。😡,对不对?增山改查是不是都会了?😊,啊。

同学们听懂同学就最终什么跳业表,听懂同学来刷波6。我给你,因为因为的确啊就是你要记住啊,咱们班参差不齐,有人可能这个东西不屑意听无所谓。但是有的人可能是这械表这块还不太熟,对不对?

所以我尽量的给你起一个蒙,注意我只能按照启蒙给你讲,用最通俗的普通话,其实这种描述非常非常不严谨,对不对?😊,啊,不要紧,咱们先按照就着大面的同学,应该大部分这种普通话都能听懂。

知道起码知道它是一个啥事儿了。有兴趣你可以下边。因为你启蒙找起开了,随便找一些文章或者直接看券表论文都可以。你起码就可以看懂里边要做一件什么事了。😊,分层它的分层是一个随我看看到了吗?

新差轮度要不要分层,要不要造层是随机的。啊,就跟投硬力一样。啊,先投一个投成零了那完蛋了,它就不分层投一了。哎,我我要我有一个多多一层类,然后再投一次硬币投成零了。okK我就这一层。

如果再投硬币变成一了,我就我还还要还多一层。😊,最多能造几层层太高也不太好,因为就像树一样,树的深度越深,其实变程度更更慢,对不对?你变得这个这个这个这个斜向斜斜向这个这个这个距离更更远,具体到多少层。

其实有时候是取取决于你的个数据量的。有时候也要调整这个层的高度。如果从。数学特少的时候,其实根本就不需要使用跳跃表,数据达到一定量的时候,才会扩充到变动到这个这个跳跃表。

其实跳跃表有一个另外的一个一个描述,它叫什么呀?叫做平衡柱。啊,它是泪平衡处的。什么叫做平衡处?是不是左旋右旋让所有的所有的深度基本保持一致,对不对?就掺照任何元素的那个复杂度就要比较均匀。あか。

到底增山改查的速度是快还是慢的,注意听这个问的非常重重点。你会发现,如果我就这个元素进来之后就比它大的话,其实这时候你要走好多次,对不对?甚是你转了一个圈回来,对呗?😡,收老理还不如就直接限金便利呢。

这个时候其实说白了它的平均的就是在一定量啊,就是这个数据量比较多比较宽这个表。然后且资格奶查这个操作比较多的时候,其实它的平均值是最优的。平均值相对。最优这总的来看,当很多病发的事情发生了。

就是这这个对对它反量比较多的时候,元素比较多的时候,那么有综有删有查有改。这四个综合来评定它的那个效率,不是只看其中一个,不是只看查询,不是只看插插入。增改都发生一遍之后,在一个定大的时候。

它各种数据各种差插入不同的位置的时候,它的平均的这种速度是最最最稳就是最稳定的。有这么一个概念。相对相对是最稳定的,好吧。okK启启蒙啊就只聊这么多啊,因为你我再聊太多的东西。

刚听明白的同学可能脑子就被挤出了,记忆点东西就就就懵了。所以今天就讲这么多,好吧,对他有一个认识就可以了,觉得很神奇就可以了。我刚才描述稍微有点差异,就是说什么叫做并发并发比说不对。

就是说比如我准备了各种各样的数据。每一个数据挨个进来做增深改查的操作,就各种各种复杂度出现在不同位置的。你为你比如说你增13579准备一堆数据挨个发生,挨个发生。

最终把他们的所有的这个每个人的损耗的时间加起来除一下平均值的时间。然后有增的,有查的,有删的,每笔数据造完之后,拿这批数据对它做为一个压测。然后再拿着别的平衡数,红黑数再做一次压测,对了吧?

那么会发现它的平均值是相对比较稳定的。好吧,朋友们。

ok那么这节课讲到这儿。基本5个歪的类型,大部分的知识点给你讲完了,以及它的应用场景和特殊性,对不对?面试的时候呢应该多说,我让你下去该补的东西都必须要手练实操补上来。

好吧,笔记自己要补。

系列 3:P106:【JVM】课程规划 - 马士兵_马小雨 - BV1zh411H79h

好。我们开始上今天的课啊。OK今天呢是我们JVM的第一节课。首先我来给大家介绍一下呢,整体的课程我们里边包括什么内容,大概呢要上多长时间?OK看这里。

这是规划中的2019年咱们要上的java虚拟机中的内容,内容以后还会更新,只是说现在的。

基本上呢有这么几个大类。第一个呢虚拟机的基础的概念,还有class文件结构。我们今天啊。

尝试就要把第一和第二全都讲完。

第31个呢是内存的加载过程,运行时的内存结构。

第4个,然后第五个呢,JVM的采用的指令。重点是GC和调优GC和调U里面呢会有一大堆的内容,有一些。

预习的东西我已经发下去了。嗯,咱们班主任呢也也应该发给你了,就是我10月16号讲过一节公开课,就是针对于GC和要调优的预习的内容。

调热时战是重点中的重点,这里面的内容呢。

也会有好多啊垃圾收理器怎么选择参数,怎么设置,各种JVM的问题怎么分析?实战GVM的工具啊,还有呢上线之前怎么去进行预规预预预调优预规划。

嗯。由于JYM支识体系呢。是原来都是零0星星的啊来讲。从今天开始呢,我们是把它进行一个系统化的讲解。呃,这个也是一个预估的时间,预估应该也是6次课。不过从以前的咱们的经验来看的话,可能6次课没准讲不完。

讲不完我们就多讲,我们以讲完为基础。不是说以固定的时间啊为为为为导向啊,这点呃不知道大家能不能理解。呃,现在线线下面授的时候,这个时间就是固定的,两天你必两天必须讲完,你不讲完,你就嗯只能看内容。

但是我觉得线上有这么一点好处,就是我们到讲不完的时候,没事,我们可以加课。多建成高炳凡本来预计也是6次课左右,结果实例当中讲了9次G的知识体系,我希望讲6次讲完。如果讲不完,我就加课。如果讲不完。

还有一种就是有一些非常简单的,我需要大家提前做预习。做预习的时候,每堂课之前我会通知大家的啊,不用担心。好,今天呢我们讲两个内容啊,第一个呢是入门,第二个呢是class的文件结构。

系列 3:P107:【JVM】JVM基础1 - 马士兵_马小雨 - BV1zh411H79h

呃。我们首先来看。第一个章的第一章的内容啊,叫java的JVM的基础入门,这里就不是java了啊,是JVM。首先呢我跟大家聊一聊呢,java呢是从怎么样从编码到执行的整个的过程,到底什么是JVM?

看这张图。把我的画图软件打开,稍等片刻。看两组。呃,有些内容非常的简单,我一带而过。咱们java从编码到执行到底是一个怎么样的过程?我们有一个文件S点java已执行java C。

他就变会变成X点class。这个class怎么执行的呢?当我们调用java命令的时候,class会被load到内存好,这块呢叫class loader。会被class load漏到内存,装载到内存里。

一呃,一般的情况下啊,我们。写自己的类文件的时候,也会用到java的类库。所以呢他会把java内库相关的这些个类也要装载到内存里。装载完了之后,装载完成之后呢。会调用自己码的解释器。

或者是及时编译器来进行解释或编译。编译完之后呢,有执行引擎开始执行。整引集呢下面面对的那就是操作系统和硬件了。好,这块的内容啊,这块这块的内容叫JVM。有这样的虚拟机。当然。

有的人呢会把class loader剔除掉,说只有下面这个叫Java虚拟机,这无所谓,只是概念上的一个划分而已。我一直强调概念这东西呢就是人类啊发明出来方便交流,方便说明问题用的。你理解就可以。

不要死抠就没有意思了。这是大体的这个图,希望大家在脑子里能够把这个图呢存一下啊。嗯。java完java编辑好了之后变成class class会被漏到内存。与此同时,像什么string啊、object啊。

这些个class啊也都会被漏到内存。呃,咱们原来老师有会问问一个问题,说java是这个解释执行的还是编译执行的?其实呢解释和编译是可以混合的,特别常用的一些代码。代码用到的次数特别多。好。

这个时候它会把代码呢进行一个。做成一个及时的编译,做成一个本地的编译。就像你可以理解为就像C语言知道呃在windows上执行的时候,把它编译成EEXE一样。那么下次在执行这张代码的时候。

就不需要通过解释器来一句一句解释来执行了。执行引擎。可以直接交给操作系统。去让它调用,这个效率要高很多,不是所有的代码呃,都要呃都会被JIT进行及时编译的。好吧,那如果是这样的话。

那你整个java就完全变成了不能跨平台了。所以。有一些。特定的。执行起来执行次数好多好多,用的用这特别多的时候啊,这个时候呢会进行一个及时编译器的编译。好,这块内容呢叫java虚拟机。关于这张图。

看大家有什么问题。嗯,没有那么继续啊。好,大家看这里。JVM呢现在呢我们可以称之为它是一个快语言的平台。Java叫跨平台的语言,这个大家都了解了。JVM实际上叫快语言的平台,什么意思呢?

作为javaJVM虚拟机来讲,目前能够在JVM上跑的语言特别多。除了java之外,还有scalecalar ,colingrbyclosure,jaon jruby还有好多好多好多。呃,据。

调查应该是100多种了,已经好吧。很比较恐怖,有100多种语言是可以直接跑在JVM虚拟机上的。当然所谓的这个JVM虚拟机,其实它本身也是一个规范。当linux上呢是由linux实现。

unux Uniuxwindows有windows实现likematic,它帮你屏蔽了操作系统的这些底层。好,那这个M虚拟机到底是怎么才能够做到?这么多语言都可以在上跑呢。

最关键的原因是就是因为class这个东西。我们可以说任何的语言,任何的语言,只要你能编译成class。符合class文件的规范,你就可以扔在java虚拟机上去执行。关于这一点。

我相信大家应该问题不大是吧?有没有同学有疑问的?所以从这位M的角度来讲呢,他呢是不看你任何的,不看你语言的。我只要看你只跟class文件有关系。甭管你是谁,你只要变成class,那就是我的菜。嗯。

context各个操作系统都有自己的GVM那跨平台是什么意思呢?是因为呢你写一个java语言,写同样的一个原文件。你的java呃,你在windows上和linux上都可以编译执行,不用修改任何东西。

以前的C和CI加是做不到的。大家伙可能慢慢的已经熟熟悉了java的这个特点啊,已经不再认为它是一个特点了。子明说,其他语言也是编译成class文件吗?是的,必须得是class文件。

不一定是编译成class文件。有的是在执行的过程之中呢。它就形成在内存之中的一个二进制的class流文件,那也扔给操系统呃扔给JVM,它也可以执行。所以JVM跟java是没有任何关系的。

所以这一点啊一定要理一定要理解。就是看上去比较怪异,说java的虚拟机实际上跟java语言没有关系。是的,是这么回事,它只跟class文件有关系,跟其他没有任何。只跟class格式的这个东西有关系。

跟其他的直接的这种语言没有任何关系。所以呢作为张有虚拟机来讲啊,它是一种规范。Java虚拟机是一种规范。它就定义了java虚拟机应该能够执行什么等等等等啊,Java虚拟机应该具备哪些模块。

遇到什么样的质量,该做一些什么样的东西等等。关于这个规范是怎么定义的,大家可以找到oracle的网站去看啊。嗯,每个版本跟每个版本都不一样了。

打开一个orQ网站。Dooxorle啊。拷贝一下。我打开来给大家看看啊。不好拷贝。

这是最新的java13的一个文档。我觉着大家要形成。自己的能力就是你直接去那个。oracle网站上找文档。我这个脾气比较好啊,你要是遇上黄老师的话,是吧?你说文档还要老师帮你找。嗯。

这个事情就不太对了啊,真的不太对。所以以后这个文档的时候,大家也要自己去找,好吧。GDK13的domentation。在下面呃这这这specation这个栏目里面有一项叫language and VM。

点进去。看这里啊,java language and the virtual machine specifications。WYSE13的WYSE12的、11的、10的、9的8的,你自己随便看。

我下载了一份java SE13的,它里面呢说了两个内容。第一个呢叫java language specification,就是java语言的规范。java语言里头哪些语法能用,哪些语法不能用,都在这里。

java SE13里头,你比如说它增加了哪些新的内容啊,在哪看呀,就在这看preview features,它增加了switch呃switch expressions andtext blocks。

当你点进去的时候,你就会看到jaYSC13这它里面的到底增加了哪些内容?switch expressions。switch expression switch block。

我原来曾经讲过那个这这这方面的一个内容,还有一个叫什么呢?叫tex blocks,就是整个字符串可以换行了。OK今天我们不是讲java语言十三里头到底有什么新内容。

我们要讲的是这块java virtual machine specification。所以这篇文档呢才是将来如果你能够阅读的话,应该直接阅读这篇文档。

java virtual machine的规范。这个规范呢这种东西呢一般都是比较的。晦涩难懂读起来比较费劲啊。另外你看啊它有600多页,应该是有600多页。呃,所以你要从头开始读读这个东西。

肯定会特别费劲。但是呢不耽误你直接下载下来,用到的时候去那里查。这个是最新的,2019年8月21号的。所有同学呢老师说老师我跟不上最新的东西,是因为你根本就没想跟上你去阅读过这些网站没有?

有没有业余的习惯,说看看有没有什么新东西出来,都知道这DK13出来了。那么它里面有什么新东西啊,你有没有这个习惯去查一查。其以前有没有不管了,从现在开始,建议大家养成这个习惯。

后面还会有GDK14、15、1617。怎么领先别人一步,很简单,你就去原氏网站查嘛,你不要等着说别人都帮你翻译好了之后,你回来再查,那时候你就变成穿二手鞋了已经。没人喜欢穿二手鞋,对不对?O。

所以GVM虚拟机里面包括哪些内容,这篇文这篇的才是最权威最权威的。我们大家瞅一眼啊,structure of JVM到底包括哪些呢?JVM的结构到底包括哪些呢?

class format这就是今天我们要讲的啊data types。呃,primitive呃primitive primitive data呃 types andvalue是基础的数据类型。

各种数据类型。好,还会有什么呢?compcompiling。编译的过程是吧?helber什呢是什么呢?啊,这这里已经说了class file format。Loading, linking。

initializing。加载链接和初始化。我们现在就要讲的内容,还有呢GVM的instruction呃instruction set。他的指令指令级各种各样的指令啊,指令就特别多了。

这里呢它并没有列出来怎么调优。

关于调优。是另外一个事情,原因是什么?JVM只是一个规范,记住了,调优是针对这个规范的具体实现。好,一会儿我们来讲JVM有哪些个常见的这种具体的实现。翻回头来看,现在来看JVM是一种规范。

这个大家应该能理解了。它是呢虚构出来的一台计算机,JVM virtual是虚拟机嘛?既然它是一个虚拟的计算机,你就可以想象成一层单独的机器。那它有自己的CPU有自己的指令级。有自己的汇编语言。

我们后面会讲java的汇编语言,就是字节码的指令集。它是一台虚拟的机器,它就是有相当于自己是一个操作系统。那自己这个操作系统内存是怎么管理的?我们后面会讲。

系列 3:P108:【JVM】JVM基础2 - 马士兵_马小雨 - BV1zh411H79h

我们来聊一聊呢,就是最新常比较常见的这种JVM的实现。这个这边的实现来讲呢。刚才咱们说了,说这VM呢是一种规范。既然是一种规范的话,那他就有具体的各种各样的实现。这个ATP协议站是吧。

具体的实现也非常多。嗯。定义了一个接口,具体的时现类呢也可以特别多,其实都是一样的啊。这1133三流的企业做产品是吧?二流企业做服务啊,一流企业呢定标准啊,这就是定的标准。呃。

oracle呢就定了这么一个这么一个标准。java虚拟机的实现标准。好,他自己呢也有一些实现。当然也是从s尔收购过来的。目前呢我们用的最多的这个java虚拟机,它叫什么名字呢?叫做hospot。

这我不知道大家了不了解啊,我起一个面航窗口给大家演示一下。

在我们的命令行里头提到加vadown version。

然后你会看到它会输出出来呢,你现在这个虚拟机的名字,我们现在用的这个虚拟机叫什么hospot。

64位的ser版。现在用的执行模式是mixed mode解释执行和编译执行混合的。

1。8版本。这个东西就是oracle的自己的hospot的实现。说其实除了oracle之外,还会有很多很多的实情。呃。

原来比如比较有名的BEABA这家公司是三个创始人的首字母的缩写形成的BEA这家公司呢叫它有一个自己的虚拟机的实现叫ja rocketcket。

曾经啊曾经号称是世界上最快的GVM后来呢被oracle给收呃收购了,应该现在是已经和hospot合并了。所以现在的hospot实际上是原来的jarock以及hospot的合并的版本。IBM有自己的。

呃呃,贾尔逊拟的实现,它的名字叫J9or这个microsoft啊序。微软有自己的时间叫micsoft VM。但不管怎么样,这些实现呢其实都是符合虚拟机规范的。

大的厂商不会说我一会我我我依赖于你oracle,我跟你体量是一样的。我会为什么要依赖你的oracle,依赖你oracle的东西。那如果你要是改的话,或者有一些什么样的东西的话,我我用起来非常的不方便。

另外还有一些版权上的冲突,所以我都会开发自己的。当然也只有有这种体量的这种规模的厂商,才会开发自己的虚拟机。那比如说淘宝淘宝有自己的淘宝VM,它实际上相当于是hospport的深度的定制版。

专门为淘宝准备的。阿里天猫用的都是这款虚拟机。还有的呢,既然他是咱们说现在虚拟机呢,你都是面对于某一个操作系统的,但是我能不能直接面对硬件啊?当然可以。我刚才不说了吗?

虚拟机这个东西本身就是一款操作系统。li VM是值得直接针对硬件的这样的一个虚拟机,它下面就是没有操作系统的,不是windows,也不是linux,只下面直接就是硬件。所以这个效率运行起来那就是更高了。

还有一个比较牛叉的呢,是是他啊这家公司这家公司叫这个应该怎么读呢?叫呃呃a z或者叫a z a a z之类的啊。el他有一家公司,它有一个产品叫Zin,这是一个商业产品。呃,你像hosport。

现在也是商业产品,但是它有一款叫open GDK,它有就对它来说呢,是还还是有这种开源的版本了。但是Zin呢是一款收费的版本,是一个土豪才能用得起的,据说特别贵。非常贵。国内估计只有像那些个垄断厂商啊。

才能用得起啊,比如说银行啊、电信啊,就这一类的估计才能用起,特别贵。呃,它商既然它是商业版本,那肯定有它的自己的一些特点了,对吧?它特点就是什么?快。速度非常快,尤其是垃圾回收。

它的垃圾回收号称是1毫秒以内。挺多时间。那个这个近的。它的一个算法,垃圾回收的一个算法,后来被hospot给吸收,所以才有了现在的。ZDC。不然的话,这个ZDC还没有。是参考的Z里面的视线。

还有很多还有很多啊。多了去了。据说阿里里面就有那么10个人能够自己写淘宝VM的啊。好,所以他们是那个P9P10P10级别,P11级别的这这个级别啊。专家你啊。好,那conex次问的问题非常的好。

conex问说hopot是商业的吗?官网不是可以下载吗?商业的就不能下载吗?我怎么觉得你这个逻辑有问题啊,学程序的人逻辑稍微给我好点啊,商业的就不能下载吗?哎,商业是可以的。😊。

很多的不都说个人他都不收费,或者是收很很少的费用。但是你公司要用的时候,我就收你更多的费用嘛。这种软件多了去了。java收费前一阵子呢。这搞得沸沸扬扬的,所以我专门还录了一段视频,叫做java要收钱。

我该怎么办?如果你想了解里面的来龙去脉,去网上搜一下老师我讲的视频,叫java要收钱,我该怎么办?中心思想很简单,hospot。8开始它不再提供那种免费升级了,谁要想必要八的升级,比如说1。081。8。

2版本升到1。8。3。好像这种时候作为公司来讲,你是要掏钱的。说的是虚拟机收费,不是java语言收费。java语言要收费,ja外语言就完蛋了。是我自己hosport设计的这款虚拟机。他要进行收费。

而果说我不再想免费的提供给你用了,免费还来给你升,级,还给你做维护。麻烦你以后想要这个升级版维护版本向我交钱。所以搬以后都要交钱。如果你要用hoport的话。但是你不用它不就完了吗?

你不是可以用open aDK吗?housebo开源版本吗?里面包含一个hobo的开源版本,对吧?或者是你用淘宝VM嘛,淘宝那个已经说了,这个是免费的,或者是你要用amazon的。实现或者你土豪。

你就买那个Zinex的实现。好了。最后呢,有的同学这由于是同学们的水平参差不齐,我需要给大家呢。解释一些相关相应的概念。这个概念是什么呢?就是GDKGRE和JVM到底是一个什么样的一个关系。

这张图一看你你就应该能看明白JVM叫Java的虚拟机,它只是来执行的,就是你所有东西都弄好了之后,让我来执行。你直接直接把那个。class的各种的东西全部弄好了,扔给我,我来执行,他就干这事了。

那么GRE叫什么?叫rtime呃 environmentment运行式环境。运行时环境,你只要要想在我操系统上运行,除了有虚拟机之外,你还得。你知道吧哪些核心内裤你得有,如果那些内库核心内裤没有的话。

你也跑不起来,你找不着那死 string点class,你觉得怎么跑啊?你找不着object那个class那个类,你怎么跑跑不了,所以。在GRE的范围来讲,要比JVM呃更大一些。

或者JVM呢是被GRE包所包含的这一个叫什么?那除了GRE之外呢?开发的这些个包这些内裤这些工具。好,这个呢叫做。Java的develop kit。JDK它里面包含这RE包含这边。好,关于这个包含关系。

看有没有同学有疑问的,没问题的同学给老师扣1。好了。😊,我呢简单的给大家介绍了介绍什么是JVM。我稍微回顾一下啊,JVM到底是个什么东西。大的范围来讲,它包括class loader。

包括自页码的解释器及速编译器和执行引擎。那么自己自己本身啊就是一个虚拟的机器。有自己的CPU有自己的计存器,有自己的内存管理。有自己的汇编语言。那么它呢是一个跨语言的平台。

只要你能够翻译成为class文件,你就可以在JVM上执行。它本身呢是一种规范,这个规范呢文档在oracle上面,嗯大家呢可以下载下来去读一下。常见的JVM的实现很多种,我们最常用的是hospot。

houses about8以后是要进行收费的,只是针对公司的商用,它会进行收费。如果你觉得买不起,你就用那个开源的。如果觉得买得起那你就买。这酒。IBM的microsoft VM。

是microsoft的啊,淘宝的有自己的VM,阿里好像最近是不是也分了一个叫阿里巴巴VM的,这个我不是很清楚啊,这个可以找他们问问。呃,laker VM针是可以针对针针对硬件的豪华版,你可以买金。Ha。

😊,嗯。那那关于JVM的最基础的内容,我半个小时讲完了,大家看看有什么有疑问的地方没有?

系列 3:P109:【JVM】Class文件格式 - 马士兵_马小雨 - BV1zh411H79h

好,同学们,我们继续啊,我们来讲第二章内容。来点那个classified format。嗯,刚刚才你看到了这这个整个的呃招勋集来说呢,应该是以class文件为核心。这class文件到底是个什么东西啊?

今天我们来分析这东西。我先跟大家要聊的是什么?就是其实我们完全是可以不用分析这东西的。好吧,我说一下啊呃目前在。公司面试的时候基本也不太会面到这方面内容设计。还还没我还没有听说过嗯。

咱们自己同学去面试的时候,说问你这个class文件里面包括哪些东西是吧?这常量池里头有哪些常用的这种常量池结构等等。目前还没有人问到啊呃。因此呢。所以大家学这个东西呢,你当成一个兴趣来学,听懂了吧?

我本人是比较有兴趣的啊,不知道你们的兴趣会什么样子。很多人学东西呢总是有一个。有一个什么公益性特别强,就觉得我学完这东西之后,到底他值多少钱,我就得立马涨多少薪水。你别这样子。

你说读原码读完了之后能让你涨多少薪水,不一定的。不过呢你天天润色这些比较优美的,比较深入的东西的时候,你的思路会变得越来越清晰,变得越来越深入。读那个比较漂亮文章的时候。

你以后写的文章会耳濡目染的变得越来越漂亮。这东西呢是对你自己的兴趣和内力的一个提升过程。得当成兴趣来学好不好?Class cloud format。呃,你学了尤其你学这东西之后呢。

有很多那种你原来不明白的事情呢,你会变得非常的透彻和明白。所以我觉得真的有必要呢跟大家来介绍这方面的东西啊。好,废话不多说,我们来开始。你先说这个克拉文件到底是个什么东东啊,看这里。呃。

这class文件不就是你编译完成之后的一个class吗?你看这个。世计当中的例子啊。这个英泰丽这不会也出问题吧,what啊没有。太过分了。嗯。呃。

我呢你你你们下去啊一定要写这种特别简单简单的小程序来进行测试。大家需要注意的是呢。怎么讲,这虚拟机呢,其实写的程序呢反而变得越来越简单了。呃,原因是什么呢?这个程序比较简单的时候呢。

你更容易观察它的classclass间的结构。大家看这个小程序啊,这个小程序是最简单的小程序。你见过这么简单的小程序吗?啊,平时练习的时候有这么简单的小程序可练哇,那爽死了是吧嗯。好的。

小程序我已经写完了,你不要里为里边里边还有什么东西没有了。public class T0100这东西是我用来排序的,你不用去看白扣01。我们来看看二进二进制字解码的第一个小版本是什么样子哈。运行一波嗯。

没有面方法啊,不用运行。好,今天我们要讲的是什么呢?说这东西编译完了之后,它编译完成之后呢,会是一个class文件。我相信这不用我说。这就是。这个class文件。

当然你如果在inla里面双击着class拉文件,它会自动帮你进行反编译。你看这个反编译版本和我们编译的版本就已经有区别了。看到了吗?就是我们原来的原原原文件的版本是啥样子,就是这样子的。

反编译出来是一个什么样的东西啊,它会自动的帮你加了个构造方法,发现没有?就是原来咱们在讲。嗯。java的这种这种面向对象的时候,就跟大家说过一个原则,就是一个class里面,如果你没有写过造方法。

默认会给你添加一个。好,这为什么默认就会给你添加一个?默认的无餐构造哎,给你加进来了。与此同时,还有一个。注释啊注释不管它,这是它source code的decode出呃呃呃反编译出来的,这个不管它啊。

decomp。那后。我们现在要整的是什么?就是这个class拉文件打开。是之后它里边是一个什么样的内容?其实任何文件打开里边全是010101。我这么说,大家应该没有任何意见是吧?就任何的文件啊。

不管你是PND也好,GPG也好,太TXT也好,AVI也好,打开之后呢,其实内部全是010101。好,这个class文件。如果我们用1个16进制的编辑器来打开。当你看里边的内容的时候,哎。

你会发现呢是这么一个东西。

那么这个工具呢叫slime。Sublime。

不知道大家有没有听说过啊。我我呢。在给大家做笔记里头,把这个工具的名字呢。来利水来了啊。好,这个工具的名字是什么呢?它叫做sline啊,文本编辑器。

你可以用nad也可以。可以用他们的打开来之后,看他们的16进制。好,当你当我把刚才那个文件,也就是T0100backcle01点class那个文件用sublam打开的时候,你会看到的哎。

就是这样的一个视图了。开啡baby0000003400100A00。好,这就是我们那个class文件啊,今天我们最主要的任务就是把这东西读懂。啊,没事,你每天早上要背诵,别人合尚起来会念经。哎。

你每天早上起来你就念这个是吧?DS cafebaby啊,ze,0,0,0,0,0,three, four。😊。

嗯。classs文件是什么呢?它是一个二进制的字节流。在这个class文件里面呢,它只有这么几种类型,U1U2U4U8和infer。其实这个类型也是我们逻辑上分的。二进制子节流没有什么类型。

只有一种就是不是零,就是一。16进制的这种class file有好几种查看方式啊。第一种呢就是我刚才给你大家解释的,你可以用sublime no pad来查看。还有一个呢,你可以下载一个idea的插件。

这个插件呢叫 binaryary啊。indexban editor,这叫hax editorban editor我查一下这插件呢,我已经下载下来了。File settings。

insstoreled啊叫BNN editor,叫banary hextmo editor。hxtcimo的意思呢是16进制。banary呢就二进制,二进制十6进制的一个editor一个编辑器。呃。

这个16进制的这种这种插件呢有很多啊,我是找了这么一个,你也可以用其他的,对就不一定非得用老师这个,好吧。那么当你安装了这个插件之后呢,会有。菜单上呢会多这么一项,哪项呢?

就是fill菜单下面有一个叫open earth binary,就把打开当成二进制的文件来打开。点击之后,它会让你选你到底打开哪个文件,我们打开T0000bycode01点class这个文件打开。

等你打开这个文件之后,好。这个视图就变成了酱子啊,0S咖啡baby0000343434。呃,这中间这块呢是它的一个翻译尝试,把它翻译成字符字符文件。这个有的是能够翻译成字符的啊,有的是翻译不了的。

所以呢有部分你能看到部分字符,其他翻译不了的就看到的都是问号啊。那这个。公寓有一个好处呢,目前我们看到的是hax是16进制,我们可以选啊haxM你可以选成什么呢?二进制。咱们看二进制的时候。

这才是真真正正本质上的东西。011000100等等等等啊。其实我们整个克拉斯文件就是这么就是就是这么一东西啊。那好,当然你也可以看八进制啊,octo八进制嗯,也可以看什么呢?十进制deimmal。嗯。

一般的大家都看这个ht,就是16进制。好,刚才这里讲的这一小段,有没有同学有疑问的,有没有?

讲了个工具。就讲到今天我我们要认识这东西啊,没问题吧。

系列 3:P11:马士兵:不同人群进大厂的攻略都有哪些? - 马士兵_马小雨 - BV1zh411H79h

呃,我就从大厂的整体体系聊,好吧。呃,想对阿里的直级,我觉得拿阿里的职级体系啊。实际上阿里的职级体系呃,跟这个阿里的阿里是双序列啊,就P系列跟M系列,一个是技术,一个是管理。🤧。

其他人的那个直机体系我没有拿。呃,但是我告诉你啊,那个你像阿里的腾讯的、百度的、京东的基本直级体直级体系都差不多。无非就是说这边是L7,那边是P6,就是大概是这个这这样的一个行义,这边是T5。

那边是P6。就这么点区别。呃,这是一个嗯。职级体系它怎么设计,为什么是这么什么就什么这么设计成这样呢?我就不多说了。我主要聊大家比较关心的,呃,就是什么样的人会是P几。然后呢。

他主要是那个那个那个那个呃主要的能力是在是在哪个层面上,好吧。那么关于这个的话呢,嗯你可以完完全可以到我们的网站上啊。就是嗯找到我们MCA的这个课,他的课程介绍里面。呃。

我们在这里呢做了一个自己的非常粗浅的一个总结,但是大家伙可以作为参考。呃,首先我跟大家说一句啊,这个P5是一个什么职金?P5是一个入门级别的大厂入门级别的职金。实际上以前阿里是有P4的。实习生呃。

但是后来P4这个直接就不招了,现在基本上就是P5P5是什么样的人,会是P5呢?😊,呃,按理说应该是0到3年。他们认为你是P5,好吧,也就是说你社招三年以上的那直接就是P6了。但是到在目前的情况下来说呢。

大多数的情况下,作为P5是。你刚刚毕业的应届生。应届生往往是定级屁股。呃,不管你是本科生。也还是研究生啊,我这里头没有提专科,因为专科屁股这个职职级你进不去,好吧。刚刚毕业的应届生,然后呢。

大概在你工作,你比方说你最开始的时候没有进到大厂里面,你进到了一家中小厂,工作3年左右。哎,你社招通过社招进到大厂了,这个时候往往是P6。然后你在你项目组里头慢慢成长为带那么四五个人。

这个时候你往往是P7。当你负责完整的整个的项目组的时候。我告诉你,你这个时候。呃,大概你手底下是几十个人的这样的一个一个一个规模的时候,你大概就是P8了。当你手底下有不同的技术团队,包括业务团队的时候。

你这个时候就是P9了。嗯。那个我如果从呃薪资的角度来说,P5的薪资的话呢,大概是20万到40万左右。那么如果是从呃。P6的薪资来说呢,大概是40万到60万左右啊。呃,如果是P7的话呢。

大概是50万到70万。但是这时候是有股票的。呃,就是大部分PT是有股票的,只有少部分没有。因为阿里有一种文档P7也比较好玩啊,他专门写文档的,他那个薪资就低很多,50万到70万。

大概再加上800到1200股啊。那个股票比较值钱的时候呢,这个差不多P7的薪水能拿到120万左右顶薪。哎,我讲到这儿,有没有同学想想看看那个P7的简历的,有没有?有没有有的话,给老师扣个一来。

3年以上还可以面屁5吗?3年以上你就要奔P6去了,你为什么还要面P5啊,干嘛这么看不起自己?呃。我我我给大家看一个非常牛逼的简历啊,这个是顶新的120万年薪的简历。我找一下。嗯。😊。

这个。呃,这哥们儿当时是29岁,拿到的是阿里的P7plus,它不叫P7,这个叫P7plus,我一会儿给你解释什么叫P7plus。P7plus。那个呃100就是80万的正常薪资,外加40万每年的股票。嗯。

就类似你大概的估算的值啊,120万年薪。呃,你们也可以呢读一读看,看看这个简历呢呃自己能不能照得住。这个简历呢如果你仔细读的话,其实你会看得出来那个。这里面最重要的最值钱的点到底在哪?

5年java开发经验,其中3年以上全是大型系统架构设计经验。三年以上团队管理经验。分布式高并发、高可用大数据量的系统架构设计和研发经验。好了,这是最值钱的。当然,目前政府的什么注册用户多少,日活多少。

日访问量多少,这种的比较吹牛逼的啊,这实际当中的数据很可能到不了这么多嗯。对开源源码有过深度阅读。好,从这儿呢你大概可以看出来P7到底是一个什么样的水平。架构设计原码阅读。

这就是为什么我在课程里面会给大家这么设计的原因,明白吧?嗯,就是老师的课程设计不是说随随便便给你设计的啊,为什么要读读原码读原理?为什么要做架构的设计?其实就在于这儿。就是希望你们能达到这样的水平。

当不是说每个人的薪资啊都能达到120万,不是那么容易的。😊,呃,取法忽上得乎中,取法乎中得乎下,你的目标定的高一点,哪怕没有到,你跟其他人相比,你都是赚的。你的目标本身就定的非常低。

我今天就吃掉一个饺子。你就算达到了,你也就吃了一个。我今天要吃100个饺子。然后就算没吃完,我吃了50个,那我比你这一个也要牛逼的多得多。好,这是他的一些个技术站。这些技术站咱们课程体系里全有。呃。

可以这么说,我的很多的课程的设计是根据。咱们同学们遇到的各种各样的问题来设计的。那个这这这这全是一堆一堆精通了啊,这个你放心啊,呃,其实看上去很难,但是呢不是想象中的那么的难。

无非就是你需要掌握架构的一些个技术选型。是吧当然最新的还有posa啊。然后呢,搜索上的一些技术选型啊,这种那种呃这这个持久化的一些技术选型,缓存的一些技术选型等等。就这么多加上一些底层的知识啊。呃。

他这个呢还没有写算法,写太多啊嗯。其实还需要有有一点算法的知识就OK了。这背后究竟付出了多少?呃。不要不要羡慕别人,我有的时候会说可以拿别人来举例子。但是呢每个人的路啊,每个人的人生路他都是不一样的呃。

你不可能完完全全的复制另外一个人的人生,跟自己比就OK。你比自己更强了,今天我比昨天强一点点,明天比今天强一点点。时间稍微一积累都不用长几个月的时间,你就会发现你已经脱颖而出了。其实就这么简单。那个。

嗯。你们你们你你你们想知道那个那个那个他现在的一个状况吗?这个这哥们是。是咱们。史上最牛逼的一个学生啊。史上最牛逼的学生。你找一下他现在的一个状况。嗯。呃,这里是大概有1000多位我的学生。

然后做的一些个小小的总结和聊天的这个过程。嗯。找一下啊。呃,就是他。Yeah。嗯。呃,这个呢是他那个。最近然后拿了5000万的股票,呃,套现之后然后从公司离开呃,做了一个小小的总结。

就是P7的一些一些一些个内容啊。P7说到底是硬通货,是个分水岭。呃,这里面需要你掌握什么,需要你掌握什么,需要你掌握什么ok。呃,大家可以到这个网站上去访问访问看看啊。

这里面都是很多同学非常真实的聊天啊,你们看看就会知道了。那个。呃,当然还是那句话啊,就是这种呢比较极端,呃,我也绝对不会说奢望,说我们每个人都能达到这样一个水平。

我在他这个年龄的时候也达不到这样的一个水平。好吧,所以大家呢也不要说太羡慕,这个也没也没有意义。但是呢最起码这份简历会给你指出方向来,我们可以朝这方向去吧。

我们今天啃下来其中的一小点是不是就进步了一点点?我说今天我们甭啃别的,我今天啃了一个分布式事务。这东西不难的。咱们一堂课里头呢,差不多你你花个三天,顶多花个3天左右的业余时间。

就能把这搞就能就能够把这个搞定,你知道吗?我们是不是搞定一条?好,我今天不干别的,我就聊一个自动化部署。我今天不干别的,我就把docker给给给搞定了。你想想看这个三天这个5天。然后那个7天加起来的话。

能有多长时间?最重要的是你根本没有必要。每一个都全部精通。面试的时候,我说过了10家乘2家就可以了。不用面面俱到。这大家能听进去吗?天神下凡,对什么学历呃,学历相对比较好。985。浙江大学。

浙江大学是985吧,嗯肯定是啊。当然我说到这儿,很多同学就开始给自己找借口了。老老哥,我是大专,所以我不如他很正常。因此我又可以安心的躺平了。😊,我说我我再给你说一遍,我说他这个案例不是要你跟他比。

而是要你建立起来跟自己比的感觉。你今天要比昨天强一点。以他的这个技术为目标能听进去吗?就是你天天跟比尔盖茨比,那你这辈子永远完蛋,你天天跟艾隆马斯克比啊,你这辈子就别活了,所有人都别活了,对不对?

跟自己比。我今天比昨天强一点,明天比今天强一点。不就成了吗?嗯。能忽悠大钱的背景。肯定背景必须放光,这就是背景背景决定论吗?来我我想问你那个马云背景怎么样?马云985的,对不对?

马云是杭州师范的大专生啊,如果没记错的话。任正非是原来当兵的嘛,对不对?英语老师。对啊。所以。不要找借口,我跟你说,你所有的这些这么说的,其实都是在暗示自己。我没有他的硬件,所以我有自己的不成功的借口。

其实就是这个给自己一点心理安慰嘛。我是种田的对。呃。好了,但是这个就比较夸张了啊,我们讲想想起来了,拿这个举个案例。呃,这是1个P7的薪资。那P8的薪资的话呢,多数人应该是到不了的。呃,到目前为止。

我直接培训的学生里头还没有还还目前啊我跟大家说,呃,确实我还没有能把一个人直接呃学完咱们课给干到P8的。I'm sorry,我这个还确实还没有干到。因为P8呢真的就很难培养了。

他的这个薪资呢大概是200万。就是按照官方的说法,应该是120万到200万啊,这是这样的一个薪资。那么这里面呢就有很多很多的非技术的因素了。技术层面我完全可以让你到这个水平,但是非技术层面我也在尝试。

呃,目前呢也有一点点好一点的那呃好消息了啊。就是这这这这种层面呢也我我也在给大家做尝试。就是课程体系里面,为什么给大家要增加团队的管理课,产品的管理课。

其实呢就是想让大家在你以后的职业生涯里头走到高端的时候,也能够还有空间。呃,到现在为止,我我们现在有一个学生啊,我在我的微信里已经把他给置顶了。我只有一个学生,他已经面了7面了,明白吗?他现在面P8。

他灭了7次了,已经灭完这7次之后呢,还有第八轮的交叉面。就是为什么说那个那个那那个那那个那个哥们说那个我考着面了,面了7次了,还没这个P琶定级太难了,确实非常的难。然后呢,还有最后一轮的交叉面。

因为什么?因为他要求的定级太高了。😊,所以就一一轮面一轮面一轮面一轮面。然后很多人都认为你确实到这个程度之后才会给你这个职级。当然这个职级到来的时候就意味着。200万年线了O。呃,据我知道的。

从京东呃跳到高德的。就是那个有一本书叫一级流量,我不知道你们了解过没有。那本书他的作者就是从京东跳到高德。啊,我当时微信联系他,说给咱们来讲讲课。然后呢,高德实在太忙了。

高德可能是阿里里面所有最忙的BU。然后那个没没有时间讲课啊,不然的话呢,把他请过来讲讲课。呃,从京东跳到高德。大概是据我了解,应该是这个数。400万。好。嗯,所以小伙伴们,你首先要敢于想。

就是你要知道呢这个世界上呢是有好多好多潜力的。你首先你你的潜力呢也不要想那么高,我现在拿12万。好,我明年的目标能不能够拿到18万,听懂了吧?这就是一步一个脚印的扎扎实实的。

今天比昨天强的非常科学的一个一个目标的定级OK。😊,怎么说呢?机会有的是啊,在这里呢。大概是1000多份1000多位的同学啊,好同学说老师,你做假,放心,老师这里头全部的案例要有一份是假的。

10倍学费赔付给你,你随便找。你想找任何一个人说他的那个那个找他联系方式,只要他同意,我都可以给你联系上啊。嗯,怎么说呢?这里面的案例呢,就是不同的人,不同的案例都多的是有顶级的。

我刚才介绍的都是顶级的案例。当然也有呢刚刚入门级别的,我还是一话就是路是一步一步走的啊,比方说入门级别的像什么样子的呢嗯。

这种呢最开始呢原来是拿8000块钱,然后学学4个月给拿到1万14000还可以吧,一年就7万多呀。

这就是学习的收获。啊。当然扯得远了,我们翻过头来再来看看啊,就是什么样的人可以到P5,什么样的人呢?可以到呃P6,什么样的人可以到P7。他到底是都需要哪些哪些东西?呃,我刚才呢给大家讲了一个概念。

这个概念呢叫什么呢?就。P7plus你们这个你们知道这个plus是什么意思吗?有没有知道这个plus什么意思?SSP。其最高嗯。呃,我想问大家一个小小的问题。那个。这里有一堆P6,1233个P6。

我要在这3个P6里面挑一个人做晋升。升值为P7。来,你告诉我谁会升上来。谁会生上来?Who。当然有同学哥就开玩笑了,开始是吧?长得漂亮的。😊,跟。评跟那个考考评官有一腿的。跟考评官关系好的。

首先第一点呃,高级别的晋升并不是只有一个考评官,也不是只有你熟悉的那个。呃,第二1点,长得漂亮跟漂亮,长得漂亮确实有点优势啊,但是呢他肯定不能不是决定性的因素。好好听我说。如果我要在3个P6里面。

挑1个P7出来,那么我一定会找那个优先已经开始做P7事情的人,能听懂吗?我再说一遍。如果我要在一堆P6里找1个P7出来,我一定会找那个已经开始在做P7事情的人。好了。

这个就是P6plus同理那个就是P7plus。就是我为什么说在你们平时工作的时候要多承担一些,多做一些,不要老在那斤斤计较。我给我这点钱,我就干这点活,我多干点,我就亏了。我我是真的遇见过这个这样的人。

😡,这样的人最终的结果就是滚蛋,没有别的。所以。让自己。就是简单说提前一步好吧,来听进去的给老师扣个一。啊。嗯。嗯。讲点儿。嗯。今天感觉讲的比较碎,因为主要我没有给大家解释为什么职级体系啊。

典型的职级体系什么样?嗯,以及呢他的一些个各种的说法啊,我简单跟大家呃说一说。也就是大概是一个什么样的什么样的什么样的一个一个一个。Okay。一个水平吧,就是P5呢它大概做了一些哪些事情啊?

P5大概是这样的,它叫做。诶。职职级的入门就是新兵呃,给你一个模块。独立完成,就是给你个程序。在别人的指导之下,我告诉你啊,这个这个东西要完成这个业务。哎,然后告诉你用什么技术,好了,你能独立完成。

这个基本上就是就是P5,听懂了吧?然后呃作为P6来说呢。就是你独立开发。某一个。这个不能叫模块啊,就是P5来说就是某一个模块的分支,就一个小程序啊,独立完成你自己的一份呃编程的工作。就这样简单。

那么P6呢可以独立完成一个模块。模块级别。那么P7的话呢,实际上就是项目整个项目级别。你可以带领团队来完成整个项目,好吧。呃,基本上大多数人呢是集中在的这三个职级啊,我目前只有一个学生在冲P8。

他冲不冲得下来,冲下来,我会告诉大家,冲不下来的话,我也不会跟着吹牛逼啊。那个。呃,作为P5来说呢,一般来说我刚才说过了,就是应届生。所以呢你社招生呢也就别跟那玩什么这种这种这种玩玩P股了。好。

大家听我说啊,呃在这儿呢我我给大家讲一个比较大家比较关心的问题啊。就是。不是。如何在毕业的时候指定大厂?来有有有有多少同学毕业的时候想直进大厂的,有没有有的话扣个一来。我们说毕业的时候直进大厂。

什么样的人能进啊。听我说,我首先是定义什么叫大厂啊?这个大厂的话呢,我自己的定义叫做一类互联网大厂。大概就是这些百度、阿里、京东、腾讯、字节、拼多多、美团、滴滴、快手、华为、蚂蚁、网易、新浪、微软、谷歌、甲骨文、or尔卡拉。

就是瞎皮小米、amazon啊,当然。😊,呃,如果你还觉得还还可以认为是大厂的话呢,你你也可以往里添加。当然也包括他的一些子公司啊,比如说他投资占比超过10%的,这个基本上长的都是不错的啊。O。

还还还有补充的吗?vivo, I I don't think so啊。vi vivo觉得不算互联网一线大厂。但vivo给的薪资据我所知还可以嗯。对方被加好友过于频繁,请稍后再试。what。

这并发量上来了,应该是。什什么时候你想起来再家吧,好不好?嗯,没关系。诶。难道是并发量上来了吗?哦,有24个。有。24个新好友的申请,等我慢慢通过,通过之后再慢慢再再慢慢加吧。不知。

那个一般来说啊呃大专和三本算一算一个层次。呃,这个层次呢不好意思,进不进不了。就是毕业直进这件事情。不能说百分之百的不行,但是99。99%的不行。但是我会告诉你后面。你该怎么进,好吧,不着急。好。

只要你是二本,你就有机会了。你是一本。90%以上的概率老师送你进去。2119850基本上百分百接近百分百啊,99%的概率老师能送你进去。呃,同学们听我说啊,当然我是需要时间的,你不能说你明天面试了。

今天找到老师,明天我就从送进去,这个这个不太可能。但是像2119。5的这种的,你只要大三找到老师,差不多就能送你进去了。呃,给大家瞅几个案例就成了。看几个字节的啊,我一会儿告诉大家是怎么怎么最容易进去。

好不好?呃,这个是字节。这是进京东了,开始内推实习。那个。找实习吧。实习。呃,实习17K。这是在校的大学生干进自己去实习的。大二升大三,正常的实习生一天400。当然这个实习的工资你也不要求不要要求太高。

最主要呢你是要到收到这种大厂的实习,这是最开心的。最能够打开你职业生涯的就是你从大厂开始。Ooppo的实习啊,oppo只能算我在我看来只能算二线的厂啊。嗯,这是。这是蚂蚁金服的时期。呃,听我说。

如果你学历够,比方说你是一本,你是985211。呃,当你找到老师,基本上就板上钉钉的就送你进去了。而且呢在这儿我也跟大家说一句,呃,我们目前也已经打通了和华为的这个内推内推的渠道。但是华为要求比较高。

他只要985。哈哈。😊,华为现在比较。格调比较高啊。嗯。嗯。那个那个我我告诉大家啊,就是怎么样才能够以实习的方式进去。呃,大家听我说呃,毕业时候直进大场,实际上不能叫毕业的时候,而应该是在实习的时候。

这是最合理的,也是最简单、最安全的方式,听懂了吗?当然。准备这件事情的时候,我希望你是从大二开始是最合适的啊。大三开始呢稍微有点晚,但也还来得及,大四就有点晚了,老师就没有那么大把握了。好。

有多少人目前是在大二大三的,你扣个一,我来告诉你现在的学习应该学什么。为了准备大厂的实习,你应该学什么好不好?嗯,有有大一大二吗?大大一当然更好了啊。对,21985研究生也是可以的,完全没问题啊。

但四了就是得得得得得得看运气了,好不好?但你也要努力啊,你不能说大四了,我就放弃了,也不要这样啊。没关系啊,像是种刚毕业的,我也会告诉你后面该怎么办,年龄大的,咱们往后放放,我告诉你该怎么办。呃。

同学们听我说,作为如果你现在还是在大二大三,最好的方进大厂的方式就是实习,没有别的。这个实习啊是你最容易进去的那怎么样才能拿到大厂的实习呢?拿到大厂的实习,重点看下面这几点。第一个叫做你的专业课。

你认真听就是了啊,第一个叫做你的专业课。专业课有哪些呢?有同学说那个那个那个数数字电路模拟电路啊,和高数no不是。用不着我讲这个的时候,非计算机专业的同学们,你也认真听。你只要把这几门课补上。

你就跟计算机专业没有太大区别。好,第一门最重要的课叫做什么东西?叫做计算机组成原理啊,简称机组。呃,我在讲课的时候是把机组和操作系统混在一起讲,为什么呢?因为机组里面包含了太多硬件的东西。严格来讲呢。

如果说你只是做java的后端,做软件的开发。这里面硬件的很多东西你可以忽略掉的。我讲课的时候会给大家讲一些硬件的东西,但主要是跟软件有关系的啊,但是你像那个门店路怎么设计,门店路怎么组合。

像这种的就没有必要啊。呃,讲讲到这儿那个推荐一本书吧。有有有有没有有没有非计算机专业的呀,有没有?我来推荐你推荐一本书吧。哎,我看我那书在在手边上吗?有飞件的一专页的吗?非机的专业的扣扣扣个一有吗?

就是飞析能机专业,你补计计算机组成原类,你补哪本书啊?😊,有好多书籍的计懂的原理呢讲的太深了。你补起来也费劲。我就我教大家啊,你你大家稍等我一下,我拿一下拿一下那本书。😡,嗯。靠,好找了。

我这书入生的太乱了啊,不太好找,直接说吧。呃,这本书叫做编码。

搜一下给大家搜一下。

OK这本书啊,你可以截图,就是编码隐匿在计算机软硬件背后的语言。呃。呃,所有非计算机的这种这种小伙伴们看这本数据,做那个硬件的入门。听懂了吧。ok。呃,说呢讲的比较有意思,也比较简单啊。呃。

你像我在讲那个多远程的时候,我基本上就是。就是给大家呃过过了一下这个硬件的知识。我有原来讲过一个多线程的内容。大概他里边是讲的这些东西。嗯。大概它里边讲的是什么东西呢?就是这个硬件的基础知识啊。嗯。

CPU的原理就是从门电路啊,就是这些门电路呢到底是怎么怎么组成计算机的这个软件是怎么驱动硬件的啊,为什么计算机一个非常硬的东西,我们居然能够用写程序的非常虚虚的东西去控制它啊,这这件事情很神奇的啊呃。

但是呢你只要把这个把这书大概6啊,你也没有必要说弄懂每一个电路,你就大致能理解整个计算机的组成了,好吧,推荐这本书OK。😊。

当然最推荐的是你听老师讲啊,这个是最省劲儿的啊,你自己啃书,他再容易也是比较难的。好,呃,这是第一个需要你掌握的。我继我我继续写。嗯。实习生啊就是第一个机组。

当然这个对计算机系的来说就就没有什么太大问题了。第二个是什么操作系统。OK操作系统原理OS。呃,这个书的话呢就太多了,我就不专门推荐了。呃,我推荐大家呢,就是你扎实听老师课就完了。

这里面最重要的东西是什么呢?一个是IO的知识。呃,一个是关于呃就是县城或者进程调度,明白吧?当然还有一个呢就虚拟内存管理啊这些。这些个是操作系统的知识啊,这个我专门讲过很长时间的课。好,这是第二个。

那么第三个是什么呢?第三个叫做网络,简称就是计算机网络。啊,关于网络这块的话呢,是咱们课程里的面是阿里的P8啊,林群老师给大家讲的网络的知识。大概从TCPIP开始讲,三次握手四次分手啊。

分组呃这个滑动窗口,这都是这这些个东西都是谁谁考啊。那个腾讯。华为百度就喜欢考这玩意儿,听懂了吧?就这这个都是大厂最喜欢考的东西啊。呃,基本上这三门课,其他的课都可以放弃了。呃,不是说放弃啊。

就是其他的课你学过最好,没学过的话,关系也不太大,基本就这三门课。机组操作系统网络。记下来了吧。这是三门课程,单里面的冬季其实内容比较多。呃,如果让我的话,我还会给大家加什么呢?

mycycl就是数据库的调优,myci的调优。还要给大家什么呢?spring的原码。OK那么还会给大家加什么呢?😊,呃,IO的就是相关的编程的知识啊,就是netty这一类的。啊,当然还有一些其他的。

我就在这儿不不给大家乱加,因为加起来就没完了。呃,原来曾经规划过6加2,曾经规划过7加1加1啊,曾经规划过1010加10加2啊,但是现在呢这些个呢都被我们放弃了。我们现在采用的是什么呢?呃。

现在给大家呃规划的学习,就是每个人不同的学习路线。大概采用的是一种。

是一种是一种这样的方式啊。在这儿也简单做一点儿。

小介绍。呃,大概你像每个人的路线的话呢,都是会不太一样的啊。你要说像他的话,他就应该先学哪个再学哪个。计算机的底层技术先学这个啊再学操作系统啊,再学爱后,再学多线程,再学JVM再学设计模式啊等等。

然后spring cloud相关的这一系列的,它的可以并行学的东西。那么卡不卡该怎么学等等。呃,每个人的话呢和每个人不太一样啊,只需要技术提升,年龄较大,不需要换工作。

技术就是每个人和每个人不太一样的这样的一条路线。但是其实普适性的路线呢也很多,呃,普实性路线呢拿下来的话呢效果会更好啊,就是这个会会帮你涵盖你用到用不到的知识点都会帮你涵盖到嗯。

那个这是这是第一个叫做技术底层。来,我我们继续聊啊。刚才我说了,我说这第一大块。那个作为大一大二大二大三的学生,这是你的第一大块。我把它叫做技术的基础,或者叫技术的底层底层原理啊,技础基础。

那么第二这是这是第一大块,这第二大块。第二大块是什么呢?这第二大块呢是你进大厂的重中之重,也是难点,是重点,也是难点。我一说你应你们应该就明白。重点是什么东西啊?算吧。刚才同学问说社招要不要?我告诉你。

像进华为、金字杰社招这位,就算你是社招。必问。算法必稳。这个是最难的。我这么跟大家说,呃,你像拿北美来说啊,美国来说,美国招招聘一个成员就考什么东西。如果你原来没有经验,就是从学校直接出来。

他就考一个东西。像我刚才说的什么操作系统啊,什么乱七八糟都不考,就考你一个就考算法,别的什么都不考。你就会知道它的重要性了。好,那如果有经验的北美的成语员好,这个时候考你什么呢?除了算法之外。

另外一个叫系统设计,就是我平时所说的架构设计。System。Design。这是要功利的。你没有,就说这两个东西啊是你做不了假的,你明白吗?如果你没有学过,没有了解过面试官一聊,你一定透顶儿。

算法你做得了假吗?你根本做不了假,你说你靠背,你能不搞定算法,这这是超级的硬实力,你搞不定的。华为现在的面试三道上机题,明白吗?三道上机体。全是算法题。你说你靠背不可能的。所以这个地儿就是做不了假的O。

我也推荐所有面程序员的,就应该这么面。他只不过现在面试官有的都比较水,算法都不过硬。所以他面的时候就只能问那些个应用级别的。呃,spring IOC什么原理啊?哎,你背过了okK你就知道。😊。

spring AOP是什么意思呀?OK你背过了,你都知道它的spring那种循环依赖啊,A依赖BB依赖CC依赖A这个又怎么解决的呀?😊,好了,你听过连老师的课,你就知道。明白吗?

就是这种东西是可以作假的。可以背的,就算你不会,你背背也能搞定。但这种东西呢是你不你你靠背你永远搞不定的。呃,这也是为什么我们在课程里头呢就是特别重视算法的原因。呃,这个也。

我我也跟大家简单呃介绍介绍这个算法的内容。呃,你呢?就算你自学也好,或者你干什么也好,随便你啊,你呢就可以。以这个为大纲,好吧,以这个为大纲。呃,大概呢在咱们整个算法体系课里头,一共是分了三个大的班型。

呃,第一个班呢叫新手班,这个主要是算法的最基本的概念啊,冒泡啊,什么选择呀、插入啊、二分法对数器。然后呢,数据结构最基本的概念啊,数组了,哈西表啊,单列表啊,双链表啊,然后二叉数,然后递归归并快排。

这个大概入门级,就是这个级别搞定搞定之后啊,新手班搞定之后呃,正常二本计算机器水平。大概二本的计算机。数据结构一算吧,这门课就学这个。但是呢这个水平是不足一斤大厂的啊,先跟大家说。呃。

那么想进大厂的话呢,要经过体系班的学习。这个体系的话呢,就是从二分法抑或基础的数据结构,各种的规并堆加强堆前缀数。排序二叉树。贪心并察集图,然后呢到动态规划。好,恭喜你到这里的时候,基本到这里的时候。

大概国内95%以上的大厂。就像你开门了。ok。所以各位在校的大学生来搞定到这里,国内95%的大厂啊,阿里了、快手了、华为了这类的基本就想你开门了,听懂了吧?那有同学说老师我想进字节了。

谷歌了这类国际上比较牛逼的这种大厂该怎么办?往后选。单调战。快速密蓄水池KMPmanature莫里斯便利啊,先德数自动机,然后呢矩矩形的问题啊,这个这个有序表卡特栏数四边形的不等式啊,后缀后缀数组啊。

动态规划的猜法。当然除了这个之外呢,呃左老师呢还向大家提了提供了刷题版啊。刷题班的话呢就是各种各样的问题啊,左中右的问题,二叉数的问题。动态规划的问题啊,这种LRULFU的问题。LLRU比相对比较简单。

LFU的话呢相对比较复杂嗯。股票问题、水王问题,月瑟付还的问题啊,完美洗牌的问题啊,像这种种的你做那个呃纸牌游戏的话,这这种是必须必须必须得那个那个那个那个搞定的嗯。呃,利扣的。

150题利寇最受欢迎的100题,今年大厂出现的最新面试题。那个我希望在座的诸位,如果你想提升作为一个程序员的内力。搞一门课就可以,这门课就是算法。而算法这门课呢。是靠突击是最不容易出效果的。

应该是建立在每天的小幅度的练习上,能不能理解?我再说一遍,建立在。每天的小幅度的练习上OK。就是每天你进步一点点,每天了解一一点点呃小小的算法,不要了解太多,也每天进步一点点啊。嗯。这是第二第二个。好。

你们还在吗?还还健在吗?我说的比较慢了,今天啊。还在的话扣个一啊啊,有同学说学过ok不错,学过学过很好啊,没学过的话就学就是了。他不是想象中那么的难。而且你了解了算法之后。

你就会发现当你真正理解了算法这件事情啊。你会发现整个计算机的世界对你来说就是透明的。明白吗?就是当你理解了你算法功力到位了之后,你会发现你理解什么操作系统啊,什么那个网络网络的各种算法了,呃。

是更不要提什么那种ATTPS像这种问题了,那都是小菜一点。因为这个东西。是易筋经。我如说平时啊你们去那个参加过工作,你们练的练的是地躺拳,练的是黑虎掏薪。但是你们没有劲儿。你们没有长远发展的潜力。

明白吗?你们说架构这些知识,那这全是算法。分布式的形容派克索斯。像什么那个那个那个那个呃选举算法呃呃这个这个道牌索引等等等等啊,page rank全是算法。这是你整个程序员的易筋经。gsip不对。嗯。

能记住吗?记就比不记强,我只能这么跟你说。我也不会记录所有的算法,不可能的。但是呢你练过就比没练过要强的多得多。你练过就打开新的空间。当然我这里说的是比较年轻的人,呃,你要是呃年龄现在比较大了。

我就不推荐你在算法上花太多精历了,听懂了吧?所以每个人是每个人不同的情况。有的人我是推荐他要好好学算法,有的人呢我是根本就不根本就不推荐他在算法上下太多功夫。但是你只要作为程序员。

算法是你这辈子都应该去了解的东西。这句话大家能听进去吗?嗯。Okay。一般来说,33岁以上吧。这时候面你的时候呢,多数都不会再考你算法了。所以这个时候呢你就可以呃对算法就只是了解的层面上。

但是呢你就没有必要说呃是动手敲啊或者这一类的,听懂了吧啊,我看有同学问。3二三岁。像面这类的成序员的时候,多数就不是那个特别初级的岗,听懂了?他就呃考你算法的概率就会很相对低一些。

但是我是遇到过32岁、33岁考你算法的啊,一般来说,你想被比较安全的,不被考到算法,基本在35岁以上。而且算很很有意思的东西,为什么不去了解一下呢?你可以不敲,但是你能不能了解一下。😊,好。

33岁怎么突破?不着急,我一会儿慢慢给你讲给你听。然后往这看。那个我我我刚说了,像这种进大厂的该怎么办啊,就是二本的一本的211985的啊,无非就是概率问题,二本的概率稍微低一些。

一本的概率更还要高一些,21985基本上板人钉钉的送进去。好,这是第一个。这是第一个。呃,第一个是底层,我刚才说过了啊,说了一说了一堆操作系统了网络原理了。第二个是算法,我说了,这是核心中的核心。好。

还有第3块。还有第3块。那么这第3块是什么东西呢?这第3块就是应用级别了。这个应用级别的体现,比如说啊你了解过最常用的spring cloud是吧?呃,我了解过现在的这种比较常见的云原声。

应用级别内容就太多了,贼多。你想短期在大学里头把应用级别全部搞定,这件事情是不存在的。这个时候往往体现你的是一个项目的概念,就是你做过一点应用级别的项目。比如说我们为大家准备的。游戏后端的项目。

你说我在校学压的时候做过小游戏,这个很容易就让人相信了。而且呢它的技术含量还很高。😊,作为一个游戏,后端有好多台服务器共同对外提供服务,是不是分布式?作为一个游戏,你是不是得支撑好多人同时在线?

作为一个游戏,你是不是得了解一些算法?ok。所以这个这个小东西对大家来说是一个很很很好的写在简历上的一个东西。Goodら。你可以再写一个应用级别的项目。你比如说商城。像商城的这喜大家喜闻乐见。

我说我练过,我写过okK也可以的。但是你记住进大厂这个东西不是决定性的。进大场决定性的是前面这这前面这两个。这是锦上添花的东西,你可以再了解一些大数据相关的。啊,数据的处理。数据库嘛。

这都很正常的一个了解了解。但是你的主要精力应该放在哪儿?放在这俩上。能理解了吧?来听您趣的给老师扣个一,后面东西就太多了,我就我就不在这儿一一列举了,好吧。呃。

那个后面最后这部分叫做你有多大的精力就学多大的东西就可以了啊。211的三本是啥?211的三本我我不太理解什么意思。好了,这是这波人怎么进到大厂最合适的方式就是实习,实习是最好进的。当你错过了实习。

这个时候就比较麻烦。错过实习,我还想往大厂杀怎么办?突击。这时候就需要你背了。这个东西呢你也不用操心,老师早就帮你准备好。但是这时候概率就一定低好多了啊,就不像原来有那么有把握了。那个嗯。

我们说呃另外一个就是难一些的,就是大专和三本。呃,刚才我说过,我说大专和三本啊,你在大学的时候想直进大厂这件事情,就是直进这些大厂这件事情是不太存在的。大专和三本大部分的同学。在你刚刚毕业的时候。

比较好的是你在大专的时候,哎,能够跟着老师学了学,然后拿到了一份不错的薪资。这个就为你铺就了后面提升的路。就是你第一份薪资会比较好,这是最美好的。听懂了吧?作为大专生三本的学生,你们认真听。

在你刚毕业的时候,应该是追求最应该追求的就是薪水。张老师让一个大专生毕业的时候21K。我可以这么说,3年左右到40K不成问题。这就是差距。第一步你应该追求的是薪水。我跟你讲,为什么要追求薪水。

我一会儿专门跟你说。同学们,我想问你呃,作为社招的人,想进到大厂最合适的时间是在你毕业多少年之后,这个大家知不知道?Yeah。嗯。3到5没错。说的非常对。你知道有些在场特别恶心。三年必须满3年。

不能高于5年,就要中间这批人。你知道为什么?原因是什么?你们想过没有?有但真真真真就这么要啊,你说你第于三年我都不要的,为什么?😡,便宜不是不是不是,也不是便宜。是这样的,第一。

他已经呃因为刚毕业有一帮愣愣头青,你知道吧?他什么都不知道,他就到处乱撞啊。这个年轻的时候呃,你们现在处于这个年龄,你们可能感觉不到。但是在一些比较成熟的人看来,你们好多时候是行为是比较幼稚的啊。呃。

各种思考呢也不成熟啊,刚才有同学问说我才毕业4个月,是不是没希望了,你是要死心是怎么着?难道你毕业4个月不能够慢慢的变成毕业三年是吗?所以就是有时候你们的想法吧。😊,他不是一种正常人的想法。

可以我可以这么说,说的直白一点,不好听一点。你出0到3年对于那些个不太成熟的人,出来就是坑企业的,就是坑人的,你就是男人练手的。啊,那个企业能控能能够控制你控制的比较好,能你能为企业做点贡献。

但是如果控制不好的话,你这个基本上就是负数。但是大多数的人经过社会3年左右的锤炼。他的心智就已经比较成熟了。又成熟又是熟手。然后呢,还没那么贵,还能听话。好了,这个是大厂最喜欢要的年龄段3到5年。对。

把了把你的棱角磨平了,他有些愣头型很愣的,从小娇生惯养,上大学的时候都没有什么利益利益冲突的那到那个企业里头,那真是随便玩啊,各种棱角啊,叮了咣啷的撞。刚感觉出来对。所以在今天听课的有一些还在棱角撞。

是自己感觉不到的,有一些已经出来的。我希望已经被磨出来的同学给给那些个还在棱角里头撞来撞去的同学说句话,好不好啊?拍拍他的肩膀,说,哥们儿。也是过来人哈哈。😊,多听听爷的话是吧?😊。

40万对大厂来说便宜吗?呃,今年腾讯给的应届生。月薪是40K。月薪是35K外加。每月4K的。住房补助。好吧,嗯。鹅卵石有经验,有干劲。对。所以所有的不管你是呃大专生还是三本的学生,或者是你就是二本一本。

然后211985,在你毕业的时候没有进到大厂,现在想进大厂的,拜托你抓住这个时间窗口。听懂了吗?我再说一遍我再说一遍,我希望你们听进去啊。所有的不管你是原来呃学历怎么样子的。那个。

进大厂的时间窗口3到5年,我希望你们能抓住。但是你想比较顺利的进去,他也不是那么容易的。想必我说这进西怎么办?我教大家。😡,我拿最最难进的这两类来教大家啊,您理解了这两类,你作为比这两类稍微强一点的。

你就理解该怎么进了。听我说。如果你是一个大专生。并且呢大专毕业的时候也没拿一个很好的薪水。打比方说你在北京你就拿了9K。我说的是在北京。这肯定是很低的薪水。为什么这么说?你要知道我们线下的保薪班啊。

我们线下有一个保薪班嘛?我们给大专生的保险保障年薪一年是15万。低于这个数,我们是要一分钱不收,把学费退回去的。然后本科生给保障的是18万,明白吧?我们假设你没有参加过任何的培训。

没有参加过任何的这种这种这种受教育,你就自己愣头青,使劲撞撞了1个9K的工作。这个可以吧,没问题吧,这就是不错了。OK然后你怎么规划你进大厂的道路?好听我说认真听。

请你务必在第一年的时候把这个薪资给我提上来。大概你在毕业一年左右要跳一次槽。跟老师学,以后跳槽都要听老师的,我让你跳你跳,不让你跳,你不要给我乱跳。你只要跳槽跳多了,必然会被毙掉。

今天有一同学跟我聊天说,老师我那个大厂呢投了好多,最后呢到呃那个呃我忘了是阿里还是美团到那个HR那了,然后被毙了的原因。频繁跳槽。我告诉你,死在大厂面试上的最弱的原因并不是技术。主要是这个。频繁调查。

所以为什么要帮你规划跳槽这件事情?毕业一年从9K至少给我提到167K左右。这是很容易的,一年时间让你提到这个数很容易的,真心不难。你用16K的工作时间在工作两年,注意在同一家单位。同意点。

在两年的毕业的头上,恭喜你毕进大成。啊,不能说毕竟啊,sorry,就是说进难场的概率高的多的多了啊。呃。然后为什么要提这次薪水?有同学说我9K工作3年行不行?这个概率的话呢就太低了,低好多。呃。

大厂能够让大厂忽略你学历的短板。我再说一遍。能够让那厂忽略你学历的短板。大概有两个层面。第一个层面是你的技术足够牛逼,但是你怎么证明你做技术足够牛逼啊,就是你的薪水足够高。啊。

你最好是进大厂之前25K以上。那我你的学历呢,我就认为哎应该是那个那个那个影影响没那么大了,听懂了吧?第二个呢,要么就是你的title啊,你是team leaderder,你是。技术经理。

你是CTO好了,这个时候别人会忘掉你的学历。啊,不知道我说清楚没有。那大专升三本的学生,有同学说,那我难道使劲我基础过硬的话,我就一是不是一定能进大厂啊?I don't think so。

如果你是这样认为就一定的话,那绝别绝对是有人忽悠你。同样的努力。你的学历比别人低。我就想问你,你凭什么就比别人要强?肯定不行啊,那不应该的,不能够的。所以呢。嗯。建议大家的一条一条线啊。

就是刚才给大家看那个大专生的简历,我不知道大家还记不记得。不要让你的学历只停留在大专上,这个大家是能做到的,也是很容易做到的。呃,哪怕你就是一个网教,哪怕你就是一个那个那个国开啊,国家开放大学的啊。嗯。

就是自考这个都可以,请你往上再拿一个学历拿到本科。就是我讲到这儿的时候,有同学就说老师有很多人还是看第一学历。有没有人这么想?有没有?老师好多人还是那个看第一学历,有没有来有有这么想的给老师扣个一。

就是。这样想的人吧,大多数人呢这样想的就是他的一个最多的想法就是悲观。就是负面心理。就是我永远看一件事情的负面。我不知道大家想过没有啊。那个如果这是能够接纳你的专科的范围,那么你只要你读一个本科。

能够接纳你的范围就扩大了。当然你给人家统招本科,可能人家统招本科是这个范围。但是你至少比你大专的范围要高多了。同学们。最关键是你之前留在这个本科的基础之上,到一定年龄之后,你再去读MBA。

那么很多那个原来那种统招的不知进取的,就已经被你甩在身后了。它是一个长期的系统的过程。是需要你保持终身进步的这种思维。同时需要你规划好你整个的。学习路线和你的职业晋升路线。怎么说呢?就是。你。

完全有机会跨越这件事情。就看你愿不愿意付出这个努力。我们退一万步讲,我们没有进到大厂。我们能不能拿到很好的薪资?我告诉你,我见过的薪资很高的大专生多了去了。给大家教大厂巴哥课的孙老师,他是原来的大专生。

原来进的。京东后来进的新浪,现在应该是60万年薪以上吧我没有去详细问过。35岁的一个女生,做侧开的大专生。在汽车之家100万到200万的年薪。ok。呃,刚才我给大家看那个简历,百万以上年限。

我再给大家看一个原来做游戏的大专生,就是好多大专生呢进游戏行业进起来比较比较方便。这个。这哥们儿是32岁大专生,然后5年经验他是原来从运维转过来。你看啊他写简历就又不一样。

就是每个人不同年龄写不同的简历。就突出这么几项就已经够了。这个在融36060万到70万年薪。ok。这原来做游戏的知道吧?啊,游游游戏服务器的架构设计,跨服跨跨服站啊,做这个的。😊,那个。呃。

再来家看几个大专的简历,大专的案例。就是我就希望你们呢能够建立在现有的基础之上往前进。就是啊你也不要说非得去超越别人,不要这么想。跟别人比是你烦恼的大前提啊,你不要不不要有这种。这种找找自己这种麻烦。

大专的简历,这是掌新的。嗯。PHP转行的掌薪了。7000块钱的。这是学了3个月,二线城市的薪资直接翻番的。

二线城是哪个城市啊?

开工收到offer7到15啊,他这薪资原来相对低。

这是坐标武汉大专的4个月给干了,干了7K的,一年8万多在武汉香不香?点点老师,我涨钱了,太感谢你能们的帮助了。OK。

大专的跳槽的,22岁的大专生,30万年薪的。自考大专工资翻倍的自考大专对日项目。网络的大专生,这是网络的大专。14K以干到25的。大专非科班的24K的。沈阳的大专6。5,干到14的。大专的退伍的。

嗯,这个这个我印象比较深刻,这哥们是错过阿里入职申通,为什么叫为什么给错过了?哥们儿在面面申通的时候,阿里给他打了8个电话。

啊。阿里三面的正在四面的时候,打了两次8个电话都没接到,都在面申通。

好了。

属于属于倒霉啊。这个是大专学历的多家大厂的offer。

经过三周面试,收到不少offer。真是想不到大专学历的我不在那些中小型公司喊我去面试。

呃,请你们听我说。就是学历这件事情在你们来说已经不可改变了,那怎么办?加强其他所有的硬腿,把能夺硬的全全全做硬了,听懂了吧?然后机会。到来的时候,你就有可能抓得住。听进去的给老师扣个一,好吧。啊。

扯起来没完了,这个外包能去吗?来,同学们外包能去吗?每每天都会遇到这样的问题,老师那个外包面了一家公司啊,中软国际这个能去吗?我都有点不能。工资高就去,还有同学说。各位同学们,我觉得问这种问题的呢。

就就是我我我我再推荐大家一本书叫批判性思维。批判性思维。呃,这不是输了,就是一种思考方式。同学们听我说那个。呃,你你们了解批判性思维的本质是什么吗?就。批判性思维的本质。

好多好多人说说我看到一个想法的时候,我要怀疑他到底对还是不对。我要做一个对对对,杠精啊,这个哈sK说的特别对啊,杠精。批判性思维就是杠精。但实际上这不是批判性思维的本质。批判性思维的本质叫做批判自己。

注意不是批判别人,是批判的自己,是你自己有某一个特定想法的时候,一定要多方印证。好好考虑一下自己的想法有没有什么纰漏和bug。是批判自己的思维。大哥。这杠精是批判别人的思维。

所以好多人把批判性思维这件事情理解错了。所谓的外包到底能不能去?我就觉得特别好玩,问这问问出这句话来的人都觉得特别好玩,你知道为什么吗?😡,我就想问你为什么不能去?难道去外包会死人还是怎么着?

所以这句话本身问的就有问题。所有问这句话的人都被我怼回去。我说你有没有其他选择?听懂了吗?假如他说我有一个外包中软。我另外还有一个东南亚的。机会,那我应该选哪个?那我外包能不能去,你得这么问。

你有没有其他选择?如果你只有一个选择。不要提外包啊,你就是凤姐,你也得老老实实的该进洞房进洞房。好吧,但是你有两个选择,一个是凤姐,一个是杨超越。那你该选谁?老师给你提建议。好,不开玩笑。

我们说外包这件事情到底能不能去?当然能去,为什么不能去?外包的很多很多人的这个呃。他进大厂之前的经历就是外包。那还需要你建议。😊,万一有人选凤姐呢,对吧?😊,嗯。外包当然能去啊,就是有好的外包的话。

他做的项目也是非常不错的。外包的技术也是锻炼人的,他的技术也不是白给的,天天还加班是吧?给的工资又低,使劲让你加班,你说你的技术能不练吗?得使劲练。听懂了吧?所以可以去,但是能能不能去,其实要有对比的。

就是你有没有其他选择,没有其他选择一定要去,为什么不去?外包有方方面面的形式,比较有名的,像中软了、博彦了这一类的。其实好多大厂也是认可的。当然还有一些。比方说有一类外包呃,华为的OD。德科。

这大家知道吗?多个就住住不知道。嗯,华为的欧弟现在华为的社招,不好意思,都从德科走。华为是要你想进必须先进欧D,必须先进那个那个外包OK。外包能不能去,当然可以去,为什么不去啊?

多个选择的时候再来问这个问题,好吧,不要歧视外包,外包没有问题的。它的好多的技术用用的技术跟你真正的甲方没有区别啊。最重要是技术过硬。就完全可以去。华为社招不是停了吗?呃,准确的解读,我给你解读一下。

华为的社招现在什么样?想认真听的给老师扣个一。我给你准确的解读华为的社招。华为手得现在是这样的。嗯。第一,应届生没有停。985。常呃,那个常春腾好吧。第二,5年以上的没有停,就是那些高端稿没有停。

技术专家这种级别的没有停。停的是什么?0到5年大现111到5年这些。那么这些如果想去的话,先去德科。先去欧D,然后OD呢每年有百分之。多少的机会进到华为本部,忘了啊,大概是有百分之几十的概率进去。

听懂了吧嗯。权威解读啊,因为我们刚刚跟华为达成了协议。

合作协议啊,给他内推。来。老有同学说我现在年龄大了。

今天聊一个大的话题,就聊最后一个吧,就是你年龄大的。我跟你说,年龄还大,技术还差,管理也不行。空间已经被挤得非常的小了,我该怎么办?哎,同学们有没有这其中有一个或者多个问题的老师扣个一,好吧。😊,嗯。

对。嗯。年龄到有多大?你们。来来来,各位各位认为自己年龄大的敲出来,我看你们有多大年龄,3033、34、22、22,你搁那扯淡呢,46嗯29。😊,2825。4934、43。okK好好好,呃。

同学们那个36岁以下的,你就别跟我这聊,年龄大了,好不好?那个年龄还很年轻很年轻很年轻啊。😊。

呃,我们长远别别的我就不跟你说什么褚实践啊,不跟你说什么呃邓我们*也也79岁才主动中国,对吧?然后就不跟你说,任正非40多岁才创立华为,还差点破产,对不对?那个那个那个马云CS才30多岁。

就是你正当年是正当年的时候,麻烦你不要放弃啊,有好多人说我35了,我以后怎么办,感觉就要死了似的,以后就得去开滴滴开饭馆了。大哥远远不是这么回事。😊。

呃。呃,课程底型面有两位老师啊,我推荐你们去听一听,听听一听,跟跟他们跟他们交流交流。😊,呃,首先第一个是讲这个课,就是大型团队管理的P8课,它本身就是P8。然后呢那个。现在是3十八九岁了。

应该快接接近40。好吧,现在依然是在那个团队里头担任很核心的角色,然后年薪依然是那你牛牛逼的很啊,这就不不跟你说了。然后这哥们是已经40多岁了。OKP9P9的老师已经40多了啊。呃。

目前呢在那个也是一家大厂,我就不说他的那个那个那个背景了啊,就是你离开阿里之前P9,然后到新的大厂之后,担任更加牛逼的角色,还是这句话。就是我最最开始就跟大家说过一句。

年龄大这件事情一定如果你现在有危机,一定是你原来规划的不够,学习的不够,提升的不够,这点大家能认可吗?如果你学习够了,提升够了,你现在具备了你这个年龄的人应该具备的水平,你怎么会没有空间。

他一定是有空间才对。当然有同学说,老师,我已经这样了,我下面该怎么办?首先调思想。你还要一定告诉自己,我还有的是空间。哪怕就是这对你来说,这个鸡汤它也是一种正面激励。嗯,我再加一个年龄又大,基础还差。

管理也不行,空间还小,还是女生有没有?感觉没有年轻人的活力了。还是女生。对。

看你个小案例看你个小案例啊。我找找找几个女生的案例。女生进入美团。拼多多。😔,京东。这是35岁的40万年薪也干到了70万。还可以吧。其实35岁呢很年轻很年轻的啊嗯这个这个超级印象深刻啊这课。😊。

这个是38岁的这个这位这位这位姑娘,我们是印象超级深刻,因为是给她费了太大的劲儿了啊,才把她给带出来。但是她带出来,她现在很牛逼的,她不仅跳了第一次槽,现在又跳第二次槽。

然后还嘲笑当时他们项目组的人特别弱,你你明白吗?😊,呃。这是他当时的肺腑之言,我当时那个还还还挺感动的,非常感动啊,说说这句话,就是老师的成就感就在于这儿。特别想择公开课的时候。

多影响一些人职业生涯中尽快走出迷茫。但是人家会以为我是托啊,暂时只能忍着。😊,如果你觉得你的比他还差,那我就也就没什么太大脾气了啊那个。怎么说。这个是39岁的大龄的成序员。呃,我首先给大家一点啊。

给大家做一个就是大龄的小伙伴嘛,给大家做一个做一个呃这个这个这个小小的建议,你们一定要听进去啊。嗯,大龄大龄的女程序员。嗯,记得应该有一个。这是大龄成员34到50的。嗯,因个有1个40多岁的啊。

大龄的大专生,大龄的跨行成序员。疫情的嗯。有1个40多的,点忘了是四十几来着。43。そ3万。还有1个40。四十几岁的来着。

啊,这个这个。呃,这个姐姐是44岁。女成员,然后收到外企的offer。那个。这这是他他搞定工作之后呢,也是肺腑之言啊,我希望给大家敲响一个警钟。你可以不跟老师学没有关系,但是麻烦你保持进步好不好?

这次找工作时间提醒提了醒,不会再温水煮青蛙了。呃,他的这个。怎么说呢?他最后啊实际上还长了新了,我不知道大家看看出来没有?鼓励一下那些大龄成员,我43岁女生,薪水跟大厂不能比,生活工作更拿了外企的研发。

薪水差不多,选了这个OK。我问他就是那个薪资达到了预期没有是吧,我说达到预期了。

怎么说呢?你相信我一点,就是当你开始正视自己心态放正。然后呢,放积极了之后,开始改变自己之后,你一定会有收获,这个收获可能会大可能会小,可能你自己没有长,甚至没有长薪。但是呢你是不是心态上已经放好了。

人是一个很好的心态的,人这一一辈子就这么几十年呢?你保持一个很好的心态,也是一很好的一种收获的。但是你只要心态好了,好多事情就会变好。你不信你试试看。那个。嗯。作为大连的小伙伴,我给大家一个建议。😊。

我我不希望大家伙。呃,年龄很大的同学,三十八九岁。找到我说老师,你能不能给我找条路线,让我进大厂。大哥,这是这这是这是非常难的。老师目前规划了好多好多人进到大厂。这个确实是。啊。

我们我我们就从这里面搜大厂的名字,你就你就能找得到啊。就比如说你就搜。阿里。嗯。这俩是55353个呃,阿阿里的就是我们公布出来的啊,搜字杰这个叫12个,然后搜那个那个呃呃美团。这是36个啊,搜。

京东啊43个,就是说其实呃进到大厂这件事情,在一个合适的年龄,合适的背景的情况下,老师帮你稍做规划,稍做指点你就进了。但是呢有的人是强人所难,他非得说我学历又不怎么样,然后技术积累还不行,现在年龄还大。

三十八九岁四十多了。老师,你能不能帮我送进大厂?如果你送进大厂,哎,我就报我就报名学习。你别跟我这扯着淡,你爱报不报?你行就行不行就不行,你不行,你报了也不行。你行的话呢,老师判断你行,他他就。

概率就高的很,就一定能行。呃,同学们听我说那个理智一点啊,如果你提出这样的要求来,说明你没活明白,三十八九岁了还没活明白,你这是人生的失败。这时候你应该对自己的最理智的说法是一个什么样子的,认真听。

应该是建立在题心上。提高收入上。这是最简单的提升你生活质量的办法,就是提收入。当然还有一种呢就是你追求你下一步的呃更好的职业的规划。比如说我想进外企,我想进到甲方企业。

我想进到那个非IT类的这一类的企业里头去。然后考虑我后面养老的事情了,这个也很也很务实,也很科学。也也相对靠谱一些是吧?提收入这件事情,老师有的是办法啊,你年龄多大,老师也能够找出办法来。

能让你把收入提上来,这是比较简单的,不难。可以这么说。报名马士兵教育的还没有说薪资涨不了的。😡,就是多少的事儿,少的也是5000以上啊,低于5000的就太少了。时间维度3到6个月左右。还可以吧。

打个牛逼出来好吗?😡,没有一个啊没有一个到不了说说完完不成这个任务的。嗯。那个。怎么说呢?就是你你把你的当你把定位定位在题心上的时候,呃,老师办法和手段就多了去了,好吧。哪怕就是让你搞点副业。

你也能把薪思提上来啊。当然前提是你要保持正向的进步的积极的心态,这样才可以啊。嗯,做出改变。有一些那个年龄比较大的小伙伴啊。每个人的情况跟每个人的情况不一样,所以年龄比较大的时候。

我就没有办法找到那种普世性的东西了。就是没有办法说我给你一个像那个呃那个那个计计算机系的这种这种学生啊,这个呃本科的这种二本的、三本、二本的、一本的这种的进大厂的路。

我们是没有办法找到找到这么一条普适性的路的,这只能是每个人的问题,每个人分析。啊。对,当然这这个就比较麻烦了,麻烦一点,好吧嗯。进大厂不也是为了钱吗?我觉得你这个人生的格调,麻烦你稍微往上提一提。

不然你这辈子会活得很痛苦。钱是赚不完的,也是赚不够的。有多少钱你永远也是够不了的。你如果只是钉在钱上,那我觉得这就是你将来痛苦的根源。呃,让你这一生活的充实一些。格调高一些,你会发现钱是自然而然就来了。

好不好?把你的目标稍微定的高一点点啊,信贷厂的目标是什么呢?实际上是为了你更好的一个职业规划职业的学历。啊,就是职业的职业的一个经历。你的你从大厂出来之后,有好多中小厂抢着要。给好多钱也也要明白吗?呃。

给大家看一个内推的11个1个一个小案例。内推呢我一般都不怎么给大家展示,主要是什么呢?呃内推这件事情并不能够让大家伙儿说我降低学习难度。注意这是两回事儿。呃,这是自自杰找我们做内推啊。

最近找我们做内推的其实已经非常多,就全国的一线大厂,呃,我们都有都有渠道内推。这个不是说那种吹牛逼的啊,就老师这儿不跟你们。

吹这种不靠谱的牛逼。这是我们大概3月份那会儿疫情还没有这么严重的时候。

我们跟那个呃微软AMD和京东联合举办了大学生的编程大赛。然后呢,这个呢是我们在给京东做培训。呃,这是呃编程大赛的现场。然后。在3月份的时候,我们和小米和百度还有京东啊,京东当时没有没有没有来人。

因为他们疫情不允许出来。当时就在我们的现场啊,我们自己公司的内部现场做的招聘会。呃,有的人呢应该是参加过啊。就是内推的渠道呢,老师这有一大堆一大堆一大堆的。就是你想进哪个大厂,只要你水平够。

我判断你水平够。这个内推的渠道非常的通畅,但是前提是你的水平要高,能听懂吗?所以内推呢我一般不太使着劲儿的说我们有内推,我们有内推之类的。我不一般不我我一般不会说这个。那个怎么说呢?

他不会降低你的学习难度,你也不要指望着说你学习的程度不够,老师能把你推进去,这不可能的。一定是建立在你硬技能过硬的基础之上啊,我刚才说的是什么呢?我刚才说的是当你有了大厂的背景之后。

像这一类的非IT类的大厂,那给的年薪是相当可观。罗湖地产年薪150万以上。team leader的年薪120万。你说他是IT类的吗?他也不是谈工作会很累吗?也不会很累。但是你你要是有大厂的背景。

我是美团出来的,我是阿里出来的。我是和他这个比较相关的。比方说ERP拥有出来的OK这特定相关了,就属于。OK我是平安出来。好,你就有机会能够到这种企业里头拿很好的年薪了。

这是年龄大一些的人的另外一条比较不错的路线。不知道大家听进去没有,作为咱们年龄大的小伙伴啊。我就在直接上直接上班。嗯,那咱们离得很近啊。我在进门桥。你如果是在防洪中心这边。

那我们直线距离就两两三百米哈哈嗯。老师,联想可以算镀金吗?我个人认为不算啊,联想。I I don't think联想是一个镀金。我在学院路这边那离得很近啊,可以过来呃坐坐。聊个天喝个茶。

子杰最近离职了不少。呃,我们曹老师跟字杰的人大概住一个楼,住的比较多。嗯。TME算吗?TME是谁啊?银行算吗?嗯,银行的用的技术其实真的一般般,所以不能算。科技公司参观吗?可以啊,我们搞线下活动啊。

因为近期的也在规划线下活动,只要疫情过去,呃,我们会找一些咱们大厂里头的高P啊,P8P9P7这些人来跟大家做见面会啊,你就会知道呢深入的了解就是他们的职业发展到底什么样子的。

并不是所有人的学历都特别好啊,呃,我给大家讲那个架构设计的老师,曹老师吧,他就是二本的学生。呃,黄老师二十四五岁,今年是25岁了。黄老师25岁。呃,离开美团的时候,85万年薪。牛没有逼?

这就是技术牛的人啊他的一个他的一个。可以达到的宽度,好吧。TME啊腾讯音乐酷狗K歌。哦,这不就腾讯吗?腾讯当然是大厂了啊。25岁对,25岁。想看看他的简历吗?他当时到阿里的时候是24岁嗯。

大概是60万年薪,那会呢嗯。嗯,打开来看看好吧。呃,我我我隐蔽了一些他的那个隐私啊。当然他这个是属于纯硬核,非常硬核。OK非常硬水。超级硬啊。这个全是基本全是精通。嗯。怎么说呢?他在大学四年。

没谈恋没谈恋爱。没有出去玩,不打游戏。就学习了。听懂了吧?所以他付出努力了,当然就会有收获啊。他二十四五岁的时候,比我二十四五岁的时候,那牛那那牛牛逼多了OK。哎呀,怎么说呢?就一分耕耘,一分收获。呃。

老师能向你提供的,就是让你少走弯路。讲到这儿呢,其实我们的课呢,其实我介绍也差不多了。我就不专门做什么特殊的广告了。

呃,简单说,你想提新的,你想进大厂的老师早就帮你想的方方面面都已经非常透彻了,你也逃不出那1000多人的案例里头去的,你也没那么特殊。想多找点薪水的,今晚你就扎实来来找老师就完了,好吧。呃。

几句话介绍晚上的活动。然后有一些需要跟老师交流的,咱们就瞎聊瞎聊会天,好不好?简单几句话接说完。

双十一的活动。今晚报名的,然后。跟那个跟那个跟那个呃今晚报完名,然后跟明天的抽奖,明天等着抽奖就行了。大概的话呢,一等奖是个什么东西?任天堂的游戏机,二等奖是哈曼卡顿的音响,三等奖是一个电脑桌升降的。

那么四等奖呢是一个西部数据的基械硬盘,无等奖啊,不念了,你们自己看找丨小丨姐要就是了。然后呢呃价格上就是这个价格。如果你觉得这个价格能让你一年涨个几万块钱,只当投资的话,你扎实来。还有很重要一点呢。

呃我们送出去的VIP的卡,这里面最重要的一点是1元升级的权限。这个呢。双十一过后,我就不打算再送了。就是1元每年的升级。这以前我们定价是18881年。当然这个有点贵了。

所以我们后面呢为了促销双十一的促销,1块钱一年升级费用。呃,每年呢新技术你不用想那么多,跟着老师做就可以了。老师来帮来研究新技术。只要你。技术当中遇见了,先来老师这里查一查有没有讲过啊。

对你的职业的生涯的助力巨大。嗯,后面的话呢,我觉得最少的收费也得几百块钱一年,好吧。不可能只是按这个价格给大家改下去啊,当然这是双十一的福利。呃,11个名额,今晚就11个。找老师来做规划。

来报名就OK了。好啦。在这就。不多多废话了,我们聊会小天啊,准备结束。今天啰里吧嗦的聊的东西比较多。嗯。讲的有点啰嗦。主要脑子里东西太多,一讲的时候吧,就容易发散。讲到一个点呢,哎想到一个案例。

就想给大家说说讲到一个点。想那一个案例跟大家说说就就会比较多。啊,这个东西呢叫知识的诅咒,就脑子东西太多了,明白吗?所以讲东西反而讲不清楚了。脑子的东西就一个一加一一说就清楚啊。

当然跨越这个知识的诅咒也是需要慢慢来的。老师一定能跨越。老师咱们网站的自测的题,麻烦赶紧添加哈哈。😊。

呃,需要人力。一步一步来啊,我看有有几个小同学看看他的一个情况。

呃,28岁的男生。硕士上海4年,国企四年30万80技术20管理,晋升搅慢,想涨型纠结,确定不了下一步的发展方向。那个首先呃第一点要判断一下你在你们原来的这个企业里头有没有下一步的成长空间。那如果没有了。

要就要考虑跳。那跳的时候呢,呃由于你已经在国企4年了啊,这个呢。你也你要想像你这种的啊,如果想进那个呃一线的互联网大厂,这个基本上属于板上钉钉的事情啊,就是百分接近百分百啊。无限接近百分百。

假如说你现在这个30万,你想拿到60万。啊,大概给老师的话,也就也就需要半年左右时间,不会超过这这个这个年限啊,明年34月份左右就让你进去了。呃,但是呢你得自己呢做出决策,有老师能提供建议啊。

就国企是比较清闲的。呃,你拿这个年薪能不能去接受一线大厂的苦?啊,一线大成的卷。那个或者你就甘愿在国企里面拿一个比较低的年薪比较清闲,这个是你自己的选择,能理解吧?嗯,而且。你需要嗯就是你需要很多细节。

我就在这儿没没法没法说太多了,就是基本上帮你送进送你进一线互联网大厂的,应该是玩似的,很轻松啊。

啊。

呃,32岁的男生,本科大连20万。5年其他语言3年。对日。呃,对日向想要懂一些,但是不精。那个是这样的啊,那个如果你想呃提薪水,其实我觉得你这个年薪啊好像在大连还是不错的。呃,提薪水的空间有没有?

当然是有这个是需要看机会了,骑驴找马慢慢找着,把技术提上来,你的机会就多了,就是这个意思。😊,呃,但是。你你你你你你说你这个满足于对日,我觉得就有点不求上进了啊,就是对日的话呢。

你应该知道他好多技术用的非常的古老,而且特别的死板。它跟好多那个技术的主流都格格不入的啊。你这个的话你不追求技术上进,那就啥也不说,你要追求技术上进的话呢,必须得搞点新东西啊。

呃,对日的这块儿。我找找我们有没有对日的小同学。这是一个自考的大专生啊,对日项目12K到23K继续30K的规划录,它是是不是也是不是也在大连,我忘了,因为大连对日是最多。嗯。就是你你提的目标不太明确。

你如果能提出明确的目标来。😡,比方说我给你举个最简的例子啊,就是大连嘛,全国的城市里头啊。呃,说这个又又又想多说了。你们想知不知道就是全国的按照IT薪水的排名,全国城市的排名是什么样子的,你们了解吗?

如果想了解的扣个一好吧。Okay。我告诉你啊。这个跟很多人想象的可能不太一样啊。😊,他们听我说啊,排在第一的薪水排在前面的叫北上深行啊,北上深行。而且这四个的排名基本上就是1234。没广州什么事儿。

没有广州什么事儿啊,呃,第二个呢第二类的城市就是二线的城市。所谓的二线啊,就是基本上可以算上广州了。广州、南京。然后据我所知的话呢,厦门应该这个薪水也是蛮高的。啊,珠海这几个薪资都都是蛮高的。

都可以给到比较不错的薪水啊,珠海。那个这算是二线吧,然后你像呃武汉呃成都。这个武汉成都。那个像什么无锡啦,苏州啦呃。然后这一类的吧呃基本上再往下排一节。然后你像大连。大连、郑州、济南呃,青岛。

然后石家庄呃,西安呃,就这一类的OK再往下排一级。不知道大家能不能理解。所以大连呢。他是这样的啊,就是凡是处在这个层面的,就是三四线往后的。我我可以这么说,不吹牛逼的说。

就是老师这课你只需要理解个50%到60%。那么在这个城市里面。排名在前5%左右的。这个岗位所需要的技术你就基本上全部涵盖了啊,比较简单。But。嗯。所以你要想提薪就简单。就看大连那边有没有机会啊。

有机会的话呢,你就去去去拿这个机会就OK了。呃,我我记得我们在成都就业的挺多的嗯。这个啊这是成都的海康威视,30万年薪左右。成都好像最近的薪水还可以啊,有一些大厂的嗯跑跑过去了啊。呃。

这个成都年薪涨了20万很牛逼吧,就是他本身年薪涨了20万,他不是说年薪是20万啊。

成都翻了倍了,5K到10K这太简单了。嗯。这是呃比较老的一个学员,就学了spring cloud成都18K的offer。

当然还有一些我记得武汉武汉也不少武汉的小同学。武汉的薪资的话也好像也也还是不错,这是涨了4K。呃。从12K干到了20K在武汉。那个30万年薪在武汉呢。呃,四涨了7K的大连的话,我忘了有没有有没有啊。

大连没有,sorry没没有案例嗯。咱基本上像什么沈阳是不是有啊?沈阳。这个应该那个跟大连差不多吧,呃,涨新涨了4。5,坐标是沈阳。那个这是6。5到14啊,就是怎么说呢?东北这一带呢薪资偏低。

所以你32岁拿了20万年薪,他差不多每个月18K多点。啊,其实还算是可以的,你明白吗?所以你要想追求更好的薪资,首先去找你们城市里面有没有这样的工作机会。如果有老师就一定让你把技术达到,听懂了吧?😊。

呃,两年半大专23学历低,但是想尽在产,不知道怎么规范学习。刚才我已经说过,专门讲过大专怎么进了。呃,你呢应该第一步提学历,建议你提上来。呃,但是我觉得你薪资还可以,还是很不错的,不要轻易跳槽,补技术。

然后大概半年到一年,我感觉啊我直觉上因为你中间很可能是跳过槽,我要看你跳槽的情况。如果跳槽跳的不是很频繁。补学历补技术,你就有机会了。但是这个机会我绝对不能说百分百的保障,听懂了吧?

但是你这个年龄呢还是很给力,比较给力啊。

你去就是路线也很简单,补学历补技术,你就有机会了啊。

就这么简单。27岁,贵阳2。5年。也有接触过最近面试的为微服务,那你就扎实学就行了。像在贵阳来说,就是贵阳那边提供什么样的薪资,要还你还是本科,贵阳那边最高提供什么样的分资呃。

这个这个这个呃薪资老师就一定让你把技术站给你涵盖到。嗯。

当然贵阳薪资肯定低低好多啊这个。嗯,没什么可说的,没有办法。嗯。嗯。大连的双非本科8K。希望进大厂学习年薪40万,你年年跳大厂年应该拿走多少薪资。你首先大连有没有大厂啊,应该没有。

所以你应该是要从大连出来。呃,你从大连出来8K的话呢,在你跳大场之前,我是希望你能够拿到18,至少是18啊。人为本科没问题的,学历够。拿18工作个1到2年,然后跳大厂,然后到40万不成问题,听懂了?

因为我前面讲的比较多了啊,我就讲的直直直接一点,好吧,行就行,不行就不行就算了。37岁,40万1年10年。不提了,大专70万保险中介。呃,这个呢应该是有点嗯,因为这个大连的小同大龄的大龄的小同学。

就大连的同学呢。我我得透彻理解,了解你原来的一个背景啊,然后你跳槽的一个情况。呃,如果说你原来还算是比较稳定。我就觉得特别奇怪,你37岁了,没想着把这个学历给提上来嘛,就说你这个原来。

原来的规划就是有问题嘛,对不对?嗯。刚才说过啊,你要想在整个的。你的大龄的人要想要想突破的话,尤其这个大专背景的话,要么就是你的技术非常的过硬,一定是架构师的级别。到不了这个级别。

你就不要提齐专一年肯定突破不了。那么要么呢就是你走管理岗。但是你管理岗的情况怎么样,这个不好说。嗯。所以怎么说呢?嗯,作为你来说。提交够。然后。提学历。然后提管理恐怕你都是要面临的问题,听懂了吧?嗯。

当然啊你只提架构,其实呢从你现在薪资也也能涨上来,这个是没问题不大的啊。因为现在架构师给的薪资还是蛮高的。但是我说的是你长远发展这三个层面,你恐怕一个都避不过去。不要认为我37岁了,我就可以放弃了。

我我我这这辈子就这样了,不要这样啊,有的是机会。

嗯。提学历提技术,就是提架构架构层面啊,我现在就不给你提算法了,算法对你来说意义就不大了,好吧。

具体问你具体分析啊大龄的小伙伴呢,我得看你非常具体的背景。青岛31岁,1万块钱,三本本科突破25。呃,青岛的25就是顶薪了,所以你要准备技术就行了,这个倒不太难。那个我们原来张富刚老师,他就是青。

他就是青岛的,他离开青岛之前就是25K。呃,在青岛那边的惠普。呃,但是青岛的25K好像就是顶薪。你可能得去什么像海尔啊、海信呢,像这一类的可能都得是很好的一个薪资才行。嗯,所以呢你技术过硬才有这个机会。

技术不过硬,你可能没有没有这个机会啊,把把架构补上啊,你到你到青岛现在这个程度就是补架构,补什么架构呢?

我告诉你啊,说到架构呢,我也跟大家多聊两句。呃,就是在整个课程体系里面。呃,在。资身架构师应该掌握的技术体系啊,这里。就这部分是我们下一步的一个重点,也是你将来的重中之重。我虽然把它放到了新增里面。

但是我认为这部分呢是所有人都应该掌握的东西。这是你将来做架构的基础,这个东西就叫做云原生。当然,云原生的内容相对来说比较多。我们自己像我们自己的这个平台,就是搭在云原生的基础之上是华为云。

华为云上相对便宜一些。呃,然后呢有一部分是搭载了阿里云,阿里云比较成熟一些。你一定要理解整个云原生的架构,这是叫未来的架构。可以说,将来你所有的架构师都避不过去的东西。是必须要理解的。听懂了吧。

那么你在青岛的话呢,呃要理解这些个对青岛当地的IIT人来说,可能相对关念稍微超前一点的东西。那么你就能领引领整个你你你你的整个薪资啊。嗯。

成春。21128日本读研躲一情回来,找到工作10K以上。大哥,如果你给老师个3个月左右,搞不定不能3个月,有3个月刚好过年,过完就过完春节。你你给老师点时间,如果让你搞不定。

这个薪资老师一分钱不收你的OK。你扎实来啊,一这个一定搞定的。如果你愿意走出长春,老是90%以上送你进大厂。

你这个太简单了,学历又好,背景还不错。就算你以前的底子再弱。你只要听话,老师都有办法让你提上来啊。

27、男生,本科16,深圳四年涨薪,不知道学什么写的越多,老师规划越详细的,你没什么可说的了。你这你这27岁的正常的薪资是多少?最少25K以上吧,所以第一目标拿到25。这简单啊,就几个几条线就让你到了。

第一条线项目线。spring cloud现在比较流行的项目。

可能网约车项目就一个网约车项目就让你干到这个这个这个薪资了,这个不吹牛逼啊,就是你把这一个项目搞定,很可能就就到了。😊,哦,有人说。这是应届生平网约车项目给干到了21K的offer。

这哥们还是一大专我印象比较深刻。呃,这是小白拿网约车面试了15K的。

你才16K。这是网约车涨到了那个涨薪资涨了5K,原来是25,现在30。学了几个技术点,薪资翻倍的。所以你你这个真心不难啊,这把几个点拿下可能就够了。二本 urban本。浙江明年。嗯有更高的见识。

不了解基本只了解代码。呃,你现在还在还在读书吧。读书的话,我刚才认认真真给你分析过,在读书的话,怎么杀进大厂。基础底层外加算法是你避不过去的这两个是必须的,重中之重的。然后项目大数据都是你的加分项目。

呃,细节比较多,我刚才已经透彻分析过,就不再多说了啊。你如果你忘了,你再找丨小丨姐姐拉小群跟你聊吧,好不好?Lavender那些13万。😔,其他职业1。5年培训一下,只外开发一年。

河南科技一本刚入职华为外包,职业规划有经济大场。你已经进华为外包了,你下一步的目标不就要进华为吗?当然有机会进那场了。你华为我不是是不是德科呀?如果是德科的话呢,呃我就直接告诉你啊。

华为的那些考题我们都是有现成的,123456,所以扎实练技术,练算法。然后呢目标进进华为就OK了。因为西安的话,大厂好像也不多。就好像像阿里华为也就你就这两家吧啊。

所以目标就是就华为就OK了。

24岁3年11,哎呀,你这个薪资太太太,中大厂呃,几科本科二本。你听我说啊,半年涨到22,如果到不了老师退你钱。必道。你这你这太简单了,我我我都不知道该说什么了。有好多人呢可能对我说这话,他老不相信。

他说那个老师,你凭什么一排板,你就能知道我就一定能突破这个数。

没什么,因为我们对可能太自信了。😊,像这种的太多了,你明白吗?你这个毕业12刚毕业12K了啊,像你这种涨幅的薪资呀,就太多了啊。十几K涨到二十几K的啊,我就直接告诉你啊,这个就是贼多贼多的。

以前12乘12,现在18乘21北京。😊,就很普遍的啊,他不是不是说一星半点的那种案例,就是拿5000万的那种案例,不是这样的。😊,呃,9乘12跳槽24乘14。上海。所以像你这种薪资涨起来。

那真的是太简单啊。你而且你学历还够啊,二本我都足你运气好,送你进大厂了,都长这点心思跟玩似的,你这是来就是了。北京物理本科M毕业刚毕业43,年薪3130到40K电信计费。核心经历开发技术没有提升。

不够系统,综合主任能了解。呃,你现在要想清楚呢是。你应该是走向技术管理岗,这个不用说。如果你现在还在跟年轻人拼一线,你也拼不过,你也没前途。所以在这个年龄,你这个年薪。相对比较可怜,我我有什么讲什么。

所以你下面的充的东西一定是技术管理岗,听懂了吧?技术管理岗。那么技术管理岗呢,这里面有两个大的层面了,一是你需要了解整个比较新鲜的架构的知识。你如果不了解的话,你根本也管理不了。

然后第二个呢就是基本的管理的内容。这2块加起来就是技术加管理。就是以前你你不要认为技术管理岗是技术转管理,是技术加管理啊,这两个层面搞上来,我觉得你是有机会能够翻翻的。到60万年薪是问题不太大。

因为你刚刚MBA也有了,你技术上再补上来,等于技术加管理就有了。好,这个时候你的空间就打开了。你其实最最吃亏的是你43的才拿31万,就是你以前肯定是。我不知道你在干嘛,应该是温水煮青蛙。

或者没有从来没有抬头看过路,世界已经在发生变化了。3亿万的年薪。很多刚毕业的小孩就直接到了。嗯,赶紧突破吧。30万年薪一年半,哎,这才比较正常嘛。本科。估值因为目前已经在估值百亿美金左右独角兽了。

明年年初50万。那P6还没有两年经验,这个问题也不大,你这个问题也不大。第一,背景很好。然后第二薪资到位。你所缺的你所欠缺的无非就是技术了。那补基数这件事交给老师就完了。让你补啥,你补啥就完了。呃。

你不到两年稍微吃点亏,最最晚最晚明年90月份也也就让你进去了啊。以下一步就是这些个超级大厂了吗?很简单很简单。这个已经看过,这个真真的很简单。这个都可以给你签对赌协议,你到不了就一分钱不收你的。

到了就多付我点钱。呃,29岁安徽。目标是40万。3万多吗。在上海。半年公司两年打酱油,银行外包已经3年,也就是三年没有跳过槽。是吧。😊。

这是你的亮点,恭喜你。你已经具备了。杀进那个。我刚才所列的一线大厂的机会。呃,如果让我挑一个进一进一线大厂的人,一个人呢是他技术特别好,但是跳槽特频繁。

另外一个人呢是呃他的技术呢相对一般,但是35年没跳过槽。我一定挑那个没跳过槽的。那个没跳过槽的人,想送你进大厂,要相对容易的多,补技术相对容易,补你的职业规划。我告诉你没有几年调不过来。

不计术这个从我们以前的经验角度讲啊,就基本上就是3到6个月左右。像这种是4个月了。这是学三个月的。呃,不需要你把所有东西学完啊,这是学4个月的。这是包了220天跳出外包了。哎呦,我去11点了。

我们还聊吗?明天要不明天聊。听我说没有聊到的呢。你要愿意也可以跟老师单独交流啊,这关系不大,老师的微信号。累了。你老师40多岁的年龄,讲这么长时间课,实际上是有点累的。

老师的微信号。就B一。

呃,这是第二个微信啊,因为第一个微信已经满了,所以就第一个微信就不再加了啊。嗯,有机会加应该是有点频繁。通过一下。对,但是我回聊天回的比较慢啊那个。有啥想聊的,你也不用客气,就直接留言就行。敲蚊字。

微信的最基本的。礼仪。敲文字,你敲文字,我可以说语音。这个都懂吧。微信的最基本的礼仪,不要问老师在吗?这应该都懂,对不对?我可以在可以不在。这个取决于你到底跟那儿聊啥,问什么?😊,有点频繁啊。

明明天加吧,没有关系。

Yeah。5年15K太可怜了。22830克金弹厂3月份最迟9月份呃,问我我问题不大小小意思。

但是深圳的大厂啊没有北京和。杭州上海这么多。嗯,我希望你能。😔,定出一个明确的来啊,就是深圳那边你能接受的大厂有哪些?据我所知呢,你应该接受这几个。呃,第一个呢就是腾讯,第二个呢是深圳有阿里吗?

好像也有吧。然后呃虾皮。lazada啊,这东南亚的这几个电商给的薪资非常的高。呃,好多时候比那个列的这几个一线大厂给的薪资还高。像目前为止,我们进大厂的这些小伙伴啊,薪资拿的最高的呃。

实际上是虾皮和拼多多。不是你想象中的啊阿里美团。是虾皮和拼多多。

老师有技术问题不明白,你直接发这最基本的礼仪跟这儿老师我有问题不明白,然后啥也不说,等着我问你是吗?我就不理你。南京30。5年经验17K还可以。呃,专科生的本科不错,专业是汽车,不错,专升本嗯。

项目不大,提升技术,涨薪资想就大涨。嗯。我看见你们小进大厂这几个字儿其实有点头疼,你是涨薪资这几个字比较简单。呃,作为南京来说。找到你南京的大厂。

主要是南京呢没什么大厂。这是头疼的点。我还是那句话啊,像南京这类城市呢,基本基本上前10%吧,老师能够让你把这些技术全涵盖掉。呃,但是呢你说他没有机会,老师也是真没有办法啊,就没有办法。

就巧妇难为5米之炊。南京的话提薪资不是问题,好吧。哎,这是涨4K的。原公司涨了3K,坐标南京。北京到南京14K涨到24K,这个还还比较牛逼吧。

原来在北京拿14,跑南京拿124,年薪30万哈哈。😊。

南京专科生了嗯。3个月南京18到30年薪40万还可以吧啊。呃,南京上海啊,听我说南京、上海,然后苏州呃这几个城市呢,什么样的东西相对于可以拿比较高的薪资。架构师的体系里面一定要加入大数据啊。

对于大数据的处理。这个是你在南京、上海、苏州拿高薪的挺关键的一个点。特殊情况只想在合肥,合肥30万年薪有点难呀,大哥。正经4年。我只能说让你拿到合肥顶薪。二本本科现在已经18K了。

我只能说老师能想办法帮助你在合肥拿到顶薪。但是合肥顶薪是多少,这件事就不好说了。29岁在合肥,你应该补下面这几个技术点。呃,面试常问的这个啥也啥也别说嗯。这必须得必须得得得掌握的,大概有10项左右。

然后呢,合肥这边。呃,你要稍微领先一点。基于云原生的分布式微服务。听懂了吧。因为我知道那个呃合肥应该是有大数据中心吧。也是云的一个基地。这块的机会应该就会你只要把这块搞定了之后,呃。

应该你会机会多好多好多。怎么说呢?就是前沿技术吧,跟上前沿的技术,跟上流行的技术。嗯。😊,行了,通过差不多了啊。

25岁的男生,大专生10K武汉,这个挺典型的。呃,三年提高薪资提薪的话呢比较简单啊。嗯,像你这种的。保守说最保守最保守的明年3四月份16K以上,不知道你能不能接受啊。呃,我看啊技术水平有限。

前沿技术了解不多,被框在了Mm行MES什么什么行业。成熟框架哦,我知道了。三年以来技术没贴上,偏业务针对MS。听我说啊呃,首先我给你做一个短期规划,呃,短期来说就是提技术,就你只要提技术就提新了。

这个肯定可以,完全没问题。那提技术主要提哪些个呢?你自己呢也说的非常的明确了。第一个叫做流行的东西,你现在不太了解。所以从我们整个的学习体系来说,spring cloud这条线。

spring cloud这条线到网约车项目。这个就是从传统的CRUD转向互联网的关键的点。这个好多人已经证明了的。然后第二个你用的全是成熟框架,你从来没了解过框架的底层。所以第二个读框架的源码。第3个。

从长远来看。提学历,你把这学历给我提上来。第4个,从长远来看,我希望你养成一个学习算法的习惯。对你将来的职业发展巨大的好处。然后至于架构的话,慢慢聊不着急。所以很简单很简单,你就可以把薪水提上来啊。嗯。

猪小屁。

嗯嗯。学习算法有什么书推荐吗?呃,你要看书的话,我是真心推荐你看咱们左老师的课程,他讲的可比书讲的好听多了,你自己啃啃算法,你就知道了啊。如果说你非要看书啊,第一本书呢叫。

java数据结构与算法这本书相对比较入门级,相对浅一些。但这本书已经停已经那个呃。停板了,所以你可以找到电子书java数据结构与算法啊,我不写了。呃。这个第二本书就不推荐了,因为第二第二本书太难了。

算法导论那本书太难了啊,对于很多专业搞算法的比较难,所以就放过他。呃,你把这本书搞定呢。像国内的这些个普通的厂子,呃,这个携成了,什么马蜂窝了,五八了这一类的搞定没问题啊。嗯。

7年多25K成本314年想换工作什么好的建议慎重。嗯,建议很多。首先第一个不许轻易跳。你这一跳呢应该是非常关键的一跳。因为你已经在这公司4年了。在这公司四年就意味着你对这个公司很坚定的忠贞。

就这个不不频繁跳槽。就算你学历稍微差一些。也会有进大场的机会。所以你这一跳一定一定要跳好。做好准备,骑驴找马,找到马之后再跳,不要轻易跳,千万不要说别人给你个什么3035,你就跳了,那你就亏死了。

这一跳目标40K以上。补40K以上应该具备的技术,然后目标就是40K以上,概率很高。上次有同学跳槽。原来拿12K,别人给了15K就跳了。我也是快疯了。我基本上直接建议涨幅不超过50%的就不要跳了。

意义不大。对你职业生涯是个伤害。啊好,通通过了一波好友啊。

java数据结构与算法是不是数据结构与算法分析java言描述,不是就是java数据结构与算法就叫这名。但是那本书比较老,但是它比较浅显,容易懂。呃,但没有没有指数了,只有只有电子版的,你搜一下。

应该能找着啊,这个意思嗯。网教202117K税后15,北京18年1月份的第一份京东外包。只说会用底层,那就补底层,这个没什么可说的。哎呦,这个正式工冷眼相看哈哈。大哥,你这个别太脆弱。

然后呢也不要太敏感。别人看你的。这种眼眼神也好,你不要太往心里去。首先,建立起来强大的心理,我已经说过这问题了。不要那个什么。再一个呢,我认为啊你作为这个学历来说,17K的话也还凑合也还可以。

所以你下一步的该怎么办呢?呃,我斗胆在你不了解你特别细节的情况下稍作规划,好不好?

你认真听啊,我建议你的是。呃,第一个你拿下这个本科了哎。为什么每次都会把这个给弄出来?Shit。😔,第。好,第一个呢,你已经拿下这个本科了,这说明你有本有本科学历了。然后呢,你现在在外包。

我觉得你第一步是应该要建议你是要跨出外包,这是你的第一步。这件事情很容易达到不难。但是呢我需要让你在快出外包的同时涨薪,至少涨到25K。这是至少的啊呃,但这个事情也不难。

就是这一步呢本身不是特别难补对应的技术,然后修改好简历,老师帮你做做好指导和润色抛装,做好准备,这步是很容易达到的。呃,但是比较难达到的是下一步,就是你让自己尽量拿一个高薪水,25K是起步价啊。

28K30,这是你的目标价。然后呢,在你下一步里边。一定要待一段足够长的时间啊,大概要2到3年左右。在这2到3年里,辛苦你好好的学习各方面的技术。认认真真的让自己的技术变得硬硬气起来。

绝对不能够比那个本科生差,而且还要比本科生更强。好在这种前提之下,你大概在29岁、30左右的时候进到大厂。呃,我跟大家说,我们曹老师进进到阿里的时候,大概是28岁还是229岁来着,就是在这个年龄进去的。

呃,时间稍微长一点。你想直接进这件事情概率比较低。不是很容易,尤其是你现在还在这个外包薪资还不算太高的情况下。呃,不过京东外包的话,应该有机会进到京东的那个那个呃本本部的吧,就看你能不表现了嘛。

你技术表现的比较牛逼,然后呃为人处事儿。

嗯又又会来事儿好,这个晋升嘛就相对来说容易很多。其实我说到这儿啊。各位想做晋升的小伙伴呃,嗯同学们一定不要放弃对于非技术的。非技术的这个追求啊,什么意思呢?就是有好多人我们俗称叫会来事儿。好。

那这个时候呢,他所。他所面临的机会要比你这种不会来事儿的,到处都是棱角的,生了吧唧的这样的人,他的机会要多的多。这点大大家同意吗?同意同学给老师扣个一,还还还有吗?还活着呢吗?没问题吧。你们想。

老师推荐你们几本那个教大家怎么为人处事的书。比较初级的那种。好冇。第一。呃。台湾作家刘墉写的叫我。不是。教你炸。好。呃,第21个。推荐一本非暴力沟通吧。非暴力沟通。其实为人处事这块重点是一个心态。

就是不要把自己看的特别低,也不要把自己看的特别高。不要把别人看成敌人,但是也不要把他当成那种完完全全的掏心窝子的呃,所有人都可以掏心窝子的那种啊,那种种傻傻了空也不行。这它是一种感觉,最关键的要去实践。

你要认识到和别人打交道,这件事情和技术同等重要。当你认识到这点的时候,你的晋升之路就打开了。是是这个说的有点那什么了啊嗯。对这个会来事怎么定义呢?这个确实不太好定义啊。

你也不要刻意的去追求说那个我就得让所有人都喜欢我,也不是这样的。他有些这方面也是有天赋的,有些人是有这方面天赋的啊,有些人呢他天生就不太适合去搞和人际关系相关的工作。

但是我认为呢你至少应该和人能够和谐相处。所谓的会来事儿,在私企里面,就是我能够专注自己做好自己的事情,同时不跟其他不给其他人带来呃负面的这种这种这种印象,好吧。积极合作不带来负面印象嗯。

普通985在读非机算机专业想转码可能性大吗?呃,你需要我预计啊,你如果想转一份普通的工作。就是只是想在计算机系计计算机这个行业里面转过来之后,拿一个普通的工作,半年足矣,老师一定能让你转过来。呃。

但是呢你如果想起点要比较高,你要给老师一年的时间,这个才才够听懂了吧?首先要补计算机的基础。然后还要补相关的呃各种的项目点啊,然后再做好简历,这样才可以。

珠海Cshop二开2一届啊转闸了,目前薪资6K1。2万。广州呃,小case啊,如果这个这个到不了,老师也也是可以退钱的。呃,你这个比较简单,而且也比较到位,你赶紧转Cshop这玩意儿没前途的。

为什么说他没前途,我不知道大家了不了解。我说了,C sharp这玩意儿没前途,原因是什么?呃,Cshop现在能干的工作,我给大家分析一下。第一个呢是做点net。点net本身是工作在微软平台。

微软平台目前在服务器领域1%都不到。很小众。C sharp能干什么?C sharp能干游戏的脚本语言。比如说你做呃unit3D的,你做cocus的,你可以考虑用C sharp做脚本。但是你说做游戏。

做脚本的,你能拿多少钱?很低。好,这是第二个。第3个C上盘能干嘛?公控的上位机。公控的上位机,但是这个领域想拿很好的薪资也很也很少。所以我跟你说,转过来是没是是是正正确的啊,而且必须赶紧转,你还年轻啊。

你要是年龄大的,搞C sharp的,想转的话都费劲了。

12000在广州的话问题不太大啊。Cshop公控上位机。对公共客户端没错嗯。

合肥985社飞科班2022。阿里实期转账24K就工资不够理想春招再战转账。阿里别的部门没有老师什么建议。哎,你这个有有点意思啊。

那个。嗯。😊,呃,你这属于呃别人使劲儿进不去是吧?你这在这凡尔凡尔赛哈,觉得薪资还稍微低一点。😊。

呃,其实作为2022届的应届生,明年才毕业。然后今年就已经拿到24。在。合肥。大哥,我认为可以了,哈哈。😊,呃,你是想秀一秀,是不是?😊,听我说啊,如果你想寻求更好的薪资,寻求大厂里面的SSP。

首先第一点呢,你已经转正了。你如果再跳到别的地方就叫跳槽。当然你想在内部阿里就想转岗,我个人认为你别动了,你为什么呢?你就给人一种特别不踏实的感觉。😡,娘的,我我这个部门刚收把你收进来,然后呢。

还还屁股还没捂热呢,你你现在就想走。😡,你别这样。呃,同时呢我也告诉你薪资这件事情,你的第一份薪资绝对不是你致富的根本。我再说一遍。无论你毕业拿多少薪资,你毕业就算拿5万。

这个你这辈子也不可不可能靠你第一份薪资来致富。能听进去吗?呃,我我跟你说,像我刚才给你看到的29岁,年薪120万的那位兄弟。他也是24岁毕的业,也是念完的呃。他是念文的本科啊。也是念他念完的本科。

你说他第一份薪资有多高,估计也就跟你差不了太多。但是不阻挡他几年之后拿到。上百万这样的年薪不足等他几年之后,在一个不错的企业里头拿到这个股票的期权。所以不要太看重这一点。

不要太看重这种这么短期的几千块钱的涨幅啊,给你涨到3万,你又能多多少钱?你应该真正看重的。是你这种感觉。是你给人的扎扎实实的感觉。你不知道我给你看的那个简历的那个那个小伙有多扎实。他给人的感觉就是踏实。

交给他,你就特别放心。你给别人这种感觉的时候,你的机会就大大的就来了。但是你给别人很机灵,很精明。啊,一有好的机会,我就要跳这样的感觉。你就错失了更大的人生机会。

所以我建议你别动了,好不好?不知道这种年轻人能不能听得进去。这个其实这种话吧,有的时候我想我要是这么年轻,我可能连听都听听听不太进去啊。你们能听进去吗?能听进去的扣个一,我也没白说嗯。

滚雪球我能听见滚雪球,你多大了?😊,就好多小年轻是听不进去的,知道吧?😊,男的本科,武汉五年13。啊高薪,你这个简单啊,那个在武汉来说非常保守的。明年34月份拿到18吧,好不好?这就是特别保守的了。

就是可以达不到给你退钱的那种保守了,好不好?😊,呃,就是你这不成体系吗?呃,跟老师这儿最容易的就是形成体系知识体系,这也是我们呃教课的一个目标啊,只要你形成体系,剩下的细节不就是钻的事吗?

这就学习的重点。

就学习为什么有人效率高,是因为他先形成了体系。为什么有人效率低,是因为他碎片化学习。哎呀,不聊了,太累了。明天再聊吧。明年双十一老师也是要参加活动的。没聊到的,可以明天聊好不好?当然想跟细细的聊的话呢。

报个名。改变你这这辈子的机会啊,就在老师这。新增13,目标新增20java。😔,呃,南京3。5。成本。高新视频资料容易忘。嗯,这不能。😔,嗯,但是你能不能到20,把握性不太高。18。如果你要是接受18。

这个把握基本上90%以上。因为你南京的话,上二师好像是个坎,我要没记错的话。十八的话呢,就基本给你补补基术,你就到了,都不用太费劲。好了,同学们,咱们就到这里吧,好不好?今儿聊的也够多了,也够累了。

有同学加我啊。呃,咱们 seeee you tomorrow。咱们直播间的话呢每天都有直播。呃,明天呢双十一的活动我也在直播间。呃,但是还是那句话呃,今天晚上的11个名额。呃,直接参与我们双十一的活动。

另外呢,双十一的抽奖双十一过后呢,像这种1块钱一年的这种这种活动,我们就不打算再提供了,好吧。呃,请大家抓住一年之中最好的活动的机会,而且这个活动保价一整年。放心啊,在你今年双十一到明年双十一之前。

你觉得你买贵了贵多少10倍赔付。参与抽奖啊,找丨小丨姐姐报名。南京去年毕业14000还可以吗?可以,我觉得可以。刚刚毕业1000吗?14K没问题啊。美浩我听累了。对啊,我说的也都已经很累,听都听累了。

说的就更累了。明天见see you tomorrowor,拜拜。拜拜。这个我建议你听听曹老师的建议,因为他本身是在大厂工作过好长时间的。呃,你这个的话呢,其实短板就在学历上。关于这个学历怎么样杀金大厂。

我在直播间讲的非常清楚。呃,恐怕呢。你现在还相当于小白。这个目标的话,我个人认为啊,你定的呢实际上是有挑战,这个难度是相对来说有挑战的。那么前三年的道路,我在直播间已经讲的非常清楚了那个。

尽量优先找一份薪资更好的一份薪水,这是第一步。然后呢,待一年左右。第二步呢提到我们进大厂之前的一个薪资,这个时候呢需要你可能要待个两2到3年这个阶段比较难熬,它是需要你长时间的一个毅力。

然后进大厂的概率就高很多了啊。呃,杀进大厂之后是另外的规划。呃,那个的时候你的这个目标,百万年薪的目标才能够。开展,所以一步一步来,先不要考虑那么远。嗯。😊,你的详细简历,哪个学校的什么背景?

SSM框架肯定是不够的。嗯。😊,大连腾讯子公司世纪鲲鹏,这算大场吗?我觉得在大连可能可以算啊。大厂嘛就是薪资比较高嘛,得给到很好的薪资才算大厂啊。拜拜。But。

系列 3:P110:【JVM】Class文件解读_1 - 马士兵_马小雨 - BV1zh411H79h

所以我们讲呢整个class文件的格式,它就是一个二进制的自节流。这个二进制自节流怎么解释,那就看由谁来解释了。这个东西是由java虚拟机来解释的。它解释的时候是怎么解释呢?

注意看class呢大概有这么几种的内容啊。这里呢我给大家画了一图。因为很多那个书上也好,或者是文章上也好,他们讲这部分内容的时候呢,用的都是表格。那个表格的话呢,你要想脑子里有一个。

从大到小的一个完整的这种概念还是比较难的。所以呢我尝试呢用这个X mind呢给大家画了这么一张图。那么这张图呢,你你从头到尾看完了之后呢,你这个class文件啊差不多就能够全搞定了啊。好。

我们一点点来看啊,class文件呢它有这么几个几种几种几种。呃,整个class里面有这么几种内容啊。第一个呢叫呃mag number魔术啊。

man version major version这东西呢是一个class文件的版本号。后面的是constant pull count。你一看就知道常量池,然后下面是常量池的一个具体的实现。

你对常量池里面到底什么内容?我我先把打开的这部分给它合上。我们先勾屋建瓴,从最顶层的结构开始看,顶层结构就这么几个啊,medy number minor version meta version。

但是这里就是全部都是。版本版本的东西,还有呢constant pull count说常量池相关的常量池的具体的实现。Access flags。这我们应该怎么翻译它嗯,叫做。那这这个应该怎么分?修饰符吧。

就是整个class间那个修饰符,你是public的,还是private还是protected的这部分东西啊。fis class当前的这个类叫什么名?super class副类叫啥名?呃。

anfaces count实现了几个接口,具体实现了哪些接口,有哪些个属性,fieldels count具体有哪些个属性?有多少个方法,具体有哪些方法 methodsds。

attribute count还有其他的一些附加的属性有哪些?附加属性的具体信息。大概就这么多然后大家呢如果大家真的对这个东西感兴趣,哎,我希望你能够背着把这东西呢给它。脑子里记下来。

或者在纸上能够画下来。这要求有点高了啊。感兴趣呢就可以研究研究。实在记不住也就算了。好,我尝试在PPT上呢给大家解释一下。这个我故意留了一些空格,咱们讲的时候呢,填上去。

让大家呢脑子里呢印象会更加深刻一些。我们一个一个来看。这里面呢能够很清晰的看出来,就是每部分到底有多长。一般来讲。U1U2U3U呃U4U8,这里指的什么?U是指的unigned叫。

无符号整数U一就是一个字节,把这一个字节看成无符号整数,就这意思。其实U一呢你不用多想,就是一个字节的意思。U2就是两个字节,U4就是四个字节,U8就8个字节。我一个小格是一个字节。这对16电制来讲呢。

我这一个16电制数就是4位嘛,两个16电制数就是一个字节8位。好,大家看这里。前面的四个字节。指的是这个文件的统一的标识符。当我们看到这个文件统一标识符的时候,就知道这是class文件。

而不是GIF文件,也不是PNG文件。很多文件格式都是嗯这么来标识的啊。你像GIF有它自己的头。呃,PNG应该也是,就是你你你打开这些文件,用16进制打开的时候,它前面这几位基本都一样的。

当我们看到这么几位的时候,就0X咖咖啡baby。你就知道哦,这是java的编译完的class文件,这是四个字节。所以这部分呢叫做magage number。过来。大家呢稍微的。画一画好吧。嗯。好。

这部分叫什么呢?叫做。My number魔术。你的EXE文件也有类似的东西啊。好,后面四位前面两位呢是。前面这两位是minor version。minoror。

miner的意思就是那个那个那个整个版本里头那个小。小版本和小标识符,比如说我们版本叫52。0,它就是那个点儿零的概念。后面这个叫大的版本号啊。我们class文件目前是有哪些个版本啊。

这个叫major version。我呢是用JDK8进行编译的,所以它编译完成这个编译完成之后的这个版本呢是0034。注意这个0034,这个34是什么东西呢?是1个16进制,那么翻译成十0进制是多少呢?

你自己去算一下3乘以。16的1次方就484乘以16的0次方,448加452。52在。整个的呃java的这个体系里头呢,52这东西就是。java呃1。8编译完成之后就是52。好吧,1。9应该就是53了啊。

毫无训练痕迹的小戏,你问出这个问题来。快气死我了啊。嗯,毫无训练痕迹的小戏,你下去之后找到咱们网站。里边有一个菜鸟预习。在菜鸟预习里边。是一个。有一个叫叫二进制的预习内容。下去之后把它看完。

这个里面写的是十六进制,我已经说半天了,这里面写的是十六进制啊。十六进制里面4A是10。C呢ABC是12啊。不会有同学问出这个问题来。嗯,你的基础真的是该好好打一打啊。好吧。

不过呢幸亏咱们是有基础的给你打的啊,你去翻一下菜鸟预习里面的二进制的内容,好吧。嗯。好,我刚才讲的这个这。这应该是几个字节了,这8个字节有没有同学有疑问的?

就是当我们看到这个class文件里面内容的时候,我们看到的这8个字节哎,就是代表的是这个意思。傻了,不不要傻啊,没事儿啊。😊,没有这方面基础是正常的啊,往前翻一翻。好,看这里后面是什么呢?

后面是constant pull count,就是常量池有多少个。有常量池里面有多少个内容?常量池是一个池子,是一个是整个class文件里面最复杂的内容,而且常量池里面会互相引用。

以及常量池会被其他的那些个各方面会引用到。所以常量池呢是极其复杂的一个内容。我们更详细的东西呢,我们一会儿再说,在这里呢会告诉你常量池有常量池里面存在了多少个常量。好。

所以这里是用两个字节来告诉你常量池里面有多个常量。那我问你,既然他用两个字节来代表,他最多能存多少个常量啊,同学们。这个叫做。Constant。P。Qut啊。嗯,conson book。两个字节啊。

二的16次方65536哎,当然。它最大的数能够代表65535。但是呢由于我们常量值后面。到底有多少个常量呢?唉,其实是constant pull count减一啊。拼错了。

consent pro count减1。constant pull count constant pro是长度为constant pull count减一的一张表。或者是这个一个数组就行了。

然后这里面的内容特别繁琐,特别。特别的繁琐,我们一会儿再来聊里面内容。所以当我们看到啊,比方说这里我写的是十。注意这十是16进制,那实际当中是有多少个常量池,有多少个?16减1。是有多少个常量呢?

15个,那为为什么要减一?因为我们的常量值的编号是从几开始呢?是从11开始。我们平常的数组是从几开始啊?是从零开始,但是呢常量值的编号是从一开始啊。为什么从一开始原因是它有一个零存在那里。

将来没准有哪一有一有一些引用指向呢,会表示不指向任何常量池中的任何一项,那个时候就可以用零号来代表。它保留了这么一个可能性啊,所以从一号开始。好,看这里史蒂文语说这个常量值数量个数和我编译的不一样啊。

你废话,你里边那个写了什么代码没有?你像我一样,什么代码都没写,它应该就是一样的,好吗?你里边要写了一个。11个成员变量或者方法,那肯定就不一样了嘛。

你见过哪个class跟另外一个class那就完全一样的那除非代码一样,否则肯定不一样啊。好,不不跟你不不多说啊,后面后面的是什么呢?我们继续看这个东西呢叫做access flags。就这小。

这项是什么东西呢?其实就是在class文件。前面你写的是public的,是不是final的,是不是一个interface,是不是abstract的,是不是annotation。

是不是enumeration?okK是不是public类型是吧嗯。后面呢又有两个代表的是什么?当前的class文件指到常量池里面的那个表里面,常量池那个表里面内容。super格副类置到畅量池里面。

Interface count。interfaces好好。这张图呢我先留在这儿。留作以后,你自自己的一个作业,你自己呢在纸上啪啪啪能把它画出来。我如果现在呢给大家这么来解释,我相信大家看起来非常的费劲。

所以呢我们采用另外一个工具,这个工具呢。叫做。它会把我们class文件里面内容帮我们翻译好,翻译好了之后呢,到底里边有哪些东西,我们能够看的更加的清晰。好,看这里。这个工具也有好多种。那么第一种呢。

java自带的叫java P的命令,我演示一下吧。

有javaP啊,有这么一个命令。java P是显示那些个class文件里面的信息,它的用法呢是java P后面跟一个我们自己的参数啊,再跟后面跟一个class文件的的的的的对class文件的名字。呃。

我们classus文件。的名字的话呢,我得切换到那个。

class文件所在的目录下面去。看这里。拷贝一下。

Copy path。嗯,我们这文件在这呢啊。😊,呃。javaP。嗯,后面写我们这文件的名字回撤。Compelled。那只是。4。只是显示了非常简单的内容。GP呢可以带带参数等Vvers。详细内容。

他就会帮我们把这个整个class文件里面的这些详细内容帮我们翻译一下,让我们来看。他会帮我们翻告诉你啊,theman version是多少,mar version是多少啊,flags呢是有什么东西呢?

public的,而且呢有一个supersuper是一个遗留的概念。

在我的。图里面呢跟大家呢。解释过了啊,看这里。这个super呢是一个该标志,必须为帧,是JD克1。0之后呢。

它一个遗留的概念,所以你看到的任何class这里的AC super都都是有的,这个很正常啊,不用去管它。大家你往下看啊,this次class后面编号是多少,super class编号是多少啊?

当你拿这个来看的时候,你就会方便很多了。

OK这是。这个工具java P这是java自带的,你不用安装任何的东西。还有一个叫就JBE如果你感兴趣的话呢,可以下载下来去使用一下。这个JBE呢叫java的呃ba code的edit。

它除了可以观看那个二进制码之外呢,还可以直接进行修改啊,你就可以在那个直接上面拿java的汇编语言直接写东西啊。那好,我最常用的是这个啊叫Jclass library是ide的插件之一。大家看这里。

这个插件你下次面自己去装settings,就这个插件Jclass lab。Bite code viewer。这拆件怎么用很简单。首先你确定你这个class文件已经有了。然后呢。

比如说啊你你你我们现在是呃有了这么一个原文件,然后呢,我把它编译一下build build project。当bu完了之后呢,我们。thinkk一下。嗯。好多class没有显示出来。必有的。啊。

正在 build的没 build的完。呃,你确认了你这些class文件呢已经全部编译出来了。好吧,然后你找到任何的一个class。把光标放在我们这class文件的。类体里边儿。然后看这个菜单儿。

view菜单。下面有一项叫做show bad code。With j class library。当你安装了这个插件之后,你就会有。嗯,这个选项了,点击你会看到啊。

它会整个的帮你分析整个class的内容,帮你分析出来。好,假如你没有按装这个插件的时候,是什么样子的呢?你只有这个菜单,这个菜单是什么叫做。6。当然你得选选中我们这个class文年啊。

Will show bad code。这是艾迪尔自带的。这这个东西啊s by code。那么这个东西呢就是用java P给分析出来的。也就是刚才我们用的那个命令行分析出来的。显示在这里了。

但是这个不好看,看起来不方便。所以一般我们用这个插件叫Jclass library。这个插件当我们打开了这个class文件之后呢,他会帮你来分析下这个class文件里面到底包含哪些信息啊?

我们来看看它分析的呢非常的。多看这里。他首先会帮你分译出来这class文件的general information通用的一些信息。看maner version。小版本大版本是1。8的,552。

他而且我会告诉你,这是这是这是1。8编译出来的classus。consin pro come的16。长度是16。产量池的长度是16啊。Xs flags是0X0021。

这里面涉及到了谓的谓语谓谓语呃呃安慰语的一个运算。按位语的运算呢。不知道咱们同学们有多少同学不熟的,需要我跟大家聊一下的,有没有?首先第一点啊,如果说你二进制不熟悉的话,你应该去看。我在刚才说过了。

菜鸟预习里面关于二进制的内容。如果你觉得不熟,需要老师讲的,可给老师扣2,好吧。如果不需要的给老师扣一就行。这里面牵扯到一个二进制呃安慰语的运算,原因其实是什么呢?我们来看这个class文件结构里面。

你看啊这个ACCplic是0X0001。然后ACC呃super是0X0020。刚才我们看到的它的结果是一个什么呢?是1个0X0021,其实就相当于嗯。其实就相当于这部分与上这部分。

这两个谚语就是0X0021。那好。当我们看到000X0021的时候,你就会知道啊,它是由0X0020和0X0001组成的。所以呢它既有ACCpublic,又有ACC superuper。嗯。那这样的话。

它就可以用。两个字节。能够代代表很多的内容,把某一位置乘1,把某一位置乘0都能代表很多内容。所以我们这个access flags两个字节就够了。好,讲到这里,有没有同学有疑问的?没问题的。

你要给老师扣一,好吧。嗯,O。所以你看到他的这些个。general information的时候,你就应该能理解了s flags0021呢说明什么palic克再加上。

ACC superuper那个那个super的话是正常的一个东西啊,说this class我当前这个类到底是哪个类呢?com嘛是用JVM by code下面的这个类,这是这个类的权限定名。

它叫做co fully qualify的 name,就是你就相当于一个全名就行了。权限的名,他只不过把这个斜杠变,他得把那个点变成了斜杠。它前面有一项叫CP音fer2号2号CP音fer指的是什么呀?

这个名字在哪存着呢呢?其实是在。常量池里面的2号存了这么一名字。jaline object为什么还会存这么一个东西啊?你想一下,也拿大腿想一也,应该知道这哥们儿是从他的父类里面继承,他父类是谁呀?

保不证他这个来。这个类的名字在哪存着呢?在修在常量池的3号里面存着呢。interfaces account有多少个?呃,你你实现了多少个接口?fieldels count,你有多少个属性。

你 methodss count,你有多少个方法,attributs count你有多少个。其他的那些个附加属性。这是一个general information,它自动的帮你分析出来的。下面。

第二项叫什么呢?叫consant pool。好,这一项是最多最复杂的。刚才我们看到了cons pool,一共有16减115项。当你打开的时候,它会默认的帮你把这首像全列出来。我们一个一个来看。

这个比较就比较好玩了。当你能看懂conant constant pro的时候,这class文件你基本上就懂了百分之七八十了。

系列 3:P111:【JVM】Class文件解读_2 - 马士兵_马小雨 - BV1zh411H79h

呃,因为我这环境呢编译的时候用的是那个十1的那个编译器。但是我指定编译出来的版本是1。8版本。所以他这也稍微有点问题啊,他可能看到的,你们你们如果是用1。8编译啊,用1。8来观察。

可能跟我看到的稍有区别。常量池的长度什么的,里边内容什么的,呃,但是关系不大啊。你只要能读懂里边什么信息就行了,关键信息能看懂就OK。好,下面我们来讲常量池啊。首先第一件事啊。

常量池里面注意常量池里面的常量类型特别多。Oh。这个常量池里面的光常量类型就有这么多种。我给他就列出来了。就这么多种。1345有什么为为什么没有2啊?标记常量池的每一种类型,前面都有一个。

一个字节的标记。13456789101直到18。这里面呢是用的最多的叫constant pullcon pull uUTF8UTF8记住了,这是代表什么?UTF8的一个字符串。UTF字符串听懂了吧?

记住这个就行了啊。然后这一会儿我再给你详细解释一对那个二进制的,你就明白了。还有呢呢是integer是一个int类型,float类型,long类型,double类型class类型。呃。

Stamlation。Field reference。属性引用的类型,method reference方法的引用interface呃,met reference就是这这这接接口方法啊。

name type接口的就方法的名字和类型的一个代表。mettter handle, method type invoke dynamic infer,这后这是这是1。7之后才有的是关于。

加了那个leer表达式之后,sorry是加了那个动态的内容之后才有的三项啊。嗯。我们看这个主要的能把主要读懂再说。我们先来看这里面会有哪些东西啊。第一个呢叫constant method一fer。

它会它这东西呢,他已经帮你分析出来了。呃,我们来看这里,它常量值里面的第一项存的叫是med reference infer,是方法的一个引用的信息。那这方法引用的信息里头包括什么呢?

方法引用信息里头我们来查一下啊,metd reference infer method method where。mer infer在这里。它包括里边包括三项,就这这个这个信息里面又包括三项,哪三项呢?

它的标记标记是10。呃,是后面的index两个字节。指向什么呢?说这个方法到底是由是包含在哪些可哪个class里面的。它是指向常量池里面的另外一项,哪一项呢?

就是这项constant class infer。那好,下面的这个呢叫指向谁呢?指向constant type nameman type infer的所所引的。下标值。如果我们能这么来理解的话。

就是我们常量池里头呢有123456,1共15个这么多。我的第一项里面存的内容,它会指向谁呢?指向别的项的内容指向别的项的内容。当然了这个工具已经帮你分析出来了,它指向的呢有谁呢?

class的名字是指向我们常量识别的3号内容,3号内容是一个const class infer嘛。你看这个3号内容的名字是什么呢?javaline object。O。然后接下来呢。

是指向nameman type的类型。是指向几号内容呢?13号内容13号内容是name type, name type是指的是什么?指的是这个方法。第一,这个方法的名字是什么?第二,这个方法的。

这我们应该怎么说描述符。是什么?好,看这里。当我们看到这个方法in initial的时候,你就会知道这是一个构造方法。构造。当我们看到这个方法的描述符的时候,你就应该能知道啊,这个方法是前面是一个括号。

代表什么?这方法里面没有任何参数。返回值是一个VV代表什么?V代表word,它的返回值是一个w。所以这里是。object那个类下面的。默认的那个构造方法。啊,不知道我说到现在。

你大体的意思是不是明明白了没有?刚才的这小段有没有同学有疑问的?大概的意思啊,因为这东西需要你下去之后,自己慢慢的好好的细细的抠。And。没问题,同学给老师扣一好吧。😊,有的学说我还是不理解,我的妈呀。

怎么从二进制里面读出来这么多内容,到底是怎么读出来的呢?好,我下面再进行一个直接对二进制的分析,看看你是不是能理解。大家看这里。这是刚才呢我们这文件啊编译出来之后的。

内容咖feba这这个这块这个这块我就不说了啊,就这个。呃, many number minor version, major versionconsant count一共是15项。好。

15箱里面的第一项。你还记得吗?第一项是什么东西?上来之后是一个字节的一个索引,注意是一个字节的锁引。重新化。我们我们翻回头去看这个规范,克class文念的规范。就是你看这个永远要对着这个来看。

当我们在constant pull count完了之后,后面马上就开始我们的里面的具体内容。而里面具体内容的话。这里面具体的内容呢,包括索引标志和类型。是这个首先呢我们来看任何一个项啊。

第一个字节只占一个字节。第一个字节是它的这个标志。这标志是什么东西?如果标志是一,那就是代表是UTF8。如果标志是三,代表的是NT值。好,对于我们来说,我们的这个标志是什么呢?我们第一项的标志是什么?

你看看。第一项的标志是什么呀?0A。0A。十进制就是十0。那我们就去查class文件里面十这项是谁呢?是constant method reference reference infer。

所以在我们常量池里面的第一项。刚才你看到了常量值里面的第一项是constant method reference infer。

接下来我们就要去查这个constant method reference infer的东西。好,看这里它里面的结构又什么样子?它里面首先标记是十,接下来呢是两个字节。这两个字节呢。

是指明声明方法的类或者描述V接口那个conclass infer的所引像,也是constant pool的所引像。后面两个字也是nameman type的所引效。所以你看啊,我们继续看。这个地方是。

我把它放出来。放大一些,看这里啊。呃,这个地方是我们的呃代表我们是我们的my method reference infer那个索引像。索引像完了之后的两个字节。

代表的是它指向的别人家那个那个那那个那个池子里面那个class类型啊,那个那个所影像。但是你看0303代表什么呀?指向的是常量池里面的3号。3号内容。好,后面呢是0D。000DD代表的是13是吧?A。

BCD对13,所以它指向的是13号内容。因此这部分到这儿。这是几个字节呢?123。455个字节。好,这部分就是我们常量池里面的第一号。当然,03代表的是什么?你是不是得找那个3号常量池里面内容去啊?

下面我们就继续看第二号常量池是07开头。长量池里面2号啊07开头,这里面又是什么内容?再这么一步一步一步一步进行分析。好,刚才这一段大家不知道是不是理解了,不知道说清楚没有。能够理解同学。

你给老师扣个一,好吧。所以我希望你下去之后呢,你就对照这个二进制,你就这么一个字一个字的来分析,你看看是不是能看懂这个常量池的部分。如果这部分你能看懂的话,那么常量池你过了。突然感觉克拉斯没那么丑了。

是吧啊?😊,好,我们再来分析一个,好吧,我们刚开始分析到了0B这里啊,我们来看07同学们告诉我这个07代表什么来着?告诉我一下07代表什么来着?给我家反馈。😊,我们得去查谁呀,得去查这个七代表什么。

这个七代表什么呀?😊,constant class infer。是吧什么标记嘛。所以。翻回头来看我们分析对不对的时候,你往这看,2号是一个constant class infer。

然后这个constant class infer又指向了他的名字,字符串是谁啊?是我们自己当前这个类的名字,它指向了14号。然后你再对照那二进制,看它是不是指向14号啊。看我们那二进制。07好。

是我们的常量池的第二号的标记。接下来000E。是不是十4啊?okK14啊。😊,那14号又是谁,你自己去看吧。接下来又是07,07是谁?class。然后000F指向的是D。15号大家还记得吗?

我们这最第一号的时候还指向了这个03呢,这是这是第三号啊。第三所以第三号还是class,它指向是谁呢?javaline object它代表的是我们是哪号呢?15号。所以你再往下看的时候,4号。

是1个UTL8UTL8比较简单,它就是一个字符串。imitial initial这个是代表一个方法的名字,这方法名字叫构造方法。由于各造方法呢都和和类同名,所以他都用引力手来代表。你继续往下看。

第六第5号是。方法的类型的一个代表。这个方法类型是特定的一种表示方式,前面用括号里边有参数,拿这个参数来代表,然后后边跟它的返回制类型,而这个返回制类型是用一个字母来代表的,是用哪个字母来代表的呢?好。

我这个文件里头已经给你写了。我们是写我是写在了message里面。啊。Methodds, the de index。它的描述符描述符是先参数列表放在小括号里面,后面跟着返回值。你比如说M。

你用括号V来代表,就表示它的返回值是V,里面没有任何参数。那假如说里边是一个tto string to string的一个方法。to string方法,它的返馈值是一个strring类型。

你该怎么代表呢?前面是一个括号,后面跟一个L。这是它的规范所标识的L,然后后面才是跟整个这个全名,后面还要加一个分号,用来用来分隔。好,这是整个方法的描述符。那更复杂的是什么类型呢?

你比如说我里面有这么几个参数,第一个参数是int类型,呃,一int数组类型,第二个呢是一个int类型,第三个是一个浪类型。好,这个方法的描述符会特别的奇怪,会是这么一个东西啊是这么一个东西。

这个东西呢你看的不清楚,我它拷贝一下,写到外面来。啊,这就是我们刚才那方法的对应的啊,我把放大。好,首先第一点I代表什么intI前面加个左中括号代表什么int数组,这是第一个参数。爱代表什么?int。

哎,左边加一个中块代表什么?应的数组,这是第二个参数。这代表什么long。第三个才说是浪类型。所以这里面包括三个参数。反回值是什么?愣了一下。はは。😊,嗯,我看我有没有给大家记每一个参数拿什么来代表。

看这里在这儿。discriptatory nextB代表的是byit,C代表是char,D代表是double floatat是Flong是J。后面SV代表是voL代表的是object。

但是后面你要跟整个的名称啊,数组是用左中号来代表的。如果你加两个左中号号,代表的就是两个数组。sorry,二维数组啊,对不起。第二餐数不是in吗?我看看啊,因为这个是我写的啊,不是不是那个什么什么的。

我有可能是不是写错了,笔误。看一眼。嗯。哦,对不起啊,这里笔误啊对不起,这里应该是把这个中块给去掉这样。突然看懂好。嗯,好。所以长证池里面内容最复杂啊,因为长量池呢牵扯牵扯特别多特别多多的内容啊。

okK我们再来看这个长量池里面的更详细的一些内容啊。你看呃这其实就是给这个方法做描述的。你一看就知道。好,继续看啊。这conant有第6号,第6号是code,这是一个属性表的名字。

后面我讲到这部分的时候,attribute attributebut。这里面呢除了so style之外啊,attribute。由于只是med里面啊,你看metd,我们现在只有一个方法嘛。

它里面有个属性叫coded。所以这个code的这个名称在哪儿来的?也是在我们常量池里存着的。因此你看到这个code实际上是后面要用到的一个常量的名字。

第7号叫line line number table,跟那个code一样,是我们后面要用到的某一个常量的名字。在这儿line number table。那么。这是第七项。

第八项呢叫local variable table,是我们在方法里面要用到的一个属性的名字,local variable table在这儿。你看这个local ver table。

它的名字的指向指向长辆车哪项啊?8号项我们来看这个8号项是不是local ver table。就这东西。优条单代表了字符串嘛?字符串 this。字符串儿。我们的整个。类的权限那个名全名。

字符串source style是我们后面要用到的。属性的一个名称。四符串儿。我们原文件的名字。后面用的source file,你看source file它指向哪一项呢?第11项第11项是什么呀?

s file。好,第12项是什么?呃,第12项是T01点java。是说字道是名字啊,第12项是那个我们真宗的那个名那个文件名啊。内蒙 type。name和type名称和类型。

名称、方法名、类型什么类型的?okK那么这个呢是呃是我们的整个的一个。不是权限那名,就是一个普通的名称。javaline object普通名称。所以常量值就完了。因此。

对于一个特别简单的class拉斯来说。好,这个常量池力就已经有这么多内容了。好,这个账调量词里大概存些什么样的东西,不知道大家理解了没有?好,能大致理解的同学啊,你给老师扣个一,好吧。

同学们大家记着这一点啊,呃就这个这个class的一些细节啊,你如果真的感兴趣,你真的需要花时间下去一点点的细一抠,好吧。总而言之,常量值是一个class里面最复杂的东西。写这种的人在阿里应该是P几。😊。

其实这个东西啊嗯它只是比较繁琐啊,它并不难。那么你说它难吗?它真的不难。我们我我们来看一眼这个原文件吧。

对我们学习的人来说真的不能,它只是比较繁琐。因为任何一个地儿你都得需要去查这个0T代表啥。这个0001指下来又是哪一个?然后呢,后面的0期又代表啥,这部分又指向哪个等等等等。你得去查这些东西。

得去查相关的一些规范。但是真正设计的人是比较牛叉的。真正做设计的,设计出来这个人是比较牛叉的class文件设计的特别的紧密,紧实紧致,没有任何的分割符。因此,这个class文件也得到了很多人的认可。

所以以后大家伙设计编程语言的时候,都不用自己设计格式了,我只要给它翻译成class就可以了。

系列 3:P112:【JVM】Class文件解读_3 - 马士兵_马小雨 - BV1zh411H79h

好,看这里。后面的呢是interfaces。由于我们这个class呢我们没有实现interface,所以无所谓就没有了。呃,后面是fieldels,由于我们这个class里面没有任何的属性。

所以这fes里面也没有任何东西。好。有同学会说,里边没有任何方法呀,为什么meds里面会有一个选项呢?这刚才你看到了,它会自动的帮我们加一个什么内容呢?哎,就是。我给给给我们这个构造方法啊。

加一个无餐的构造方法,默认的。好在这个方法里面。这是这个方法的名称,namedescript。name是引用的第4行。是常量池里面的第四号descriptor描述是常量池里面的第5号。

Aces flags。他的访问符。访问标识符。public的。好,看这里。关于方法的仿标识符。都在这儿wesds的。Weathds。任何一个mets里面的选项都有这么几项。

access flag两个字节标识符有这么多。OK特别 low。好,name name刚才你看到第四行,descriptor第五行,其实这方法还有一些个属性附加属性。那附加属性是什么东西呢?

在这里全有了。最主要的有这么几个。扣的这是最重要的一项,就这个方法的代码是怎么实现的?大家记住这一点。好,这是他的名字,名字扣d就第六号。但是。

这个才是一个方法的具体的实现才是最重要的那这个方法具体是怎么实现的呢?好,认真听认真听。认真听。下面才是真真正正的显示了这个方法的实现。而这个方法的实现呢,实际上它引用的是code里面的这个属性。

而这个属性的话。内容就多了。当我们看到这个方法的时候,我们会去里边找他的这个方法里面的那些个1一条一条的命令,一条一条的指令。而java里面的这个指令。好,我打开我们的java虚拟机规范那本书。嗯。

指令。稍等一下啊。打开我们java虚拟机规范的这本书。怎么什么都打不开了?气死我了,这个。哦,打开了。这本书呢我已经下载下来了啊,你也可以去or克网站去下载。呃。薯签儿目录。

在java信息规范里头的第六节讲的是java virtual machine instruction set。第七节是它的一个参考,就是你整个的这个二进制码分别代表的什么内容?

认真听认真听这个方法的具体实现,翻译成class文件之后,全是这些东西。一个方法的具体的实现,这个翻译完了之后呢,全是这些东西啊,00代表没有做任何操作。

01代表A constant now02代表什么什么什么。这东西是什么?java的汇编。

所以作为我们java虚拟机来讲,当它读到一个class文件的。里边的内容的时候。我我这个找不不好,直接找啊,就是找到这个方法的一个实现的时候,可能我们读到了30这个东西号。

他就要去里边查表里面查30代表的是哪一条指令。

O。然后呢再把这条指令翻译过来,它到底是哪条指令呢?A load0。然后再去表里面查A load零里边到底是个什么东西,我们找一下A load0。

A漏0。在A漏的。在这儿看到了吧?0X19。

看我们的哪部分有0X19存在在哪呢?0。19。19。19在哪里?对不起啊。19。问题啊。为什么没有呢?😔。

他调用了jaline object。那有可能是object里面的那个要求。哦,A load的0A load的0,对不起啊,这是A load的,不是A load的0。A漏的A漏的A漏的A漏的0在这儿啊。

0X26。哎,不对,D漏的0。A load的A load的00X2A。

0X2A。找一下。2A。2A好,在这儿。这其实是我们那个方法的执行那段那段代码。你看啊第一个呢叫2A。

2A呢我我去就去查这个表,这个表里面呢告诉你这个2A呢,实际上它是。呃,A6的0的。这条指令好,接下来呢我们就要去查A50里这个这个指令代表什么?那么这个指令代表什么呢?

如果我们用Jclass library的话。我们直接点A load的0点一下。他就会帮我们。直接打开我们的oracle的链接。太讨厌了,我这口内部出错。

A漏的杠N。欧尔口把这链接给改了,太过分了啊,我们只能自己去查了啊。😊。

我们自己只能去自己去尝。😊,妈呀,这可就麻烦了。嗯。structions a load的0找吧。It's eat all。AAA。A漏的根啊这个。好,接下来你就去读哎这个。汇编指令到底代表的是什么意思?

这个汇编指令代表的是啊把本地的那个。呃,本地变量表里面的第零效是吧,放到站里,嗯,放到站里之后呢,进行第二条指令invoke special。啊,一环抄一环,这就是这YM会音。

当然今我们第一节课呢还讲不了这么些,我们下节课再来讲这里面的指令到底的是什么意思。但是不管怎么样,我相信呢你应该对整个class文件它的一个组织结构有一些呃认识了。我们再来的稍微的这个回顾一下啊。

整个class文件结构呢有好多好多种。类型。呃。尤其是到mes这啊,我们我们我们再稍微稍微回顾一下。嗯。

看这里。

好。整个class拉斯文件的结构啊。等我们大概理解了一些基础的内容之后呢,再来看这些就没有那么头疼了。它是一环套一环,一环扣一环的。好。

看这里整要克拉文件结构呢有这么几个may number0X咖fe baby是吧?matter version小号m version主号主号次号1。8是52。0,所以前面是00,后面是34。

然后constant pro count有多少个常量池,下面是常量池减易具体的内容。这常量值简易具体内容呢有有这么多种类型。我们我这我写的这个第一个呢非常的简单,所以你看到的那里就只有UTM8的。

还有呢像是me method reference的方法的,还有呢name and type的。现在你看到就只有这么多。如果你这个class越写越复杂的时候,你们自己感兴趣,下去加一点儿。

东西再加一点东西,然后来看看它生成的class文件到底有什么不同。最关键是这里面呢互相之间还引来引去的是吧?好,下面是excess flags。

accessces flags呢指的就是整个class里呢,你你前面是写的public的,还是pripri还是还是什么什么什么东东?face class,我当前的这个类是谁?

super class副类又是谁?这个在哪看啊?这个实际上如果用这class library呢是在这里看。呃,他默他会给你放在gene information里面,它并没有在下面列出来。

那this class是谁呢?哦,它是访问的常量池里面的第二号,superclass是常量池里面第三号。你自己去找那个乘量池对应的内容就行了。那好。T续。实现了哪些?接口那些接口的索引。你可以想象一下。

如果你写了接口之后,那长量池里面肯定接口的名字写在常量池里。然后下面呢是对那些长量池的一个索引号的访问。有哪些属性?属性有具体的,有这么几项。这个属性呢access flags,它是public的。

是不是public的,是不是s的,是不是final的,是不是 volatile的,是不是transient的,是不是 syntheticthetic的。

syntheticthetic是不是我们自己写的,而是由编译器自动帮你生成的。这样的属性。好。它的名称的锁引,记住这一看这个锁引,你啥也别说,一定是长量石的一个缩引。它的描述符到底是什么类型的?

具体是哪哪种类型的?另外它所附加的一些属性,attribute是附加属性,有的有有的没有。方法。方法的各种的。结构方法的结构是什么?哎,它到底是怎么样进行标识的?然后呢,它的名字的缩引。

它的描述符的缩引。还有它附加的一些属性,方法的附加属性最重要最重要的一项是扣的。代码是怎么实现的?而这个代码这个东西具体的在哪儿呢?实际上是在最后一项attributs里面。

就附加属性里面最重要的一项呢是方法表,也就是这个方法。编译完成之后的字检码指令。那么JVM看到这个指令的时候,首先会读这个指令进来,然后他根据指令去查他自己的指令表。到底是哪条指令?找到这个指令之后呢。

再来看你这个指令到底代表的是什么意思。比如拿A load的零来说,它其实就是在方法的局部变量表里面的第零项。第零项是谁,永远都是只要是你你你不是静态方法,永远都是这个d。他会把这个this扔到。

操作数站领。领导操作站在执行第二条指令。第二条指令叫invoke special,叫特殊调用,调用什么呢?调用this的构造方法。O。invoke special啊,invoke special。

这时候你在一些表里面去查。Invoke special。你看一眼这个invo special到底在的到底呢?哎它是怎么定义的,里边讲的是一个什么样的东西。然后JVM再根据条指令一句一句的执行。

当我们看到这个code的时候,最后一条是哪哪条指定的是return。

呃,我们看到的是A load0。A6的零完了之后呢,A漏的0是2A,下一条指令是B7。

我们来看B7对应的是不是叫invo special。invo special看到了吗?0XB7。

所以对于java虚拟机来说,它读一条指令嘣儿执行这个方法的时候啊,在执行这个方法的时候,嘣儿读了一条指令。他一查哦,A load的0,然后做相应操作。接下来再读下一条指令B7哦一叉是B7。好。

做下一个做下一个操作。

完事儿之后呢,再读另外一条指令,下一条指令是return,对吧?Return。return是B1,对不起啊,inbook special后面应该是带参数的。Invoke special。嗯。

Used to construct index to the runtime constant pool the current class。下面应该是两个参数啊,B1和B2。也就是说。它调用的是。

因为他有的指令带参数,有的指令不带参数啊。下节课呢我专门讲这个指令的内容。

我们来读这二进制啊,这个B7呢是带了两个参数啊。呃,D0001。后面这两个字节是那个指向常量池的第几号,常量池第一号还记得吗?是jaline object,如果没记错的话。

所以它调用了那个ja line object的构造方法。是干了这么一件事儿。然后呢,下一条指令是B1B1这个指令又是谁呢?我们去查一下。

嗯。去找啊B一的指令是谁呀?你看啊0XB1是谁呢?是return说明方法结束了。

因此。构造方法里面。好,这几条。有同学听懵了是吧?别着急啊,因为你听前面应该没听蒙就没问题。因为这块儿呢是我下节课要讲的内容,只是提前跟大家伙说一下了。这几条。就这么1234。5个字典。这五个字节。

是谁呢?是我们这个文件的构造方法的一个具体实现。我再说一遍。刚才你看到了我们生成了一个方法,这个方法呢叫构造方法。这个方法呢有一个code属性。code属性里面呢才是我们真真正正的这个方法的具体的实现。

这个方法呢?在站在站在虚拟机的角度,它是怎么实现的呢?它是就有这么这么123455个字节来实现的这个方法的具体实现。在我们人看来,这个方法里面什么都没写。但是大家应该都知道,调用这个方法的时候。

你需要调用谁啊?需要调用object的构造方法,这点没问题吧。我再说一遍,我们任何的一个class。当。呃,你你你你你如果不给他写任何构造方法的时候,他会生自己生成一个构造方法,这个没问题,对不对?

而生成构造方法里面你没有做任何调用的时候,它会调用副类的构造方法,object括号。我这我我讲到这儿,有没有同学有疑问的,有没有?再重复一遍,写任何class,你没有写任何东西的时候。

编辑器默认给你加一个无餐构造方法,无餐构造方法你的实现必须得你还记得吗?就是。任何的构造方法必须得调用副类构造方法。我们叫做构造子类之前必须先构造腹类。那副类里面呢就默认它会调用腹类无餐的构造方法。

也就是它会调用object这个类的。构造方法。好,讲到这儿,有没有同学有疑问的?有疑问你提没有没有问题,同学给老师扣1。那么这段代码是在虚拟机里面是怎么实现的,这么来实现的。就是这5个字节来实现的。

那这个五个字节到底是怎么实现的?刚才我们分析了一下。当。这5个字检。这五个字节,当他读到2A的时候,他知道这个。指令叫A漏的0A漏的零代表什么呢?把this压榨。压榨啊扔进去。然后后面呢是调用下条指令。

下调指令是谁呢?是B7,B7叫invo special。而invo special是需要两条,是需要两个参数的,哪两个参数呢?就是00和01,后面这两个参数,001代表什么?代表常量池里面的第一项。

常量池里面的第一项是java。L。All object。invoke special调用了javaline object,它的构造方法。所以这条指令是调用jaline object构造方法的。

最后一个B1。Return。好了,同学们。今天呢我带大家入门了class文件格式,但是我并没有详细的解释这里面每个字节代表的都是什么。呃,如果大家对这感兴趣。请大家下去之后呢。

你对照java的这条这个这个。

lananguage的specation,或者你去看那个深入呃理解张旭一那本书啊,它里面也进行了一些总结。当然也没有必要。因为我我已经给你总结出来了。你你你只要看到看着这个这个这篇文档啊,就这个。呃。

X mind的这个东西。你就能查出来到底每个字节代表的是什么东西了。嗯。这节课呢我们讲了class文件基本的结构。下一节课我们讲什么呢?好,将这些东西。A load到底代表啥是吧?

A store又代表什么?然后。F都要代表什么?invoke special代表什么啊?in呃invo static代表什么?invoke virtual代表什么IOR又是什么东西等等。其实这个东西呢。

java的指令集呢是用一个字节来代表,统共呢它就有个256条指令,最多有256条。所以他指令级呢并不复杂。另外呢我们也不可能带大家呢去每条指令,我都给你讲一遍,我也完全没有这个必要。

你要学会怎么去阅读说明书。就当你看到这条指令的时候,它到底代表是什么意思?我不理解不理解怎么办?要去看那个说明书。

🎼所以下节课重点讲java运行时的这种东西。

系列 3:P113:【JVM】第一天课后作业 - 马士兵_马小雨 - BV1zh411H79h

我建议大家做这样两一件事儿,可想啊给大家留点作业。

你比如说啊。一。

Okay。好,你比如说呃我我我我现在我写的文件呢就只有。

就只有这么简单,那么我是不是可以加一个接口啊,你比如说这个classpublic class T0101,然后它实际上两个接口,一个叫collonable,一个叫sealizable。

那它对应的这个二进制的码到底有什么东有什么有什么有什么区别吗?那你就打开来看看嘛,对吧?

这个class library嗯,你会看到thecont pro呢就有19项了,为什么会有19项啊?肯定会有接口存在吗?我们找一找一下,肯定有啊。

你看这 object的。J Iizable。强有了对吧?

那interface呢interface零是什么?interface一是什么?他。去指向了长量池里面哪一项,你就你就理解了,你就真正的彻底理解了哦。原来这个东西编译完了之后是一个什么样的内容?

那么你继你就继续啊,学这种东西的时候你循序渐进。你不要一下子搞特别复杂,有的同学上来二话不说,哇,七八十个属性啊,八九十个方法,你这样看就没法看。学东西也得需要。方法的好吧,循序渐进的来。

你比方说你再写一个里面就有就有一个成员变量,因他I等零。你看你再来看它里面生成的代码是什么样子。我简单看一下。

你看他cons pro里面一定有一项是什么东西呢?是那个。

因体者。

内门type。はい。这是它的类型的描述。Fiels。哎。

哦,关于这个主主要是这个零呢,它内部做了一些优化啊,它没有产生这个零。

嗯。这得改才行。就能等0这零是他内部做了一些优化,能写个888。然后要重新。rebud一下啊,一定要让它重新rebud一下。

我们看朝常池里面有没有这个888存在啊。

嗯。常量池没。

Should by code with your class library。常量池。Fielel the reference。

。嗯。😊。

Field。

第17项。は。

M粉。现在编义呢编译到这儿了。Code。哦,在这儿啊,对不起,它常量池力并没有存在,但是它存在了代码代码选项里面,代码项里面。他会把这个888的怎么复制过去。呃,你通过读这些代码,你就会知道它。

你你你你你你的成员面量到底是怎么实现的?呃,我给你举个例子啊,你看啊呃我们刚才说al load0invoke special调用javaline object的 initial方法。

然后又漏漏的0,把this装进去。SI pushush888,然后把888扔进去,put field2号,2号是那个I那个那个那个那个那那个变量,然后把这888push呢put啊,对对不起。

put field就是把这888扔到I这个变量值里面去。所以通过这个读,你就能至少能大概读出一个什么信息来呢?它会首先所谓所谓的构造过程是怎么构造的?一个对象出来之后呢。

这个构造过程首先会调用负类的构造方法,然后呢才会把自己的成员变量进行初始化。

至少你能读读出来这个东西啊。然后你再继续继续学。

你比方说你再加一个str,你看看它的。他的他的这种。

二进制码是怎么生成的,你再加一个方法,看看它二进制码是怎么生成的。

如果说这个方法。

这是构造方法,你加构造方法,它默认的就没有了。你可以继续。再加一个这种方法,tablebo的M。一定要先简单从简单往复杂一点点慢慢来。加当你加了这个方法之后,你再来看。它的二进制码里边又包含了哪些东西?

就这样一步一步的整个class的文件你就慢慢全熟悉了。由于方法所牵扯的内容比较多,这个东西我们是放到下节课再来给大家讲。而且呢。当有了这个方法指令集之后,会有一些比较复杂的面试题,比较恶心的面试题。

我们下节课呢再来给大家讲,好吧。

系列 3:P114:【JVM】第二天课前复习 - 马士兵_马小雨 - BV1zh411H79h

OKOK好,咱们准备开始上课啊。😊,那今天呢我们上JVM的第二第二堂课。呃,今天呢准备给大家讲。classas的 loading, linking和 initialitializing。简单说呢。

我上节课讲了class文件的格式。那么这节课呢我准能给大家讲这个class文件是怎么放到内存的。classas loading, linking和initializing。好,在讲这个之前。

我稍微回顾一下上节课讲的内容。呃,我再说一下啊,上节课讲的内容你没有听,也不耽误上今天的课。JVM的很多课呢,实际上它是一个并行的,并没有这个前后的关系。呃。

我要讲GC其实呢你不听今天的课GC你也可以照样听。所以呢大家放松了听啊,有时间的情况下,把前面那堂课补一补就行了。呃,我们稍微回顾一下上堂课讲的什么内容啊。上堂课呢呃我教了大家呢。

就是你怎么去认识那个class的文件格式。也就是说当你看到这堆东西的时候啊,你起码心里头不再那么抵触了。class的文件这个东西呢,现在啊面试题里头还没有人问到过,好吧,还没有人问到过。呃。

不过了解一下,总是让你觉得心里踏实啊。上节课呢就是讲了这堆东西里头,这每个字节都代表的是啥意思?啊,主要讲的这个东西。😊,那。呃,我们简单回顾一下啊。就带着大家呢一点点的你就平记一来,好吧。呃。

还记得吗?前面四个字节是代表什么东西呢?class文件的一个魔术,imagine number这魔术是固定的对,cafeba。后面两个字节代表的是它的。versionion的小值部分。

minor version这应该怎么翻译啊?呃,后面再有两个字节代表的是它的major version。一般来讲,这是一个16进制数了。用JDK1。8编译出来的class文件,这个模数呢是34。

算过来的话就是52啊。算成时间制。你在用呃。整个的就简单说,整个的这四个字节代表的什么呢?代表的是这个class文念的version版本号。后面是最重要最重要的部分啊,也是最最容易让人混淆的部分。

就是这部分。这部分是什么东西啊?是一个什么样的结构的,我不知道大家还有没有印象。这个呢是一个线中池。sorry是一个常量池。刚起床呢,有点晕呢,还。这于常量池,这常量池是怎么存储的,它的结构呢?

前面两个字节是它的常量池的长度,那么后面呢是真真正正的常量池的存储的内容。呃,我不知道大家还有没有印象,就是后面存储内容里头是这个常量池有几项呢?你看啊,如果说我的常量池。呃。

它的长度上面写的是0010,哪位同学能告诉我一下后面这个常量池真正存储内容的时候存了几项。1515对,没错,为什么15呢?0010。转换成十进制是16,后面长度是16减1,所以是15。

当然这个常量池里面存的是具体的什么类型的话,大概得有十几种类型。这个大家回去查那个图就可以了啊。好,我们往后敲一敲。呃。传量池后面跟着的是什么东西啊,不知道大家还有没有印象。长两吃后面跟着的叫做。

access flags是吧?叫仿标记啊。仿标记说的是什么呢?说的是你这个lay啊,前面写的是public呀,还是private呀啊,是不是一个annotation啊。

或者是不是一个anumeration呢?是这些东西。再后面右边两个字节,这两个字节代表什么?This class。当前类。啊,face class当前类是什么意思呀?

是记录着嗯这个class的文件的名字吗?而字符串的名字吗?是吗?是这样的吗?这里面是不是记录着我当前字符串的名字,是吗?两个字节。不可能的是吧,我两个字节记录这名字,我记录不了几个字符的。

就只能记住两个字符。对,永远记着常量池,关键就关键就在于后面的所有东西呢都是去引用它的。所以这是指向常量池的类名的那个引用。好,再往后这个部分呢叫super class。好那好后呢。

super class完之后是interface count。interface count就是我这一类呢到底实现了多少个接口,后面呢就是一个一个一个的interface意。

一个一个的接口一个一个的接口。好,这个接口里边仍然存的是指向常量池的引用。好,账号fields。Pause。有多少个属性?后面呢就是一个一个的field。具体的属性是哪些?有多少个方法,mes。

Comm。后面呢就是一个一个一个的方法啊,他们具体的那个属性啊,me method infer。那好,最后一项呢叫attribute count。

然后里面存的是各种各样的 attributetributs,各种各样的属性。这个属性里面最重要的一项呢,其实是code是吧?代码。方法里面的代码。上节课呢我还教了大家呢用什么样的工具。

去来查询一个class里面内容,我不知道咱们同学下去试没试啊,这工具。

6。

show back code with G class library,用这个工具去看它二进制的内容。

这里面呢它会清清楚楚的帮你列出来constcent有哪些?

interfaces有哪些fields哪些,然后metters哪些。

嗯,等等等等。然后mas里面的。他这些生成的呃这里面内容呢,我们后面再来讲给大家听。呃,java的汇编指令呢并不是特别多,200多条。当然作为老师来讲,也不可能把200多条从头到尾给你解释一遍。

讲最常用面试题里头有可能会遇上的啊。

OK好,这是上节课我们讲过内容。

系列 3:P115:【JVM】类加载器 - 马士兵_马小雨 - BV1zh411H79h

那么今天呢我们讲新的内容,新内容呢是class的 loading linking lighting。那么这部分内容讲的是什么呢?就是一个class文件呢,是怎么从硬盘上到内存里头。并且呢开始准备执行了。

OK看这里。这个有一个class文店,它默默的呢躺在了硬盘上。需要到一个什经过一个什么样的过程,才能进入到内存里,并且准备好呢。认真看有这么几个步骤,有三大步,第一大步叫loading。

第二大步叫linking。第三大步呢叫initializing。三大步。在这三大步里面,第二步又分成三小步,第一小步呢叫verification,第二个呢叫preparation。

第三个叫resolution。嗯。笔记。新建一个笔记啊。我上次记得笔记好像不小心没存,啊,就特别讨厌。博上的笔记呢也也也没有什么太多的内容了。上记的笔记没有存,I'm sorry,太过分了啊。嗯。你给。

好,现在今天我们来讲这个那编译加载初始化啊。编译这个问题他说加载和初始化啊。呃。嗯。加载呢。因为呢加载过程呢是分成。这么几步,第一二呢叫loading。好,第二步叫linking。

linking呢又分成三小步,第一步呢叫verification。呃,第二步叫 preparation。

那么第三步呢叫。呃,第三步叫叫叫叫叫叫啥来着?

对不起啊,第二步应该叫做。第三个叫热字啊解析。好,那么第三大步呢。initializing。我们今天把这个过程呢呃尝试给大家讲清楚,这过程内容还是比较多的。今天讲完的话,我们下节课接着讲。

首先我们来看这个loading的过程,先给大家解释一下每一个步呢大概是什么意思啊,loading是什么意思呢?loading就是把一个class文件漏到内存。

它本来是在class文件上的一个一个的二进制,一个一个字节,把它装到内存里去。装内存里去。呃,装完之后呢。linking的过程,这三小步分别代表什么?verification是校验。

校验的意思是你你给我装进来的这个。这个class符不符合我class文件的标准?假如你装进来的前面四个字节,它不是这个cafeba。在这步的时候基本上就被锯拒掉了。O。这小步叫preparation。

这步很重要,这步是可以说是面试题有可能会被问到的。就这步呢是它是把class文件的静态变量附默认值接这一点。交负默认制。不是付初值。

比如说你静态文件里面有一个写的int I staticint I等于8。注意在这一步的时候,这个班并不是直接在这里把艾值复成8。我后面给大家举例子,而是先复成0付默认值。

接下来就行resolution resolution的意思是。这个class文件里面的常量池里面用到的那些。符号引用要给它转换成为直接的那个内存地址吧,可以直接这么认为。

就是直接你能够访问到的那部分的内容。做一步呢叫做initializing。 initialitializing的意思是静态变量的负值,这个时候才复为初始值。才调用静态代码块啊。先大致记这么一个流程。

后面我们一步一步来细细的分析。好,我们首先来看这个类加载器的内容啊。首先第一点需要告诉大家的是JVM呢。它本身有一个类加载器的层次,这个类加载器就是一个普通的class。这边M有一个类加载器的层次。

分别呢来加载不同的class。是我说这M里面所有的class都是被类加载器。给加载到内存的。那么这个类加载器简单说我们可以。把它叫做class load。好,看这里。嗯。嗯。

找到我们class load的部分。什么。😔,这class library干掉啊。嗯ん。第一个呢是我们整体的一个小例子,我们先。呃,不看整体的小例子啊,我们先看第二个小例子。

那么这个小例子呢来告诉大家呢,什么叫做class load。呃,我觉得多多少少咱们同学们稍微有一点点基础,应该都会用的。用过class load。不管你是故意用的,还是说超编代码用起来的。呃。

每一个class就是在我们的呃java虚拟机里面到内存里面的任何一个class都是被一个class loader load到内存的。那么这这个class loader呢。其实就是。顶级呢有一个副类啊。

这个副类呢就叫class loader,它是一个abstract class抽象类。所以呃。就相当于这个类是被谁领到内存里面去的啊,被谁领进去的呢?它一定是class loader这个类的子类。O。

所以这是他的顶顶级负累。当然。如果你想知道你这个class是被哪个class loader漏到内存的,其实很简单。就这么来写就OK了。比如说str这个类啊。

我想知道它是被哪个class loader捞到内存的,你就这么写stream点class拿到str class那个对象,然后调用它的get class load。其实说到这里呢。

关于class类的对象这件事啊。呃,我我我先从大面上跟大家讲这个class类的对象到底是一个什么样的东西。呃,一个class文件,这是那个sp的class文件。这个平时躺在硬盘上啊。

里边什么cafeba,就上节课里面我我们讲的那些内容,这个内容被漏到内存之后,内存里面到底发生了什么呢?内存里面呢实际上它创建了2块内容。别真听一个class被捞到内存之后,内存里面实际上有2块内容。

第一块内容是把这块的二进制的东西肯定是扔到了内存里。好,他占了一块儿。第2块内容指的是什么?与此同时,生成了class类的。class类的一个对象。好,这个class类对象指向了这块内容。啊。

不知道我说清楚没有,看大家能不能理解这个这这个小图。我再说一遍,当任何一个class漏到内存之后,实际上它生成了2块内容。第一块内容呢是这个二进制的这块东西确实被漏到内存,放到了内存的一块区域。

可以原封不动的扔进去。第二个呢,它生成了一个class类的对象。通过以后其他的那些我们自己写的对象。去访问这个对象,通过这个对象去访问。class类的文件。所以生成一个class类的对象。

这个class类对象是指向了这块内容。好,后这么讲,同学能能理解吗?class对象也是在堆中吗?class的对象。是在。嗯。class对象这个对象有可能是在met space,这我得查一下啊。

就这个部分。应该是在mettter space里面啊,mate space。嗯ん。当然一般也不会有人聊的这么细了啊,不是站不是站,注意这是克拉斯雷的对象,他不会不会是在站里面啊,t catch。

matetter space里面好吧,如果有人这么问的话,你回答mate space一定不会有问题。class对象也是new出来的吗?呃。它是不是new出来的。

它是hospot里面CI加代码load的过load的过程之中给弄出来的,它未必是调用了我们new那个命令,好吧。投资的mettter不是8之后才有的吗?对啊,咱们讲的是8呀。嗯。

内存分区这块咱们不是还没讲到吗?既然有同学问到,我就提前跟大家说一声内存分区的。呃,像存常量存classus的各种各样的信息的时候,实际上呢它这块内容啊逻辑上叫message area。

逻辑上叫这个叫mesger叫方法区。但1。8之前这个方法区的实现落地落地在什么地方呢?它叫做permanent generation。永久带呃,1。8之后呢叫met space。

所以这2块呢说的都是方法区,只不过呢一点。发之前叫perman generation。然后。一点半之后呢,就 meta space。这几个概念这么来区分的啊。

混制小龙class对象可以认为大class的实力吗?不是。你哦你也可以这么认为,但它是一个单例,好吧,就那一个就代表着那个class的唯一唯一的一部分啊就行了。嗯,今你们来分析一下。不知道大家。嗯。

以前的英国用过反射的同学应该会知道,呃,我们可以通过这个class这个对象呢去拿它的什么呃get declared methods,它到底拥有哪些个方法去拿它里面的方法,甚至呢我还可以通方法呢进行调用。

当然你分析一下,就执行这个的过程之中执行反射的过程之中,它一定是那些个方法的信息是存在了这个对象里。然后真正让这个方法执行的时候,它一定得去找什么呀?找那个class类文件里面的那些二进制码。

把它翻译成为java指令,一步一步来运行。所以。这个class类呢,平时我们说我们我们没讲到这么细的时候,就跟大家说哦,我我我们有一个class类的对象,代表着str。但讲到这里的时候。

我们知道class类的这个二进制的时候,你就应该知道实际上内存里面是有这么一个对象。但是真正访代表的是哪块内容呢?这这面块内容,只不过我们不能直接去访问这个二进制的东西。这样的话我们得自己解析。

所以我们通过一个class类的对象,通过他他帮我们解析好来去再去访问。啊,这个过程不知道我说清楚没有啊。好,我们不说,来看这个啊,继续看呃。因为class呢,它的class loader是谁?

可以通过这样的方式啊,str点 class。当然这个写法也可以写成什么呀?str点啊,get class就是你一个str对象的get class get class方法。

然后再拿它的get class load。他的class order是谁呢?我们来看看。run一下。关掉一部分程序啊。今天估计要拖堂了。

嗯。

OK我们看第一行啊,第一行显示的是空值。好,这里面呢就要跟大家讲这个类加载器的一个层次问题。呃,作为类加载类加载器来讲,它是这么一个加载过程。这个加载过程呢是分成不同的层次来加载。

不同的类加载器负责加载不同的class。最顶层的叫不tract。其实解需点就是最最开始的那个类加载器叫不str。它负责加载什么内容呢?负责加载。GDK里面最核心的那些个炸文件里面内容。

比如说run time点炸,咱们平时所说的这个sp screenring点 class呀,object点 class呀,都是位于这个炸文件里面,还有chse点 jar等等核心类。

这是由CI加实现的一个类加载器。所以什么时候你说我调用该 class loader,拿到这个类加载器的最后的结果是一个空值的时候,代表的你已经到了最顶层的这个类加载器。

好在下面是一个叫extension,叫EXT类的加载器扩展类。它负责加载什么呢?加载那些扩展包里面的那些个文件。各种各样的文件,这些扩展包在哪儿呢?你打开你的JDK的安装目录,你会找到有一个包。

一个目录叫EXT下面的那些炸文件,由它来加载。还有一个是我们自己平时类用到的类加载器,你么看是谁呢?叫做application APP类加载器。它是用来加载class pass指定的内容。

我们自己的class文件都是位于class pass里面,这个写java的人应该都知道它是由谁来加载,由他来加载。好,还有我们可以自定义的加载器。今天我给你讲到。自定义类加载器。你你加载你自定义的。

你你想加载哪的,你就加载哪的,就看你怎么写。认识了这个类加载器层次之后,我们再来看这个小程序。St class是由谁来加载的呢?OK是有我们的,我刚才说过。最顶级的是吧,它是空指。

说明是我们的butstr。第二个呢是你不用你别管这类是啥名字啊,实际上是那个那个呃我们核心内库里面某一个包里面的一个类,我随便写了一个。当你拿它的get class load的时候,它依然是空置。

为什么是空值呢?因为。它也是被我们的不str类加在器加载的。下面这个类啊这个3点net SPI name service这个类呢这个类是位于你自己去查它是位于什么呢?它是位于EXT那个目录下面。

里面的某一个炸文件里面,当你调用它的时候,get class load的时候,你就会发现它的class load是谁呢?来,看下面叫做EXT class loader。

Launcher下面的EXT class loader。所以它的那加载器就变成它了。那么你看啊,我们现在自己的这个类P002class load level点儿class,这是我们自己写的对吧?

它是由谁加载的?ge class load是由。APP class loader。所以回过头来再看这个图,我不知道大家能不能看明白了,就是有一些核心的内库。是被我们的btract就控制来加载的。

凡是位于EXT。这目录下面的里面的炸文件,这些个类被谁加载呢?被EXTclass load来加载。我们自己定义的这些自己程序里写的这些是被application class load来加载。

当然我们还现在还没有牵扯到自定义class load,讲到的时候再说。好,讲到这里,关于这张图,有没有同学有疑问的,有疑问你提没有问题,你的给老师扣个一,我你继续。对。Yeah。O。好。我们继续啊。

一会我们再来讲这个加载过程啊,加载过程叫双亲尾派。

很多同学是听过这个词的,应该。在这里呢有一个小问题啊,有不少的那个文章也好和嗯。不少的文章呃。还有呢就不少的这种这种书啊,我不知道为什么,每次讲到这个类加载器继成这个关系的时候呢。

总总会把这个图给抛出来。总要把这个图给抛出来,这个图呢很容易让人产生一个误解,你知道吗?我们说呀类加载器的这个层次是这样的,注意。内加载器的层次呢,我说。这个类加载器它的负类加载器。

往上叫APPAPP的附加载器叫extension ,extension的附加载器叫 strap。可是我们谈到这个负这个词儿的时候,是不是很容易和继承混了呀?

所以有不少小同学就会认为他的父亲是不是就是说在类的层次上,他是不是从application plus loader继承,他是不是继承于extenion class load,他是不是继承于不是所以。

千万千万别混了。有不少同学是一个混淆的一个关系。啊,这里并不是一个继承关系,好吧。所以尤其是有些那个呃文章和和和书啊。二话不说,讲完那部分之后呢,马上把这个图抛出来。其实这个图没有没有什么用的啊。

这个图讲的是什么?就是说这个class load在语法上是随时从谁继承的这跟刚才那个图没有半分钱,没有半毛钱关系。所以当你看这个图,然后脑子里记着这负这个词儿,又和上面图一混淆。

你就不容易认清楚class load了。我再说一遍,这个图你完全可以忘掉,不要去看它。这个呢只是在语法上,在语法上的一个关系。就是我们写publicap class load。

它的副类是extends从谁继承?从UIL class loader继成。UIL class load从seecure class load继成。

seecre class load从class load继承,也就是这么回事。是以分子在语法上的一个关系。但是真正的我们用它来去漏的呃class文件的时候。是说我如果找不着。

这个类是不是我我我我我有没有把它加载过,我我委托给谁去找啊,委托给我的附加载器,注意附加载器不是继承关系。

系列 3:P116:【JVM】双亲委派 - 马士兵_马小雨 - BV1zh411H79h

好,所以这个图呢你你心里很有数就行,好吧。就烦讲着讲着,突然之间呢讲了两个体系啊,然后又又没说清楚嗯。那下面我们来讲的就是双切维派到底是个什么庸。当然还呃这这个后面还有两两段小代码我没有讲完。

你你注意看啊,你仔细看你看。

呃。snet SPI他的class loader,也就是这个class loader。刚才咱们看到了,它是1个EXT的class loader。

那么这个ESC class loader调用它的get class,它本身也是一个class呀。然后调用他的class loader。他的class loader又是谁?

就是这个class loader的class loader是谁?你会看到控制。说明啥,这个class load的class loader。是我们的最顶级的。那个克拉斯罗他给绕进来的。其实。所有的。

这个我们的class往上头找的话,最后一定是被我们最顶级的那个bustr class loader给load进来了。所以过程就是这样的啊,bustr class loader把谁给漏进来了呀,把。

EST的那class loader load进来,再他再去负责load别的。然后呢。像这个这是我们的APP的class loader了,他又把APPclass loadload了进来。

然后他再去load别的。这是被谁加载的?加载器的加载器是谁啊?所以你也不知道混混淆成什么样的,说加载器的加载器是不是就是他的parent,不是。parent是加载类的过程中需要查找的一个层次关系。

至于这个parent它是被谁加载的那是两回事儿。

那千万这里面容易混淆的概念呢非常多啊,要三个三条线混一起哈。😊,呃,面朝大海问说那个bstr为什么返回空,是因为呢不str呢。呃,是由C加加来实现的。java里面并没有一个class和它对应。

因此呢它返回的是一个空值。嗯。book drive加载器是什么呢?是C加加实现的一个模块,可以这么来认为。

嗯。不 drive。它本身是java虚拟机内部用CR加代码写的来实现的这么一个模块。在java里面直接访问呢是没有一个class和它去直接对应的。因此。

当我们get class loaderge到头的时候。这个时候他只能给你返回一个空值。所以当我们看到这个空值的时候,它代表啊你已经到头了。好。我们说一个class文件需要被漏到内存的时候。

执行的过程呢是这样子的啊,认真听。一个class文件需要被漏到内存的时候,执行的过程什么样的呢?任何一个class。假如你自定义了。那么这个时候呢,就先尝试着去自定义的这个class load里面去找。

他内部维护着一个缓存。说哥们儿,你有没有把我已经加载进来了?你如果加载进来一遍了,你就不用去不需要再加载第二遍了。你如果没有加载进来。你赶紧的把我给加载进来。这个过程你先听一大概啊。

因为后面我们还没有讲这个class load的加呃,就自定义的class loader,一会儿我我会给大家演示。那好,然后他如果在自己的这块缓存里面没找着的话,注意他并不是直接加载这块内存。

直接把你这个克文件。二话不说给你加载进来。不是不是这样的,他会去他的父亲附了附加载器。APPclass load里面说。爸爸,你有没有把这个类,比方说这个类叫S吧,把S给我加载进来啊。

那APP里就会他去他的缓存里面去找我认为有没有S呀?如果有返回了。如果没有。委托给他的父亲去找我这里面有没有S呀?好了,如果有范位如果没有。委托给他里面去找哎。找他爸爸,你有没有S呀?那,如果都没有S。

bos drive呢就往回再委托。我这没有S啊,麻烦你去给我加载。严森生说我只负责加载这部分,那S我找不着啊,找不着怎么办?哎,麻烦你给我去加载APP说我只负责加载这部分啊。其他的我我我我不知道啊。

我找了半天,反正class pass里面没有没有怎么办?哎,委托你给我去找。整个过程。最后是经过了一圈,转了一圈,才会真正的把这个S给加载进来。

当我们class custom class loader能够把这个S加载进来的时候,好,叫做叫做成功。如果加载不进来。跑一场哪个一场啊,class not found。找不着。好,这个就叫做双亲尾派。

O。不知道这个图呢大概清楚了没有?我后面画了一个动画。每次给大家画动画啊。嗯,我都都快崩溃了,因为每个动画画起来都要画一个小时,给大家演示不到一分钟。好,认真看。认真看。看这里啊。

有一个class文件需要被加载到内存的时候。他首先呢调用你自己定义的那个class文件的load class这方法,把自己给load进去。找到我们的克拉自自己定义的这部分。嗯,如果说他。找一下。

在自己的缓存里找找找。如果说找到了返回结果,如果没找着找到他自己的负类加载器,谁呃谁呢?附加载器啊,不叫叫负类加载器,附加载器谁呢?APPclass load。如果找着了返回。如果没找着。

找EXT的class load。如果找着了返回,如果没找着,找不str class load。不scribe class load找着了返回。如果没找着的话呢。回过头来,又让EXT你负责去加载好。

这个时候是加载啊,是找到这个class,并且加载了。原来呢是在cch里面,在缓存里面找,有没有找着。那如果加载成功了,那就返回结果。如果说加载没成功,我找不着我在我我负责的这部分里面这个小区里面。

我找不着这个类怎么办?交给他的孩子,他的孩子去找并加载。如果找着成功,如果没找着交给他自己的孩子,他自己的孩子找着成功了,成功就返回结果不成功。class not found不知道大家看完这个动画之后。

是不是理解了class的load的这个过程。这张图你抓一下吧,好吧。老师,我画张头,画了一个小时快。一分钟就演示完。面朝大海问这个缓存是在哪儿?缓存你可以这么简单的认为就是它自己内部维护的一个容器嘛。

一个list或者呃一个一个数组加载的东西都扔在里面嘛。每个加载器都有自己的缓存。对每个加载器都有自己的缓存。他负自己负责哪部分,就负责哪一块啊。好当,你明白这个双亲委派的过程。

这双亲呢这个双亲尾派这个词儿啊起的也不是特别好。呃,双亲委派。双亲委派这个过程就双亲,一般我们指什么呀?父和母嘛?父母双亲双亲俱在。所以这个东西说叫双亲尾派的这这个这个这个词儿起的过特别好。

其实双亲尾派指的是什么呢?指的是是由一个从子到父的过程,又有一个从父到子的过程。这叫双亲。啊,所以这个名字非常的怪啊,翻译有问题。对嗯。嗯。好了好了。那下面问题就来了是吧?为什么要搞双击委派啊?😡。

你给我一class,我直接给你漏到内存不完了吗?你你你搁那扯什么扯,你我非得找我到我后期里找找找同学们为什么呀?好,这是面试。如果问到内加载器是属于必问的一个问题,就是Y为什么?为啥?为啥要搞双清委派?

不知道有没同学知道的。清然,你说的对啊,你理解的没问题嗯。好,听我说主要是为了安全。主要是为了安全。说安全跟这有关系吗?有关系。哦,我们假如用反正法,假如给你任何一个class。

你自定义的class都可以自由的把它漏到内存的话。那么我就可以给你这么一个class,这个class叫java点儿 land点儿stream。哇,这牛叉了啊,我我这个class叫java点烂点str。

我直接把s就是oracle自己写的那个内部的核心的sring给它给它覆盖掉。我交给我的自定义的class loader。然后把这个str漏到内存。接下来呢我把整个的这个东西打包成一个内裤。

我交给我的客户。大家知道我的客户在输入密码的时候,他应该会把这个密码存成一个sstreamam类型的对象。哇,太棒了,把你的密码存成一个spring类型对象。我这个spring类型对象。

是反正这部分代码是我自己写的嘛,java点 line点 string是我自己定义的这么一个str。我干脆直接把你的密码偷偷摸摸的发给发一封邮件发给我自己。哇,全世界的密码都到我这儿了,太爽了。

只要你拿java写用过我这个内库,你的密码。全是我的。你们会想想看是不是会有这种问题。但是如果采用双亲纬派,就不会有这个问题。当我们要求一个class。

class自己定义的class loader去加载一个java点line点s stream的时候,它就产生了警惕。我得先去上面查查有没有加载过。查查查查到最上面的时候,发现已经加载过了,加载过了。

直接给你返回。睡啥话。我还重新给你加载啊。好了,所以当有人问你为什么类加载器要使用双亲维派机制的时候,注意这是面试经常有可如果问到这部分,基本就会被问到的问题。为什么要使用双切维派?主要是由于安全问题。

大家听明白了吧?当然还有几个次要的问题呢,就是你你你上面已经加载完了,我就不需要重新加载了吗?我为什么要加载两次,我找找看就行了,这是一个资源是不是浪费的问题。但是这个是次要问题,主要的问题是安全问题。

嗯。😊,好,感悟感悟说既然是自定义。要是我不去上机照,自己可以加载。你以为这么简单不可能的,一会儿我们累加载器写的时候,你就明白了。这个。这个过程是已经写死了的,这个过程是已经写死了。

你只能去实现查找class的那部分啊,这过程已经在内部写死了,好吧。这事儿你是改变不了的。啊。

系列 3:P117:【JVM】父加载器 - 马士兵_马小雨 - BV1zh411H79h

好,双击纬派双击纬派呢附加载器注意千万注意这个附加载器不是类加载器的加载器,千万别这么认为类加载器的加载器。你就是APP的,它也是。putstr的它它它也是空值。那么EEEXT的它也是空值。

但是APP和EXT之间还存在一个父子关系。所以附加载器不要和其他那种语法上的东西混一起。负加载器并不是类加载器类加载器,也不是类加载器的负类加载器。我要把这个跟大家写清楚,就特别容易混淆的地儿啊。嗯。

He以。😊,い。附加载器不是累的。类加载器的加载器啊。😊,也不是。累加载气的。负类加载器,这是无法问题啊。副加载器如果从源码上来理解。源码理解附加载器,很简单。

这个class的对象里边有一成员变量叫parent。这parent什么类型的?class loader类型。我们所说的附制加载器指的是这个parent对象。这个判他经指定为谁,他就是谁。我认可指定。

甚至可以指定我自己定义的那个可以的,没问题啊。呃。我们来看这个小丽的程序。

啊,大家看这里啊。

刚才我讲了这些概念之后呢,我们来看这段代码,看大家能不能看得懂。然后呢,你理解一下到底什么意思。看这里。T004,然后拍完点che点class给class loader好。

告诉我一下这个class loader是谁。在APP没错。那接下来呢他get到class load之后,再geclassge class loader是谁?

控制没错。好,下面这个get parent ,get parent啊,同学们就class logo里面有一方法叫get parent。注意,这是它的附加载器,它附加载器是谁啊?啊,EXT。

ge parent的ge parent。

又是谁呢?

啊,那get parent的get parent再get parent。

我把它住掉了,因为你想想看一个空指针在盖pyon的报啥错。控制人错嘛嗯。所以你看这个结果。空制空值。He。

嗯。😊,运行的有问题啊,运行的刚才那条程序。

重新跑。他的父亲是APP嗯,不是不是他父亲,他的累加载器APP雷加载器的。类加载器的加载器控制类加载器的附加载器。EXTclass loaderEXT的class load的附加载器。

控制。

系列 3:P118:【JVM】类加载器范围 - 马士兵_马小雨 - BV1zh411H79h

我们看呃各个类加载器的一个范围。类加载器的范围,我说过它是来自于launer的原码。有同学说啊。什么意思?看这里啊。呃。找到我们的。Class load。我们来读一下这个原码啊,大大大概大概理解一下嗯。

该 class load。嗯。不是跟class load,这个应该是。刚才我们打印的时候呢,一直没有呃关注这块。呃,launer。

就这个类。launcher launchcher启动器在我这我们刚才打印的时候,可能大家伙没有仔没有仔细看这段啊,把termin调出来看看。软点来看啊,你注意看啊这部分呢其实我没给大家细讲。

其实呃呃这这个我们说打印一个class文件的to string的方法,它默认显示是什么呀?是类的名字加后面的他的还是code的一个码嘛。那类的名字呢,你看这个类的名字呃。

这种类的名字大家我不知道能不能理解。这什么意思呀?是smisslins下面的包下面的launer这个类,这个类下面有一个内部类叫EXTclass loader。对,这是它内部类的意思。好。

这个launcher是个什么东西呢?这launcher呢呃其实就是class load的一个包装类,一个启动类。好,在这个类里面,其实它你你要看这个代码的话呢,你能够看出很多内容来。

就是说我们是怎么看出来,我说不 strap它加载的这个呃路径是。我们的核心路径,而EST呢是指的是呃EXTDIRS指定的这个这个属性指定的一些路径呢?

我们的ja为为什么我们都APP class load指定的是java class点pas这个路径呢?其实所有的代码都是来自于launcher它的源码。laer原码呢。

你看啊boot boot class pass和你指定的是这个sstem get property。散步的 class pass。嗯后面呢。代码读时间很长了啊。java点class pass,这是谁呢?

这是。APPclass loader看到了吧?它内部类APP class loader,它负责加载哪部分java class pass。system的属性这部分。那好。

那ESCclass loader负责加载哪部分呢?负责加载这部分java点EXT点D2。

所以如果你呃说老师你讲的这个我能不能验证一下,你可以完全是可以通过这种方式来验证,怎么验证呢?看这里。

这验证呢也非常简单啊,其实讲原理的这种小代码呢都比较简单。看这里。你就这么来写就行了。呃,boot的 class pass是哪些。

你就拿到这个属性stem get property拿到这个属性之后是一个长的字符串,我把这个字符串里面的分号来替换成为换行符。嗯,stem lines,这比较简单啊,大家读一下代码。

给10秒钟看能不能看得懂。就是我拿到这个属性,我看这个属性啊,系统的属性里面这部分刚才我们读源码的时候不看到了吗?这部分代表的是哪部分的内容啊,我们把它读读出来。把符号换成换行符给大家展示一下。好。

第二部分java EXT direction呃 directions。directries啊java EXT的扩展的那些个目录在哪里?javaclass pass呃。

我这个程序定义的这个class pass又指的是哪个?跑一下看看。好,中间是用横线隔开的,我们一个一个来看。

通过这个小程序,你能够很明显的看到哪些炸包是被我们的bstr加载的这些。这一个1。8杠01GRElibr下面的resource点诈RT点炸。呃。上R呃。

RSA sign这是加密的GSSE啊GCE叉SJFR以及GRE下面如果有这个目录class。这下面的class是被我们根儿加载器加载的根上的加载器。好,那就继续。还有。对我们的EST。

那个class呃loader来加载的是谁呢?EXT目录下面的。EXT目录下面这些个炸包是被他加载的。那对我们的应用程序的这个呃来呃APPclassro加载是谁呢?下面这些。一对。看这里主要是看这个。

productdion这VM这是我的什么呀?这是我的。呃,像项目的路径嘛,他会去到我的项目路径下面去找。

呃,下面这个呢是idea啊,自己帮你指定的啊。

系列 3:P119:【JVM】自定义类加载器_1 - 马士兵_马小雨 - BV1zh411H79h

啊。接下来呢我们来看看呢怎么样呢才能够自定义一个类加载器。呃,想自定义类加载器的话呢。근得要。稍微的嗯。读一读这个class loader的源码。简单读一下啊,看这里。谁带大家读。你静下心来。

现在呢你静下心来跟着我的思路走,好吧。呃,读这个原码呢稍微的有一点点复杂。如果你没有学过前面的老师讲的。设计模式的话读起来呢会稍微有点复杂,不过解释给你听莫急啊。在 class load。

最顶级的副累abstract class class loader。我们先说第一件事,就是你如果说想把一个。类给加载到内存的时候,你应该是怎么做?呃,想把一个类加载的内存的时候呢。

这个小例子就是load class by hand,我们我们用利用。现有的这个类加载器去加载一个类的时候,去怎么加载。注意看是调哪个方法呢?是这样来调,看这里啊。呃,这个类。

T05low class by hand点class get class loader来,大家告诉我,这时候我们会拿到哪个类加载器。APP是吧?APP好,拿到这个类类加载器之后,我只要调用它的一个方法。

叫load class方法。接下来呢我把你需要加载的这个类的名字告诉他。他就会帮我加载进来。所以首先第一点,load class这个方法。大家先要认识一下,就是说你要加载一个类,很简单。

你只需要调用class loader的 load class方法,就能够把这个类加载到内存。那加载到内存,它会给你返回一个class类的。对象。也就是我刚才讲的那个过程,它会硬盘上找到这个类的源码。

这类源码呢可能在哪个目录下面。好,找到这个class文件源码之后,把它漏到内存,与此同时生成一个class类的对象,把这个class对象返返回给你。所以它返回的是一个class类的对象。因此。

我们这个小程序。Note class by hand。我找到APPclass load调用它的load class方法,让他帮我去load的T002class load level。没问题。

可以load进来。load进来之后返回给你的是class类的一个对象,我给他起这编列名叫class。接下来我就要用class点 get name,那么正常的话一定会返回我那个。T062那个类。

OK大家看到了,它返回的我的类的名字T062说明已经正常加载了。如果大家我不知道有有因为有一些新报名的同学啊,你以前应该可有可能没有看到老师讲坦克的时候,坦克一期那会儿呢我是利用一个类加载器来加载资源。

大家我不知道大家还有没有印象啊。呃,有多少同学那个听过坦克这部分呢,就会应该有印象。我是利用类加载器呢来加载坦克以及图片的资源。

Get class loader or get a resource as stream。所以class load呢能帮你干很多事情,能够帮你去加载各种各样的东西。如果你像想加载某个类的时候。

你直接调用它的low class方法。嗯。嗯。折子细说和反射的区别是什么?这个这和反射有什么区别?class load是反射的一个基石。你平时用的所谓的反射。

无非就是你用的class类的这个对象去访问二进制的这些代码。这不就是反射吗?这没有没有嗯聊啥区别,这没有区别。他是一个。相相辅相成的有关系啊。风林说什么时候需要自己去加载呢?哇,风林。

你问的这个问题相当的有深度啊。同学们什么时候需要自己去加载一个类啊?来有哪位同学说一下。什么时候我们需要去加载一个类?嗯。呃,学过spring的。s会某一个classs会给你生成一个。

动态代理这个动态代理是一个新的class。那么当你要用的时候,实际上spring偷偷的漏的把这个新的class给你漏到内存了啊。呵。给你放内存里了嗯。嗯,好多有网络的问系。没错嗯。

toom get对load自己自己那部分,它肯定是需要load load load load自己的自定义的这些class的。这日报。前面一边老师讲过的这be热部署,怎么才能热部署啊大哥。

你这个class放到那放到硬盘上,我是怎么才能给你进行热替换,怎么是热替换呀,我肯定需要一个class loader,把这个。手动的漏到内存里面去。还,不知道我说清楚没有。But。哦。

我看刚才好像面朝大海也问了个问题啊,给刷过去了。等看。面朝大海问,加载进去就生成class对象吗?不是要经过初始化才生成class对象。初始化呢一会儿咱们再聊吧。初始化呢是把它的。呃。

静态变量进行赋值是那个过程。初始化不不不不初始化啊初始化不是实力,你说的实力得去调用了谬了。那个昧方法呀,已经开始执行了才有实力的概念。那方法开始执行了,才得里边才可以没有实才有实力的这个概念。

这里的初始化呢指的是这个class load的进去。生成。指向那个class的对象,然后这个对象里面有一些静态的东西,这个静态东西是不需要实力,不需要new的,不需要ma方法执行的。好。

这个初始化过程我们一会儿再说,好吧。你讲到了啊,别着急。哦,我先讲完的这部分,大家能不能理解?就是我们需要加哪一个类的时候,是调用它的low class方法。

下面我们就来看看呢这个low class方法,它一个核心的。核心的他的这种执行的逻辑到底是一个什么逻辑,也就能够呃告诉大家,为什么你是不能够。改变这个逻辑不能够去。刚才有同学问到了。

说我我干脆就不找我的副累行不行?不行,因为它里面已经写死了,这个low class是已经写死在里面了。好,我们来看这个loc class代码。loc class代码呢。他调用了另外的一个。呃。

重载的方法,这方法叫loc class,就是你需不需要解析。解析刚才我解释过了,把符号引用转换成为直接访问那个地址啊。呃, synchronize的一个log,这个你加载的时候呢,一定是要加锁的。

别我加载了一半,另外一个也加载了进来了啊,加了加了把锁。find loaded class这部分是什么呀?first它在注释了。first。

check if the class has already been loaded,你是不是已经加载进来了?那么这部分呢。是你读到最后的时候,它返回的是一个呃find class loader0。

当你 class load零的时候,你就只能去读java虚拟机的原码了。hosbo原码。因为他已经是内地了。喂。嗯,在这儿读过只要心里原码呢,嗯如了,这不是不是这个这个这个黄老师读过啊。

他后面会给大家分析分析hos胞原码。如果大家感兴趣听一,不感兴趣的话就算了。一般呢也不会问到这种深深入到这种层次的问题啊。好,看这里。呃,这个class has already been loaded。

你检查一下是不是已经漏进来了。如果等于空的,没漏进来怎么办?如果漏进来直接返回了就啊,如果漏进来直接返回了。所以如果等于空没有漏进来,没有就没有漏进来的时候才去漏的。漏的时候怎么漏的呀?啊。

parent调用他的parent。去load class,所以这就是开始委派过程了。没有漏进来,我得先去调研parent,parent上来是不是也得先找啊。

你分析一下parent的load class不也是这个代码吗?他上来也是先找。而没找着怎么办?又调用了4类的那就就继续继续找嘛。一知什么如果说cch里面找到了,那就不用了,不然的话呢。

我们就调用low继续来load。那这个loadload的过程呢,所以这呃我相信大家应该就能理解这这个呃过程了,这是一个类似于递归的一个调用。

类似于D位的个调。所以首先呢去找catch里面,如果找不着的话,让他副类去look class look,而他副类look class时候上来也是先找,有没有找着?然我们继续看啊。

这个load class。如果说呃我副类没找着,副类没找着,都没找着,那我就必须自己去加载的时候,自己去加载的时候怎么加载呢?哦,我先给大家看一下这个parent啊。

你看啊每一个class loader,它内部的这个parent是一个final值,已经指定了,连改都改不了。所以他就决定了你是改不了你的这个parent的,你也你也没办法去去修改整个的过程。你放心。

人家设计的这个时候不可能给你留下这么大的漏洞。好,我们来看这个加载的过程啊,加载过程怎么加载呢?😊。

也就是说经过了上面这步,我也没找着,然后我的负累也没加载成功,那说明只能交给我自己去加载了。我再说一遍,上来呢先找。

哥们儿,我我有没有加载过我的cache里有没有?如果有就直接返回。如果没有等于空吧。如果没有,如果没有找副类,让副类去加载,负类加载上来也是先找嘛,所以是从上的这个过程。假如说一直涨到上面。

一直都没找着。

那我只能由我自己去加载,对吧?只能由我自己去加载的时候,怎么加载的呢?注意看它调用了一个方法叫做find class。你去找这个类。

好,这个方法。这方法的实现只有一句话。这个方法protected。受保护的。只能在它的子类里面去访问。其实通过这个,我不知道大家能不能够想出来,我自定义class loader该怎么定义。大家看这里。

在class load里面,find class最终呢我们是要调用fin class的,可是find class它的一个实现直接抛ll了个异常,class not phone exception。

那怎么办啊?很简单嘛,你自己去实现这个方法吗?那这个过程我们再分析一下,现在是不是通过那个原码能看明白了。首先上来呢,我先自己找,对吧?我自己找,如果说没找着,我调用负类load class。

可是负类 load class是不是也是上来先自己找啊?类 load class是不是也是向来先自己找啊,如果没找着,是不得交给我自己自己去录的啦,我自己去的,他说是不是调用find class呀。

同学们。😊,所以我们自定义class loader,我只用干嘛?重写find class。每个副类都有f class,那必须的啊。嗯嗯,launer里面。不是负类啊,其实应该是负附加载器。

你看这个呃呃本身那个ES class loader是从URL class loader继承。那URL class load是从secure class loader继承。

secureecure class loader呢。是从克拉 loader集成是吧?好。我们来看这个URLclass loader。也就是这U克 loader里面。

7。哟可修的看到了吗?find class。这他不就有实现了吗?你自己去就是他这个实现你要感兴趣就看一看,不感兴趣就算了,无非就是那个在目录里面找嘛嗯。

那你从EXT是从那继承的那EXT当然也有自己的find class了,是吧?所以你想想看,如果我们要自定义一个class loader的话,我们怎么办呀?我们只需要干一件事就就可以。

我这么简单,能不能理解?呃,我只需要干一件事就可以。我只需要。定义自己的find class就可以了啊。

系列 3:P12:【多线程与高并发】课程规划 - 马士兵_马小雨 - BV1zh411H79h

好同学们,我们开始上多线程和高并发的,2019年的第一节课,我首先跟大家交代一下,在2019年的这个版本里头,我给大家讲哪些方面的内容,呃,那么老师呢会给大家讲多线程和高并发啊。

这两大块儿应该说怎么说呢,就这两大块啊,是现在面试他问的越来越多啊,也是你从一个一个相对初级的程序员,然后像比较高级,中高级的这方向的迈进的,一个必须要踏过的一道坎儿,呃,我先跟大家简单交代一下。

就是后面会讲的哪些方面的内容,无论如何呢,这些方面内容呢都会给大家讲完,呃我的预测是4~6个周末啊,这个不一定能够讲完,如果讲不完的话呢,呃咱们再往后就拖一拖,另外呢呃老师讲完这块儿之后呢。

会讲那个jvm呃,原来排的操作系统的课呢,排在jvm后面会比较合适一些,呃我后来考虑了一下,因为先讲操作系统,其实呢它里面呢也有很多同步的东西,那么同步的这块呢,实际上和多线程和高并方案有些冲突。

我们不如先学最直接的,学完这个之后呢,我们先学再学jvm,jvm也是离我们最近的嗯,金九银十,你要是想去跳槽的时候,马上能用得上的好,在这个之后呢,我们再来讲操作系统。

其实你理解起来呢会更加相对容易一些呃,我会尽量的不和其他的课冲突嗯,每个周末的上午,这个周六或者周日,为什么是,或者主要是要照顾一下,黄老师那边的源码课,因为黄老师那边他的时间并不是特别固定,呃。

他还是在一线在上班,所以呢我能照顾他一下啊,就是这个意思。

呃我大概讲六大块儿呃,第一大块的基础的概念,什么线程开始啊。

今天我们基本上就能把基础的概念,应该讲差不多,第三块呢是同步的容器,第四块线程池呃,第五块呢是高频的一些面试的东西啊,第六块呢是呃disrupter。

呃,不知道有多少同学听说过这个框架的,这个框架呢,它也是一个mq框架。

嗯,我把我的画图软件调出来,那么这个框架呢也是一个mq的框架,好,这m q叫什么呢,叫message q,小消息队列的是吧,消息队列呢非常多,后面还会有老师给大家讲那个嗯actim q啊,卡夫卡呀。

这些都是消息队列啊,好我给大家讲的这个,如果你能在简历里就体现出来,并且能够跟面试官说清楚,这是10000%的加分项目,呃这个呢是叫做destructure,应该来说是目前大家伙公认的,在单机环境上啊。

效率最高的,性能最快的这样一个m q啊,讲到的时候我们在聊这个问题啊,得需要了解前面的关于并发的。

这部分的内容。

系列 3:P120:【JVM】自定义类加载器_2 - 马士兵_马小雨 - BV1zh411H79h

只要存在就不会被重新加载了啊。

我们来看这个自定义自定义的加载器吧。在这里啊自定义。

好,自定义类加载器有好多种方式了,最简单的一种从class load集成。呃,这个呢。刚才我们分析过,你只需要干一件事,重写它的find class方法就可以了,就OK了。呃。

大家看我重写这个find class方法的过程啊,重写这个fin方翻呃find class方法的这个过程呢,会用到的它的一个辅助方法。这方法呢叫deffinine class。

这个class这个 class呢一会儿我呃这个方法呢一会儿我们简单跟大家说啊。好,再看这里啊。fi F等于new file我创建了一个文件,这个文件呢是位于C盘test目录下面。

然后你传给我的名字,你传给我一个,比如说这个名字co马士兵JVMhello这名字。

然后我把这名字呢点儿替换成为斜杠,那就是找到了它的全路径,最后加上它的克拉苏截名。这个fiel呢其实指的就是哪个哪个fi呢?大家来看一眼啊。

C以。Test。🎼下面有comme马士兵JVM。然后下面hello点class,其实就是这个这个这个类的全路定名吧,就是整个。

呃,类类的类的文件文文件路径,再加上类的名字啊。

嗯,绝对落定。

我你找这个范,我们怎么才能够把它给漏进来呢?是这样来做的。F input stream, to input stream by the array output stream。

把它转换成为一个二进制字节数字节数度。从文件里读出来,写进字节数组里。协数字接数组之后呢,把它转换成为一个二进制的字节数组。转完了之后呢,怎么把这个二进制字节数组给变成一个class类的对象呢?

刚才我们说过,我们说是另外一一个流被我们加载进来,加载进来之后呢,是一个二进制的东西嘛。二进制完了之后,我怎么能把把它转换成一个呃class类的对象呢?用这个方法deefine class。

这方法呢也是在我们class loader里面定义好的,你直接拿来用就行。deefine class。Deite as。是把这部分的二进制的东西转换成为的类的名字是什么?空满是兵GVM排lo。好。

字节数组。是转换成了哪部分的内存里面的位置,字结束的起始的位置,0结束的位置,字接束的长度。相当于整个自己收组。通过这个方法,我就把它转换成为了一个class类对象。

所以总而言之,想调用一个class load呃,想自己定义一个class loader的话。

很简单,我们就是从class楼这继承,继承完了之后呢,重写它的fin class方法。

在fin class方法里面,我们找到。你要load进来的那个二进制的内容,在内存里面给它完完整的load进来。录完了之后呢,再把这个内存这部分内存转换成为一个。class类对象用哪个方法能?

用deeffinine class。搞定了啊。

就OK了。那说这东西怎么用啊,这么来用,看这里。

class loaderL等于6T006MSB的class loader。这是我们自己定义那class loader。然后我们要想加载一个class的时候,load class。

co马士兵这边Mhello。就能录进来,我们用反射去访问。他的方法啊把用反射呢把它弄出来一个对象扔在这儿。然后调用它的M方法。啊,跑一下。

只要能漏进来,说明就没问题是吧?大看啊,hello这VM。😊。

已经调用完我的方法了,比就说已经漏进来了没问题。然后呢,L点ge class get class loader,就是我这个class loader是被谁加载进来的呀?是被我们的APP。

而L点geparent,他的父亲是谁呢?也是我们的APP。

好,这就是自定义class loader啊。自定义class load呢。

呃,写框架写内库的时候是基本上都要用的。spring有自己的class loader to care有自己的class loader。有自个class loader之后。

你想 load自己在某一个指定目录下面的class文件,你就可以用这样的方式去load的了。好,这就实现了一什么呢?这就是我们自己的自定义的那个class load。刚才我们看到。

由于他的父亲是我们的APPclass load,所以如果需要加载一个类的时候。他如果先先去他的父亲里面去找。他会去找这呃马士兵下面的马世斌的下面的海low。你你你你加载过吗?问他的父亲,他父亲是谁呀?

刚才看到了APP吗?他父亲在里面找了找了一下,说我这儿没加载过。但是我要问我的父亲好,他父亲是谁?EXTEXT你加载过这个这个这个hello这个吗?那EXT说我没加载过。找他的附亲。

不str不str说我也没加载过,我也没加载过,我我我我我尝试加载一下啊,你等着我我去加载一下。但是我其实上是没没有办法去加载的,原因是啥?原因是我在我的这些个站文件里面是找不着这个类的那那对不起。

那那你只能你你只只能你自己去加载啊,那我行,那这个这个ES就说那行,那我自己去加载吧,他找了一下说我这个也不也不够我加载,不够我加载怎么办啊,那那对不起,只能让我的孩子去加载,那孩子去找了一下,说哎。

不对啊,这个我也找不着为什么?因为你想想看C盘test,这是在我的classclass part下面吗?没在,所以我也找不着,我也找不着怎么办?哎,算了。我们自己定义的这个class load。

那不好意思,你去加载哦,那行,那我我我既然去加载,我就加载了,调用我自己的load class。😊,调用load class的过程呢,找了一圈,fin现都没找着。大家回回想那load class代码。

是不是到最后得调用我的find class啊,那我就去调用我的自己的find class。😊,好,我在fin class的时候。

哎,我去找了一下,但我这有自己的fining class吗?哎,我找了一下,把这个文件给找着了。找着了之后呢,我就给它转换成反馈给你。

不就OK了吗?

嗯。嗯。或制角云可以直接漏炸吗?漏炸的意思不就是你找到那个炸文件,把里面的classance挨着牌的全读出来,全漏进来,不就叫漏炸了吗。一般不会去漏的整个这文件。呃,java的这个加载呢叫做懒加载。

需要的时候才加载。叫lazy loading叫懒加载,需要才加载,这是一个比较细致,特别繁琐的内容。

系列 3:P121:【JVM】加密 - 马士兵_马小雨 - BV1zh411H79h

看这里啊。嗯。后面讲的这个内容呢呃应该讲的就是算是给大家扩展,算比较好玩的内容了。啊,谈不上你必须得掌握的,好吧,我们所以我们放松了来。呃,我我们我们来聊这个通过自定义class呢。

其实你是可以定义那种自己加密过的class,就是你你给自己的代码加密。大家知道这java的代码class文件很容易就被反编译了,是吧?但是我要是给你自己定义自己的格式,我不想让别人反编译。

这时候怎么办呢?你可以通过自定义的class loader来进行。好的,看这里啊。通过资义class load来进行,我我我是这个小程序给大家做了一个小演示啊,这个当成一个兴趣点,了解了解就行。好。

注意看。我呢做了呃一个加密的操作啊,怎么做的呢?是这么来干的。呃,ink from是加密呃,加密我干了一件事儿,就是平时啊同学们一般的情况下。这知识点要扩展起来也特别多。好。平审就一般的情况下。

一个classus文念,它不就是一个二进制的。二进制流吗?呃,然后呢我编译好了之后呢,自自己手工编译好了之后,我我把这个class文件给它加密,怎么加密呢?我这里采用的是最笨的,特别普通的办法。

就是抑惑对某一个值进行一个异惑。呃,大家知道,如果对某一个值进行抑或,抑或完了之后再抑或这个值就相当于解密了,是吧?如果你不了解这块啊,二进制的二进制预习的内容ok。回去回去翻。就无所谓。总而言之呢。

我抑惑一个一个数,然后再抑惑他一下,我就回到原来的值了。有同学对这有没有同学对这块有疑问呢?就抑惑一下,双抑惑就回到了。有问题同学你直接扣2,没问题同学扣1。对我菜鸟也是讲过的对啊。

那所以呢我就弄了一个抑或的种子值,这个值呢叫二进制的10110110。那反正你两两亿一这这个值只有我自己知道是吧?我用这个值来对我的文件进行加密,怎么加密呢?我就是把这个文件里面的所有的内容全读出来。

每一个每一个字节全读出来,读出来之后呢,对这个细的进行抑惑。抑或完了之后呢,我再给它写回去。写回去的我给它起了一后缀名叫MSBclass。所以这是你为什么在这里看到了一个。

MSBclass,这是我们加过密的啊。你如果你用把这个用二进制来打开的话啊,open用slamme来打开一下。你就会看到呃,他。哎,what对16进制的。十六进制视图嗯。sle的16点制视图在哪?

淘不切了啊,找了。

呃,如果你用16斤针看的话,它最开始的这些就已经不再是那个呃cafeba了。所以别人去用普通的class load,把我这个class loadclass load进去,它是读不出来的。

那这时候怎么办呢?我要我自己要想用的时候,我怎么办?我自己要想用的时候,就是我find the class的时候,把它拿拿过来之后呢,我把里边的每一个字节读出来,读出来之后,我再抑惑我自己的这个。

加密了这个C。好,我我就相当于解密了。也就是说当我们自己有这个值之后,只有。我自己能用,别人就用不了了,除非他知道我这个C和加密方法。😀Yeah。大伙对你把自己的加密的原码也给他。嗯,像这种简单的加密。

那那人家肯定解了啊。杠精啊,你就属属于杠精中的杠精啊。

所以没方法里面,我先加密啊,解密完了之后呢,我再用通过自己的方法来进行解密,再来读,这就给大家快点着玩的,好吧。大家了解就行啊。

系列 3:P122:【JVM】编译器 - 马士兵_马小雨 - BV1zh411H79h

好来看这里啊,我们再来看一个比较尖锐的问题。这个问题呢叫做编译器。刚才呢我们只讲了加载,其实上没有讲编译。呃,编译这个过程呢。需要大家掌握内容啊,觉着这块内容注意看。是。🤧是。呃,大家知道呢。

那个java呢是解释执行的一个class文件落到内存之后呢,它通过java的解释器interpreer来执行。那java呢其实有一个叫做JIT的JITjust in time。Just in time。

compilerGIT的编辑器指的是有某些代码,我需要把它编译成为。本地代码相当于是EXE的。那么在lins底下呢是lins啊这个可执行的格式。好,这种情况下。叫做。

我可以把java代码也可以编译成为本地代码来执行。所它里面呢有个GIT的东西。那这我说,所以现在大家如果有人在问你说java语言到底是一个解释性语言还是编译性语言呢?你完全可以告诉他,我想解释就解释。

想编译就编译,就看你怎么定。为什么呢?听我说。默认的情况下是一种混合模式。混合模式什么意思?指的是。使用解释器,再加上热点代码编译这两种方式同时进行。什么叫热点代码编译?听我说。是这样来做的。

我们写了一段代码。这代码里面呢有一个循环或者一个方法。在执行的时候,刚开始是用解释器执行。结果发现在执行整段代码,整个虚拟机执行的过程之中呢,有某一段方法或者某一段代码或者某一个段循环。呃。张普逊。

你就发现说这个循环呀执行的频率特别高,频率特别高,一秒钟执行它好几十万次。我解释器解释来解释去,我觉得这段代码呢老被人用,老被人用。算了,我干脆就把这段代码编译成为本本本地代码。

那么将来在执行这样代码的时候,请你执行我本地这样代码。就不要在解释器里面解释来执行了。效率提提升。O。这个叫混合模式。不知道听清了没有,有没有有没有同学有疑问的?这叫混合模式。能理解的同学给老师扣一来。

嗯。😊,那我相信啊。当你看到这个模式的时候,同学们应该有同学会问,那我为什么不干脆直接编译成。本地代码啊对吧?那执行效率不更高吗?为什么呢?因为第一加va的解释器。现在它的效率也已经非常高了。

在一些简单代码的执行上,它并不输于你编译成本地代码。这是第一点。第二一点呢,如果你一个执行的文件特别特别多,各种各样的内库的时候,啊好好几十个classus,这是很正常的一件事情。你上来二话不说。

先在内存里编译一遍,你这个启动过程会长的吓人。所以他现在默认的模式是混合模式,但是你完全可以只用参数的方式来指定到底是什么模式。杠X mixed是混合模式。杠X inter interpreter。

int杠X interpreter是编译模式。对不起,解释模式纯解释啊。sorry,这里写错了。嗯。是解释模式啊,interage解释。他启动很快,执行起来稍微慢,因为它解释执行吗?

那么刚X compare acompilation,那么这种的呢叫纯编译模式,直径很快,启动很慢。当然我所说的启动很慢的意思是你有好多好多类需要编译的时候,你如果只要有一个类需要编译呢。

其实启动还是挺快的。好。那么那实一据说本地代码啥意思啊?本地代码。嗯。EXE理解什么意思吧?这就是windows的本地代码。那么linux本地代码的格式是EERF是吧啊。

就是说C语言编译完的那个东西叫本地代码。这意思乱日依稀啊,不知道我记释清楚没有?嗯,Native代码嗯。好,呃,我看刚才那个有同学说那个呃怎么确定热点代码是吧?你们你看啊这个hot spot。热点。

6点。这hospot原来的意思就是就是我能够进行混合类型的执行的hospot热点。标等代码的检测呢。多次被调用的方法。多次被调用的循环,这这种情况下进行变译。他怎么检测呢?其实就是用个计数器。

某个方法每个方法上都有一个方法计数器监测这个方法。哎,突然间发现某个方法在一秒钟之内,哇塞,执行了某一个值啊,超过某个值10万次。好,我要对他进行编译。这意思。怎么干的?其实拿大拿大腿想一想。

应该知道怎么干,他只能这么干嘛?他没有其他的办法啊。不是标记大伙,我们刚才解释了吗?有一个方法计数剂,就是它监测这个方法。每执行一次都个记录几加一。然后一分钟之后,他检查了一下,发现这方法算了一下。

平均一秒钟都超过10万次了,怎么办?编译吧。嗯。这个阈值记得也能设置,见能见到过?这个阈值能设置是吗?查logo啊。就弄你查查。查查之后分享出来啊。好了,同们,这是混合模这种模式来我们来验证一下啊。

就是说。呃,这东西呢实际上是可以验证的。这一个小程序叫way to run啊,到底用什么样的方式来运行呢?嗯。呃,我我写了这么一方法,这个方法呢叫M。从一从零开始一直到10万啊,然后在里面的值呢。

每个值除以除以3要对三进行求余。嗯,房屋本身没意义,就是耗时间用的。

呃,然后我在卖方法里头上来先执行了10万遍M方法,10万遍M。

然后开始记时间。再执行10万遍M开始记时间。上面这段其实就是告诉JVM虚拟机。你看啊,现在有这个方法被执行了很多次,而且短时间内被执行了很多次。请你对它进行优化,就这意思。那我看到里啊。来躺一下试试。

我们先得确定一下它的执行模式啊,先执行一下看再说。停掉啊。

我们先指定一下它的模式run。

al shift F10啊,同学们。

突这个正好出去了,让你让大家看不到啊,不要讨厌啊,在这儿啊run。Added configurations。好,去指定一下它的参数,这个V呃V motionja虚拟器的参数在这里没有做任何指定。

没有做任何指定,就代表着它是混合模式。我们记录一下混合模式,它的执行时间试一下。

混合模式呢就是它监测到这个方法被重复执行了,所以呢他就会把这个方法进行一段编译。混合模式啊,其他的像这种的什么star啊这一类的全全是全是解释执行啊。现在是4秒2,我再指一遍,怎么这么长时间?哦。

4秒大概4秒左右吧,再执行一下。这其实你应该用我原来教大家的那个GMH来做一些统计和输出才会更好一些。3秒7再执行一下。讨厌了。

4秒3啊,反正大概吧4秒左右吧,差不多嗯。

呃,4秒左右的话呃我们换一下模式啊。

Run。Be configuration。指定一个杠X,我们只要intererin纯解释性,它就没有那个编译内部编译这个过程,跑一下纯解释看它多长时间。好,大家可以回去睡了。好,大家先去吃饭,下午再看。

😀哈哈哈哈。😊,算了,咱别等了,行吗?

咱不等了是吗?O。哎,总而言之,你这个时候你要用纯解释执行起来就费老鼻子劲了啊。😊。

哎,算了算了不等了啊。😊。

你你们自己下去,自己慢慢好玩的话,自己做实验吧。好吧,总而言之这么慢嘛。😊,好,我们使用编译纯编译。好。嗯。3。9。好。嗯。4秒8。就差不多比那个呃混合型的呢稍微的快那么一点点。别的也。

稍微快一点点也也也也没什么啊。呃,不过如果你累特别多的时候,你启动的速度就会特别慢。因为它编译的过程是需要时间的。

你感受到慢的是因为它在编译,好吧。嗯。

系列 3:P123:【JVM】懒加载 - 马士兵_马小雨 - BV1zh411H79h

Lazy loading。这个累 load顶严格来讲呢,应该叫la initialization呃呃。懒懒初始化啊,但是。就很多人就说懒家奶。这VM的规范里头。并没有规定什么时候加载这个类,听清楚。

首先第一点呢。多数的呃JVM虚拟机的实现啊,它都是用的懒加载。懒加载意思就是什么时候需要这个类的时候,我才去加载。我并不是说你一个炸文件里面2000多个类,但我只用到了其中一个类。

我需要把2000多个类全漏进来,不不适的。我用到了ms这个类,用它来做数学计算。那我只用把这个类的代码录进来就OK了。我真的没有必要把相关的那些个包里面所有代码全漏进来。所以这个我相信大家都能理解。

很很简单。但是JVM并没有规定,你什么时候把这个类给加载进来。有时候你要是真愿意啊,你自己写JVM实现,把二二话不说,把所有全加载进来,可以的,没问题,随便你。

但是呢他严格的规定了什么时候初始化5种情况。我再说一遍,别去深究他,没有意义,好吧,就扩展着玩了。什么时候必须初始化是规定这么一种情况。当new有这个类对象的时候。

get static访问这类对象的实例的时候,put static访问实例的时候,invoke static调用静态方法的时候。这些指令的时候,必须初始化这个类。访问final除外,final变量。

一个类里面的final变量。在你解析的过程之中,立刻就给它定好了。这个值就是一个固定的单独拿出来放在内存里面,某一个特定位置值,反正也变不了。所以我甚至都不需要对这个类径初始化。

我就能定知道这个翻动变量的值。当你使用反射调用的时候,当你初始化子类的时候,负类必选初始化。虚拟机定要用被执行的主类,含有卖方法那个类必须说始化。下面什么动态语言支持啊。

就是java method handle method handle解析这个结果的时候,如果解析成它是一个get static, push staticinvo static。啊,这个时候可你说实话。

我再说一遍,这一页讲的内容,我不需要你去严格掌握,没有没有必要。好吧。不过我们可以做一个实验。大致了解这到底是什么意思。听我说。所谓的加载这个类加载完了之后呢,刚才你看到加载完了之后。

它自动的就会进行一个呃loading linking和inial lighting的过程。

注意看我有这么一个类,这个类呢叫P。P这个类呢有一个静态变量叫I。还有一个静态变量呢叫J。

第一个动态变量是final值。另外它有一个静态的语句块,叫sstem out print。我们说需要这个类的时候才加载,我们怎么证明它被加载过?

只要他被加载过,这个P一定是被打印出来的。

因为刚才我们说过一个class漏到内存之后,它有loading linkinginitializing的过程。initializing这个过程会执行静态语句块。所以这个类load进来。

这个静态语句块一定被只执行过。所以这个P一旦被打印,就证明这个class一定low进来了。我说到这里,有没有同学有疑问的?没有没有问题的同学给老师扣1。所以说这个P一旦打印出来,就证明这个。

类被加载过了是吧?啊。我们一起去看啊。P小屁。同学告诉我这个类会不会被加载?我同学说老师,你这不是用到了吗?😡,你分析我刚才的那5种情况,我扭他了吗?没扭,我访问他的静态变量了吗?没有。好。

同学们告诉我。P小P这时候。会不会被加难呢?不会对。讨一下试试啊。

你看没有任何输出,没有加载过,按需加载。咱下面这个呢。

X小X等于6X,你说那P会不会打印出来?

注意伦6了X了。

X的它的负类是P,那它一定是展印出来的,这个P必须得加载进来啊。

OPX。然我看下面这个。我打印P点I告诉我会不会再打印一个P后面。

注意I是final类型,final的类型会吗?

跑一下。

不不。我们刚才说他不会打印那个P,注意啊,他会把这个值打印出来,但不会打印那个P,说明那个类没被加载,知道吗?我打印final的值是不需要加载整个类的。

看这个P点J,这个呢非fin非 final呃,我这个类啊,你你注意看我这个P这个类。是lazy loading的内部类。所以我要访问P这个类的时候,必须得是外部类dollar内部类的名字啊。

不然我直接访问不到。

系列 3:P124:【JVM】第二天课后总结 - 马士兵_马小雨 - BV1zh411H79h

我们稍微复习一下。嗯。呃,双期委派主要出安全来考虑。那个我复习一下这个双击委约的过程,就向上找向下委托这么一个过程。呃,然后呢我给大家讲了。累计楼顶的问题。内底楼顶有5种情况。

那么这个这种情况呢是在深入加了虚拟金那本书里头。有详细的列出来啊。

来,这地呢给大家复制下来。累计loading的5种情况。是这5种啊。那么今天呢。Okay。呃,我们还讲了。class loader的原码。刚刚文板需要大家掌握什么呢?

就loadclass过程到底是什么样子的?我们需要重写的时候就需。需要。look class嗯,然后。呃,是首先是fin and catch啊。不是计你这不是加载过了,如果没加载过的话呢。

应该是调用父亲的冷。Parent的。Load plus。如果父近交载不下来,我就就要用find class去查找啊。find class呢这个呢是需要你进行重写的。所以呢我们自定义了加载器。

最简单办法就是从。lastloader集承。然后呢。重写。摔的看爽了。在里面呢我们一般会用到deffin class。来把二进制的。自接出租。转换成为一个。class类的最小。

使用自动系的加水器呢也可以进行加密是吧?

定义自己属于自己格式的这种class。好,我们讲了混合执行的问题啊。解释执行。

嗯。大概呢这是我们呃今天讲的内容。那么下节课呢再来给大家讲了linking的过程,以及和inlishizing呃inlishizing的过程。呃,刚才我看jones已经把那个参数给查出来了。呃。

这个就是说怎么检测热点代码。叫它这件代码,刚才我看joths已经帮大家把那参数查出来了啊,XX叫什么来着?看看。😔,周老师,你来再来敲一下来,我给大家记在笔记里。周老师,你还健在吗?呃。

compelle threshold是吧。re后的他默认是等于1万的是吧?那我正好正好踩到了这个点上啊嗯。Okay。后来。

这是我今天咱们讲的整个的技术的问题,已经讲完了。

系列 3:P125:【JVM】第三天课前复习 - 马士兵_马小雨 - BV1zh411H79h

一。好了,各位同学,咱们上第三次课啊。呃有一些同学是新到的,那么应该你前两次课呢没有听或者没有补,这个没有关系。呃,第一次课呢咱们讲的是class loading。就是说呃sorry。

第一次课我们讲的是class的 format formatclass文件的格式。呃,那块呢是比较独立的内容。你呃放在咱们课后去补就行了。呃,上一节课呢讲的内容呢稍微有一点点复杂,所以我们稍微的回顾一下。

好吧,即便你上次课没有听的话呢,你先大体的跟上这次课,再下了课之后,你再去补上一次课的内容。上一次课呢,我们主要讲了类的那个呃整个load到内存的它的一个大体的过程啊,重点解释了双清委派机制。

就是class loader。那好呃,我们来稍微回顾一下啊,一个class呢放到内存里去会经过好几步。第一步呢叫loading。主上节课主要讲了这部分啊。

呃第二步呢叫linking linking分成三部分verification preparation和resolution。这个后面我们再解释。那么。这几步呃loading临挺完了之后呢。

最后一步呢叫initializing初始化啊。好。上节课呢我主要讲了类加载器啊,关于类加载器,我不知道大家伙还有没有印象。类加载器呢它叫做双默认的啊,默认的是叫做双亲委派机制。

双亲委派机制的主要的含义就是当你要求一个class loader去load的一个class的时候,他首先找他的父亲,注意这个父亲不是继承关系上的父亲,而是你自己指定的他这个代理的这么一个关系。好。

Yeah。他先去他的parent里面去找,你有没有漏的过来,漏过这个类啊,如果漏了,直接返回。如果没有漏呢。就再找他父亲的父亲,一直在那顶上顶上那个呢叫bustr用CI加写的。如果到这儿都没有找到的话。

那么他就翻回头去看我能不能加载呀。由于他加载的是特定的class pass,所以他加载不了的话,他就找他的孩子,你继续给我加载,你继续给我加载,你继续给我加载。

一直到我们自定义的这个class load这里,如果能加载上,那要加载,加载不上呢。class not found exception。这是双亲纬派的一个机制啊。呃,因为有可有可能有上节课没听的同学。

我再呃说一遍,我再说一遍啊,没有由于有上节课没听的同学,所以呢。你大体听明白我刚才复习的这个意思,然后你课下去抓紧时间把上一节课内容补一补,好吧。嗯。偶然问说不是继承,怎么是parent。

他的一个成员变量叫parent啊。好,这是双清委派的一个机制啊。然后上节课呢,我教了大家呢,怎么样去呃定义自己的class load。这个呢要看代码了是吧?啊。

自定义的class load大家还有没有印象啊?自定义class load呢使用的是一个设计模式里面的模板方法,template method这样的。

呃,一个一个一个一个设计啊。嗯。

Stture。ok。我们稍微回顾一下啊,也一个自定义的class loader来说呢,你首先要从class load或者它的子类来继承。继承完了之后呢。去只要重写一个find class就行了。

这个fin class呢是在low class里被调用的,是吧?

让我们重重写好啊,呃找到你对应的class版漏到内存,这个就叫自定义的class load。

在目前这种自定义class load的情况下呢,你是不会打破打破这种双清尾派机制的。上节课咱们读源码的时候说过,这个双亲尾派机制实际上是写在哪了呢?我不知道大家还有没有印象啊。

class loader里面的那个方法,load class嗯。给大家读个原码啊。所以由于look class里面双亲委派机制的模型已经被写好了。所以你只需要找到它的调用find class的部分。

重写这部分就可以了。嗯,寻找类啊。Okay。好。呃,这节课呢我们给大家讲一些上节课遗留的内容,就是有一些同学问的问题啊。

诶大概。那。Or of no。上节课呢有同学问过一些相关的问题啊,我来稍微回答一下。

哎,我也是醉了。

那怎么重新定大小,这么费劲呢。拖右边拖不动,只能拖左拖左边。

是怎么做到的?

稍等一下啊,把内容拖进来。

啊,这上节课呢,咱们做的笔记。

嗯。呃,双清委派第一节课呢,我们遗留了几个问题。

有个有同学问说是这个parent到底是怎么指定的?其实怎么指定呢?这件事特别简单。呃,你想一下啊。

你来分析一下啊,拿大腿来分析一下。同学们,你们想想看,我们自定义一个class load的时候,我们有没有指定他自己的那parent呀?为了避免咱们。

这个上节课没有听的同学啊。

这个你你先听一大概就行啊,这个你你要需要补一补里面内容。呃,我们回顾一下,任何一个class loader,任何一个class loader。大家看这里啊都有一个parent。

成员变量parent他的parent也是一个class loader。呃,咱们自己定义自己class load的时候,实际上呢并没有指定我的class load是我的我的parent是谁,对吧?同学们。

好,我没有指定我的parent是谁的情况下,他的parent是谁呢?那当然你就去找啊呃,他的parent到底怎么指定的?

这个你要去原版里找的话,你就会你就会知道。

嗯。看这里。

看一下这个原码啊。同学们,你们想象一下,我new自己的一个自定义class load,它会调用父亲默认的参数为空的class load。所以呢当他调用父亲默认为空class load的时候。

调用的就是这个构造方法。

在这个构造方法里面调用了自己的另外一个构造方法。好,这个构造方法呢,但家你看这里啊。他第一个是没有用的。第二个呢是他的parent。所以在这个构造方法里已经指定了他的parent是谁了。

那parent是谁呢?

这 their parent and parent。

呃。他的parent是谁呢?看这里啊。看下面这种。protected class load class load parents用这个方法可以指定他的父亲是谁?

他附近默认的是谁呀?嗯 guesses the manager security return now。

Check freight。

Parent。嗯,你得看他的父亲默认。呃,稍等片刻啊,我一会儿再给带大家找到那个他默认父亲在哪里指定的那段代码。

呃,我们先来看看你怎么指定你自己的父亲。呃,大家看这里啊。呃,我们怎么指定自己的父亲?你会发现在他的。副类里面有一个各造方法,这个各造方法是protected的是吧?受保护的,所以只有子类能调用。

那嗯看到这里,同学们我问大家一句有。多少同学能够想得出来,我到底怎么样自定义自己的class,就是自自自己指指指定自己的父亲啊。很简单是吧哎。看这里啊。呃。

我呢给大家写了一个自定义的指定父亲的这样的一个。

class load啊在这里。T010pararent。你怎么指定自己的父亲?其实非常简单。用自己的class load呃,自定义的这个class load。去从class order集成。

构造方法里面,plic mylo的构造方法里面调用super指定parent。我parent是谁呀?我parent自己随便指定的,我可以指定是我自己自定义的那个parent。

是吧我现在这拍的是我自定义那个MSBclassloader。然后我下面的这个my loader,他的父亲就可以是这个MSBclass loader。

所以super这块直接调用super就可以指定他的parent。这第一个问题呢我就解决了。好,关于这第一个问题,有没有同学有疑问的?偶然偶然说是重写。你说是是重写哪个啊?未指定的话,有默认的吗?呃。

你要是想没有指定的情况下,看他的默认的是谁,这个用用什么方法呢?里面有一个方法嘛,这点get parent你就能拿到是吧?所以你查一下他默认的是谁就行了。嗯。😊,我们自定义的这个呢。

看这里啊。大兵说子类定义父亲的 parent没有定义啊,我们不是只定吗?调用了分类构造方法给它设进去不就行了吗?设定啊不叫定义。设定为它的值,好吧。

呃。

等一会儿,我给你找一下他默认的那个是谁。

。默认的这个呢是在哪里指定的啊?

搜一搜。

Parent。

该s systemstem class load嗯,看这里啊。在这里。呃,当我们调用父器默认的这个时候呢,默认的是谁啊?它是get system class load。

就是拿到的是一个stem class load,这 systemsem class load又是谁呢?他是怎么调用的呢?

嗯。

具体的这个实现呢,你不用去看这stem class loader呢,就是默认的就是我们的APPclass load啊。

呃,你直接调用这个方法就能拿到他最后的结果到底是谁。这里面呢由于牵扯到了很多安全性的内容,我们就不详细的直接追到我们所有的这个代码里面去了。

呃。

initial system class load在这里面是真真正正的把我们的class load默认的那个值给你初始化了。那默认的值是什么呢?其实很简单,你直接在你的代码里面去试一下就行,好吧。

很有很多内容呢,你只要动手一试就可以。我相信大家应该能想到吧,这块。

你比如说他的父亲到底是谁,你可以list thereget parent不就知道了吗?呃,get system class load。呃,你如果想那个。知道他的系统的。

咱们系统默认的这个class load是谁,你是不是在这里直接调用get system class load就可以了。所以。这个东西还用我在这里给大家写吗?如果需要的话,我就再给大家写一下,需要吗?

偶然偶然你问的这个问题是在上一节课里面内容,你现在已经下课再补一补好吗?偶然嗯。这块还需要我给大家写吗?就是一个类默认的。

写想吧。

我写在这儿啊。一个class loader默认的。比如说。

s out new T006,这是我们自定义那class loader their get parent他默认是谁是吧?

Ss out。你呃。let loaderge system class load默认的那个啊,就是可刚才你看到了,默认就传的他父亲,就是通过ge system class load得到的,对不对?

运行一下,你一看就知道啊。好看这里都是APPclass load是吧?所以他的parent默认是谁?APPclass loadclass load就系统系统class load是谁?

stem class load是谁,也是APP class load。就是当前的我们这个project啊都是由他默认来加载的。所以自定义这块到现在指定parent这块。

我看大家还有没有谁有没有一些什么样的内容嗯。leden个 system class load你被用来干嘛的?就是拿到系统的默认的这个class loader嘛,也关于安全的嘛。呃。

它内部呢自己定义了一些安全的检查,但这个我们一般用不到。我们需要他的时候,就直接调用这方法拿到用就行了啊。再我再说一遍啊,有很多小同学的问题呢,其实不是这节课的问题,而是上一节课的问题。

所以呢你这节课的前前一小半节,我复习的这个过程呢,你要是暂时听不太明白,关系不大,先补一补上节课的内容再回来听。好吧,同学们嗯。O。嗯。那好,那关于。指定parent这块咱们就过了。

上一节课呢其实还遗留了一个呃很大的一个问题啊,就是呃咱们双清委派机制是可以被打破的。这块问题呢,我们作为一个扩展就行,你了解就好。不了解的话呢,听老师说说好吧,有个印象。呃。

因为是因为我为什么又讲又讲到这么深入的内容?其实原因是有一个小伙伴啊跟我说,他面试的时候遇到过了,好吧。我只能感慨现在这个面试啊是越来越变态了啊,当然多数的情况下啊是不会考这方面内容的。

那。就是你你的这个打破双亲尾派这个问题啊,打破双亲维派这个问题是什么情况下会发生?呃,同学们,你们想一想,你们咱咱们回顾一下啊,这个双亲尾派是在哪个源码里指定的呀,是不是load class的原码啊。

还有印象吧?是在class loader里面的load class这个源码里面已经设好的,指定好的啊?

这个class loader这个类,然后这个类里面的load class这个方法。

咱们上节课呢读过这方法。う。

所谓的双亲委派机制,其实呢就是在这个方法里面呢给咱们写死了。所以你你你这这方法我在上节课带大家读过了,我就不带大家重新读了呃。

在这里是先找他的父亲的,什么,先找自己的,找不着了之后呢,让他父亲去调,父亲再找他自己的等等,才形成了。刚才咱们所说的那个双亲委派机制,先上上先向上找再向下委托这么一个机制。双亲委派。那好。

要打破这个双清委派机制。第一件事儿我先问你,你说你该怎么做?load class已经帮你写好了双清尾派机制了,你只需要去重写咱们的find class就可以了。

可是现在我要求你去打破双清委派机制,你怎么干?你只有一个干法,就是把low class给重写了。我这么讲,大家能理解吧?就load class已经重写人人家已经写好这个机制了,你想把这机制给干掉。

你怎么办?你是不是得重写这个load class呀?所以。

你要想咱们说怎么实现啊,就是说你要想打破这个双切尾派机制,我不想用双切尾派了。

你要想打破他。重写load class方法,而不要去重写find class方法,这时候就能打破。那什么情况下需要会打破双清尾派机制呢?呃,在深入理解招要虚拟杰那本书上啊,就是周志明老师那本书上。

他说过三个。

三种情况。第一种情况,JDK1。2之前,自定义的class load都必须重写low class。因为那会儿还没有find class那方法,所以那会儿你不想打破也得打破,这是它自定义的一个缺陷。

这个不管它。好,这不管。第21个呢是。你可以自己在一个县城里面设定自己现城上下文的class load,你随便设定。你随便设定完之后,这class loader load class你一重写。

那你就可以随随便便的load的各种各样的class了。当然有同学说可能老师我不太理解这块不太理解就不太理解,就不理解这。不用去深入去研究它,没有什么大太大的意义。多数情况下,你面试是遇不上,好吧。

遇上就算你倒霉就行了,找下一家。好。好,我们继续啊。还有呢就是模块化的时候,这个热启动热部署,像OSGI呀、tnca啊,都有自己的模块指定的class loader啊。

这里是可以加载同一类库的不同的版本好,这里其实用到的自定义class loader,打破双亲部署,双亲尾派,这个用的是比较多的。一。有。听我说。一。哎,稍等啊,这个观键咱们的机器人女友在那里边那说话。

孙老师帮我把那机器人女有给关掉,谢谢。嗯。我先给它关掉啊。好,听我说咱们呃有有多少同学,咱们多多数同学听这个课的话,你应该是了解toca的,对不对?好,有有没有现在在听课同学不了解tcast。

你给老师扣个2来。有没有?好,大家听我说啊。嗯你们不了解toca是是什么情况。听架构的课需要你SSM的基础。SSM基础什么意思?你tomca不了解啊。如果这个要不了解,你真的得听一听。

就是连老师的初级课曲线啊。不是这个这个了解呢,我说的你用过就可以啊,你知道tomca是怎么回事就行了。不是说你源码急OK。好,听我说tomca呢,大家知道你写一个web application。

你就把它呃你自己写的类呢扔到一个tomca的指定的目录下面去是吧?同学们一启动呢,它就可以这些类的就加载下来了。但是大家知如果说呃我们要是两个不同的web application。

两个web不同的web application,在toomca下是可以同时被加载的。但我问你一句,如果第一个web application里面,它加载了一个类是A,第二个呢也加载了这个类是A。

加载的是不同版本。比方说这unit这里用到的是。5。5。1版本这unit这里用到的是4。0版本。那这两个内容注意这两个里边的类的名字是一样的啊。只un你里边有个类,这叫A吧。他的名字和5。

1里面这个名字A是一样的。报g点这unit点什么什么什么。如果我们用。刚才的这种双亲委派机制,你觉得这俩哥们儿能够加载到同一空间吗?肯定不可能的呀。如果第一个被加载进来之后,后面再加载的时候。

他肯定会去找啊,里边有没有啊?有发现有一个同名的,有一个同名的,他还会加载吗?他不会被加载。好,说到这儿,有没有同学不能理解的?能理解的同学给老师扣一,我们继续好不好?嗯。

所以呢tomca里边每一个web application都有自己的class loader哦,我说到这里,大家是不是能理解,就是每一个自己的web application都有自己的class load。

自己的load的这个class loader。互相之间是可以同名的这是没问题的。好,class loader一第一个class loader里边有一个名字叫comme点马氏兵点什么什么。A好。

这个没问题。class load2里边它load进来一个comme点什么什什么A,这个也没问题,听懂了吧?两个class loadload进来可以同名的垒。这是完全没有问题的。

OK所以这里面呢其实他就已经呃。打打破了双击委派机制啊,当然打破的细节呢比较复杂。呃,你你你刚才那个你他他都要往父亲里去找啊,那个父亲里去找人,如果他找到了,他他他是不是就加载不了了呀。

那这时候怎么才能让他不不去父亲里找啊,我二话不说,我就直接加载行不行?我不去父亲里找,那怎么办?你是不得去重写load class呀?

ok。好,为了跟大家说清楚这个问题呢,我写了几个小程序来给大家演示一下啊。

大家看这里。

这里呢我我给大家演示一下,就是类的这种热部署是怎么实现的。OK类的热部署是怎么实现的。呃。你看这儿啊。呃,当然。这是第一个呢,小程序呢是不能够实现的一种方式,不能够实现一种方式,什么意思?

正是因为你只是重写了find class,你是打破不了双清委派机制的。所以你这个这种方式是不能不能实现的。什么意思?你我们来读一下这代码啊。呃,我们定义了自己的1个MSBclass loader。

然后呢,去load的一个class,这个class呢叫hellow。名字comme嘛是兵GVM helllow上节课以。漏得过这代码啊,代码比较简单。呃,然后呢我打印class的hash code。

接下来注意看注意看,我把第一个class load设为空。Dclass loader设为空。设为空之后呢。我重新再漏的,我我再new一个class loader。你有了一个新的class loader。

然后我再去load的同样的一个class。

我们来看看这两个classus是不是相等。考一下。

但然你能看到它是处。

嗯,看这里啊。

他处同学们,这是其实这是为什么呢?就是因为你双亲委派,不管你怎么怎么做,他都会去父亲这里找。如果你漏得完一次之后,你下次无论再找谁去漏的。他都会去这个。已经加载过的那些个类里面去找。如果找着了。

它就不会再重新加载。所以你后面你无论再你多少次,再漏了多少遍,都没有没有任何用处。如果你想干掉这件事儿,想真真正正做到热加载怎么办呢?只有这么一种办法,大家注意看。

看这里。好呃,在这儿呢我。定义了自己的新的一个class load。我刚才说了,你你要是定义自己class load的时候,只是重写find class,你是打破不了双清尾派机制的。那么。

你要想打破双牛委派机制,你只能这么干。自定义自己的my my loader从class loader继成。这次我们重写的是load class,而不是find class。

好在load class里面呢。好的,看这里啊。

我首先去找谁呢?找你要求我去load的那个class文件。

如果我没找着。我让我的父亲去漏的,如果我找着了,我直接自己就漏的。

这里头有个小小问题,大家回回顾一下,人家class load点默认的那个load class逻辑是什么呀?首先找是不是已经加载过了。对吧我把那部分逻辑给他干掉了。我说你我管你加载过没给我加载过。

反正你告诉我名字,我就直接去加载。

正因为这样。

我们才能实现什么呢?比如说这儿有一个class文件。好。我呢呃要想让他动态改了之后,我要是想让它重新加载,我怎么办呀?

我重新调用一下。

我这个class load这个这个这个这个这个呃load load load class就OK了,我重新调一下就OK了。因为他二话不说会去给我重新加载。那有同学会说,老师这事儿不对呀。

你如果是同一个loadclass loader的话,他已经加载过一遍了。你再去load的。你原来那个是覆盖不了的呀,没错,覆盖不了。但是我怎么办呀?我直接把这个class load整体干掉不就行了吗?

所以tom cat里边啊是这么干的。当你要你你为什么能写1个GSP文件,或者为为什么能写一个那个那个呃web web application,你改了里边内容之后,它能够进行热加载。很简单。

他直接把这个web application的整个。class loader他的class loader全部干掉。干掉之后呢,重新再加载一遍。

里边的所有的class。我模拟了一下怎么写呢?这么来写。看这里。my loader等于new my loader。我念完了之后,我load class。透马士钉JVMhello。

然后接下来我又new了一遍my loader,这次我又重新load classcom点马士冰点这BM hello。好。打印class两个classus是不是相等?

这时候还相等吗?跑一下看看。bos不行的。上节课咱们做过代码,如果你在同一个class loader里面去load的,它两个是相等的对吧?现在呢它已经变成不相等。

说明什么我们load的class不是同一个。那那你可以想象一下,在这两次load的中间,如果你改了。海lo里边代码的话,他肯定就会输出新的。嗯。Yes。

ok。这是呃tom cat的底层呢,它现对应的怎么实现。当然我写的其实上非常简单啊,只是为了教大家一下呢,它呃原理性的一些东西。你要想呃真真正正的把那个整个tmca全都实现了,那个就相对复杂很多了。

那么原来连老师呢讲过tm cat的源码。呃,如果大家感兴趣的话呢。找找啊,咱们公开课的那个链接里头也有。好。这里呢是我大概教了大家一下怎么样去进行热加载的一个概念。就热加载呢呃基本都是这么干的。

他会把整个class loader全部干掉。

干掉之后呢,再把其他的那些class漏了一遍。

系列 3:P126:【JVM】初始化 - 马士兵_马小雨 - BV1zh411H79h

好。🎼到现在为止呢,我们就也就相当于呢我们把loading这部分的内容呢给解决了。下面我们来看linking这部分内容。那么linking这部分内容呢,它分成三步。

第一部分呢叫verification preparation啊,第二步叫prepar。第三步叫resolution。我首先简单给大家解释每一步大概是什么意思。呃呃,loading这块内容呢相对复杂。

问的面试题呢比较多。其实后面这部分内容啊,面试题呢并不多,就那么一点点嗯。我呢这节课呢把咱们后面部分内容给呢快速给大家解决掉,好吧。首先第一步呢叫verification。

verification这件事儿其实特别简单,就是你检验你刚才加载进来的这个class文件,它到底是不是符合这VM规定。你格式不对,你前面那四个字节不就是0S咖啡ba,那肯定不对啊。

那不是我要不是我要的东西,你被篡改过了,我就不会再进行下一步。所以verification是对文件进行校验的。这比较简单,问的也很少,咱就不多说它。第二步叫prepar好,这步必须掌握这步是什么呢?

给静态成员变量附默认值。好,这部呢叫prepar,对静态成员面料抚摸认质。先大概记一下,一会儿我来给大家演示程序。第三叫resolution。resolution叫解析。

如果大家读class load的原码的话。

还是去看一眼。在我们的这个class load的源码里边。

呃,load class的时候。

不知道大家还有没有印象啊,loc class第二呃第二个参数。第二参数是一个布尔类型叫resolve,到底是不是进行解析。就是你传储,它就会对你进行解析。如果不传输不传储的话,就不对你进行解析。

所以这个解析指的就是这一步。

就是resolution这部。那么resolution到底是解决什么问题呢?resolution是解决这样一个问题。他会把类方法属性符号引用解析为直接引用。那有同学会说老师什么叫符号引用?呃。

我们稍微回顾一下我们第一节课讲的那个class文件里面,class文件里面在它的常量池里,是不是放着一个一个的类的。名字呀,比方说java land object,这个大家还有没有印象?

L里边写的是java land object。好,当我们下面要用到这个object的时候呢,它下面的这个引用啊,实际上是一个符号,指向的是这个字符串javaline object。

但是这个真正的这个javaline object在内存之中的什么位置呢?它很可能在这个位置。好,所谓的解析过程就是把这个字符引用。我们称之为符号引用。直接转换成为指向内存的具体的地址和指针的这个过程好。

这个过程叫resolution。关于resolution,有没有同学有问题的?有问题你提出来。没问题,扣一啊。Yes。嗯。所以resolution呢呃比较简单。对啊,jona说有有些引用是动态绑定,哎。

有些是必须是动态绑定。因为你只有扭出来了之后运行起来,你才能知道那个具体的位置在哪。所以很多是动态绑定啊,不是说有些啊是很多很多都是。所以这个resolution一般来讲,面试呢也问不太到,呃。

问到的内容呢也没有没有没有什么更加详细内容,多数就是多态。其实啊所以这个呢我们呃先不去理他,好吧。现在呢最重要的呢还有两项,一项叫preparation。我刚才说了是类静态成员附默认值。

那么静态成员变量附默认值,什么叫默认值啊?大家学java最基础的时候,int类型不指定的时候,什么值?零嘛对吧?long类型0double类型0。0嗯,然后引用类型要是不复值的时候空值。

然后这就叫默认值给静态成员变量服默认值。那好。那什么时候会对这些默认直径初始化呢?在第三步里头,initial lighting调用类初始化代码好,在类初始化代码里头。给。静态成员点亮。F。初始值。啊。

这句话什么意思?

呃,我原来在公开课讲过一道面试题,我们通过这道面试题来理解,好吧。来,我来我们来读一下这个命试题啊。嗯。好,这面题呢在这里。

来,我先给大简呃,大家呢一点简单的时间啊,你先读一下这道面试题。几十秒钟,你先读一下啊。我们有一个自定义的class T,它呢成员变量countt等2。还有一个成圆变量T小T等于6T。静态的嗯。

过造方法,private tea。看着加价。然后。面二题是问你打印T点com这个值是几?来告诉我。哪里有2有3是吧,来。来跑一下。三啊说二的都不对,怎么还要说一的?浩涛,你这个一是什么概念?

这一是哪儿来的?呃,来注意看啊。然后我把这两句话换一下,哎,两句话换个位置,你再看一下啊,刚开始是这这是这样的,康等2先复制,然后再调用了newT换个位置。跑一下。A,这值变成二了。好。

这到底是什么情况怎么做到的?我们来分一下这小程序啊,这里面呢实实际上牵扯的内容也挺多的啊,尝试给大家。

分析一下,我的画图板翻过来之后没有装上啊,我只能拿鼠标画。嗯。😊,我只能拿鼠标画,拿鼠标号就拿鼠标画,好吧。呃,你认真看啊。呃,整个过程呢是这样的,我们先看先看。这样的一种做法。

抗等2最后是怎么打印出来,抗能变成三的,是什么一种情况?呃,我们来分析一下整个的执行过程。执行过程是这样。当我们调用T点com的时候,他需要把T点class漏到内存,通过我们的class loader。

我们class loader默认的就是APPclass loader,它会把T点class load到内存,load完了之后进行verification进行校验。校验完了之后进行preparation。

prepar就是把T里面的静态的这些成员变量给他附默认值。那这个时候看的值是几啊?抗的值是0。注意这时候小T是什么?小T是空值。所以他这个时候有没有调用。构造方法没有countt加加了吗?没加。ok。

继续进行resolution解析,不说了,进行initialization initialitialization初始化初始化就是来给这些值把它把它复初始值。那复初始值的话,这count原来默认值是0。

初始值日几初始值是2,所以这时候countt变成2。好,这个初始值是几?这个初始值是new T,所以它会调用new T把countt加加。因此。抗的值最后变成3。调至第一个过程。不知道大家听清楚没有?

好,我们来看第二个过程,反过来我们反过来再看,认真看反过来过程是什么样子的。反过来过程是是这样子的,我们再来分析这过程啊。这个过程是T点class漏到内存不解释了,verification不解释了。

接下来进行prepar,prepar的时候,T是什么?T是空值。啊,刚开始啊就是准备的过程,T呢是空值n值。好count的值是几啊?count值是0。听懂了吧?好,接下来。进行初始化初始化过程。

首先注意,由于他语句换了顺序了,它从上往下执行。所以首先会调用6T。这个newT的时候,把countt加加count的值现在是几啊?是零countt加加呢count的值变成了一。接下来继续往下执行。

那6T6完了之后,count的值负值为2,所以最后的值赋值为2。因此第一个是3,第二是2,这过程不知道说清楚没有?嗯。哎。这道题呢其实问的非常的无聊。呃,我我们一般写程序会这么写吗?

我们一般写程序会这么写吗?听到啊。一般不会这么写嘛,谁会谁没事这么写程序。😡,我要是这么写的话,我一定是说给他付付。初始值的话,我直我会直接给他这个构造方法里,或者用一个静态语句块。给他付出日职。

就是这是一个编程习惯的问题。嗯,还有一点。我真的没事儿,那个会在这里头进行countt加加。总而言之呢,这代码呢就是为了面试编出来面面面面面你用,好吧,面试秀智商用的啊,所以一般的呢。

也不会呃这么来写程序啊。你要是这么写程序,基本上你的会被你的你你你的老大怼你,这是肯定的啊。呃,所以。一般啊写你如果真正的写程序的时候,一般怎么写呢?其实呢是应该写。诶。把这里都复成初值。

用一个静态语一块挨挨着盘的复值就行了,好吧。所以呢。嗯。😊,这个程序呢就是为了向你说明整个我们class漏到内存之后,实际上它是有两个过程的。第一个过程呢叫preparation。

第二过程呢叫initalization。好,关于这一点,我我现在呃问大家一句,是不是大家都明白了。

就是这两个过程。第一个过程呢,preparation是静态变量复默认值啊。第二个过程呢是静态变量复制为初始值啊。嗯。

好嘞。Yeah。好,当大家理解了这个问题之后呢,我们再来讲一个更加更难的问题。好吧,这问题呢我在公安会也讲过,但是有同学可能没听过,所以我还要重复一下,我快速重复一下。更难的问题。这更难的问题是什么呢?

同学们,这里啊其实只是一个嗯。静态变量的问题。呃,我们我们分析一下啊,假如他有一个成员变量,M是8。大家知道这个成员变量。要想呃给他这个运用把它用起来的话,那么你实际上实际上需要拗对象的。

你得把这个替这个对象给扭出来,这一点呢比较简单。注意这个new对象的过程也分成两步。我再说一遍,new对象过程也分成两步。比如说假如它成员变量啊,咱们现在扭出来了一个对象,叫叫小叫叫T啊。

大T的对象扭出来之后,它里边有成员变量,M8,它分成两步。第一步是把这个。给这个对象申请内存的过程。申请完内存之后,它里面的成员变量先付默认值再说一遍,先付默认值。所以。

如果我们把它说new一个object, new T把这句话再来分解的话,它实际上中间也是两步。第一步呢是new出来这个T这个。扭出来替这个内存,new完了之后,里边这个成员变量还没有进行赋值呢。好。

这个时候它的默认值是0。然后newT下一步申请完内存,复完默认值之后,下一步才会调用构造方法,调构造方法才会给它负值成为初始值。这个初始值变成8,所以它中间有两步,第一步是0,第二步是8。

我讲这儿跟那个classus。初始化和那个呃prepar也有有有非常的类似。关于这一点,有没有同学没听明白的,没听明白的同学,你给老师扣个2。Yes。听明白给老师扣一,我们继续好吧。

我在就是任何不管你是静态变量,静态变量是在类初始化的类类类被加载之后分成两步。那么对象里面的成员变量呢,是我们扭出来之后啊,分成两步。小五,你是哪没明白啊?嗯。呃。

M等班和浩涛问M等班和countt佳佳先后顺序,你写把谁写前面。谁就先执行,正常是这样。但其实他们两个如果没有互相之间没有依赖关系的话,还有还是有可能被乱续执行的。我这节课如果讲的快,就能马上会讲到。

先别着急,好不好?因为这节课内容呢挺挺挺多,挺深入,挺细的还啊,我其实就这节个经准备了很长长时间。但是乱序这个东西呢,我后面会讲,先别着急啊,总而言之就是先分分配空间,再付默认值,然后再付分付初始值。

就这个这个事儿啊已经被面试的时候面了好几次了,大家理解这件事儿就行。

再说一遍。好,做个。小小的总结。就是总而言之呢。漏的。漏了完了之后呢。默认值。然后呢出始值。这是class,如果是object呢new objectject。如果是 new的话,依然是。申请内存。

申请完了之后付。默认值。然后初始。

比后中间啊他有一个负默认值的过程,这点。

系列 3:P127:【JVM】单例模式 双重检查 - 马士兵_马小雨 - BV1zh411H79h

有恐怖。最恶心的是有的有一道题是这么问的。这道题呢我得打开原来的,咱们曾经讲过的一个模式,这个模式呢叫单立模式。我们找到单利模式代码啊,稍等一下。我在讲设计模式的时候呢,讲过一个单立模式。呃。

在这个单力模式里边啊。找到我的得力模式。Sing过 letter。哪去了?这儿了。在单列模式里面呢,我讲过1个DCL单例。好。呃,不知道大家还有没有印象啊,这个这个单例呢称之为。第一。

DDCL单位叫DCL什么意思呢?叫double。Check。double check啊,双重检双重检查是什么意思?比方说我们要对这个单例啊,呃,我们说我们分析一下这个这个小程序是怎么写的。

这个小程序呢其实上是这么写的啊,就是我们现在呢要为呃给manager06呢做个单例。那做这个单例的时候,我是这么写,上来之后先检查。我想做成多线程安全的那上来之后。

我先检查这个instance是不是等于空。如果它等于空的话,那说明还没有任何一个线程给他进行初始化是吧?同学们,那这时候呢我就好。加速上锁上锁,我来对他进行初始化。下面我又进行一个检查。

我为什么要进行这次检查?主要是因为我到这次检查到加锁这个期间,有可能被别的县城给处入放了。所以我又进行第二次检查。如果他依然为空,那么说明刚才这一段里头没有人进行过初始化。

这个时候我就可以踏踏实实的把它进行初始化了。你有manature06。但是这个面试题问的是什么呢?问的是。同学你好。这里的manager06需不需要加volatile?为什么?好,我先告诉你答案。

需要加voltile。为什么关于为什么主要是重排的问题啊,我记得我讲vollettail的时候呢,也给大家讲过这个问题。我在这儿呢,由于是整个这个也牵扯到类的这个加载的过程对对象的初始化过程。

所以我在这里呢再给大家重复一遍,为什么要加volt。如果说不加vollatail会发生什么情况?同学问我们来分析下呃,这件事啊,如果说不加volattail的话,会发生什么情况?会发生这样的一个情况。

就是第一个县程。加上锁。检查完了。第二个线程呢就是其他线程没有初始化,然后我加锁上锁上锁完对这个instance进行初始化。可是很不幸的是,这个初始化过程,如果初始化到一半的时候。

听我说初始化到一半的时候,什么叫一半的时候,就是我们缪了这个对象,而且呢还申请了内存,申请完内存里边的成员变量,假如有一个值还给它付了一个初始值为0。好,到这个情况下。

大家注意这个时候这个instance就已经指向这个内存了。所以这个instance已经不等于空了,已经不再是空了。那么在这种情况下,另外一个县城来了。另外一个县城来了之后。

他会首先执行这句话叫if instance空。可是这时候很不幸的是,这个instance还是空值吗?还是控制吗?不是了,我刚才说了,这个instance已经进行了一个半初始化状态。那大家你可以想象一下。

另外一个县城既然上来一检查这个instance,它不等于空了。我我有我第二个现程,我是不知道他已经他实际上是处于半初始化的状态。那我第二个线程是不是就直接开始用这个初始值了,而不是用那个默认值了。

我本来默认这是100,初始值是0。结果您倒好这个订单啊,已经有100个订单了,默认这是100。结果您倒好您第二个线程来了之后,直接拿零给我往上加,会发现你只有一个订单。所以这个时候就会出问题。

那怎么解决这个问题呢?解决这个问题的关键呢是在于加walllet。那有的同学可能会说,老师这事儿他妈神奇了,怎么会。把这个。这个。vololatile加上居然就能够搞定这件事儿。好,这里头是重排的问题。

指令重排指令重排我接下来马上要讲。但是在这儿呢选提一个预热就行。好,认真听。嗯,要了解这件事情的话。认真听认真听啊。

看这里。嗯。😊,我在basic里面随便写一个class啊,这class呢就叫T好了。没有。我啥也不写,我就溜了个T啊,啥也没有,就这么一句话。好。Yeah。质证一下。观察它生成的二进制码。Vi。

Show by code with the J class library。找到m。找到min方法。我们来看卖方法里面new这个对象的时候,他做了一件什么事儿。注意看他拗的时候缪缪了我这个T方法。

Dupplication invo special。呃。看这里啊。记得我是把这段切下来。对啊,基本上。还差了一个,我这小程序还差了一个一个小东西。Yeah。我们还得复制给变量啊,T小T等于6T嘛。

跑一下,然后再来生观察它生成的二进制码。Will。手败扣。没方法可了。呃,你看这里啊。这段呢我已经切下来了啊。四句话,new duplication invoke special a store。

好,这四句话呢我已经打切到这里了。

我们来详细解释一下这四句话为什么会产生问题。问题就产生于在这里啊。就是new这句话完成之后,其实内存已经有了,内存已经申请好了。下面这句话invoke special是调用构造方法。

把内存里这个M值原来是零给它变成8。嗯,是这个过程。好,接下来S store一是什么?A store一是吧?这个引用值赋值给那个小T。本来正常的情况下,应该是先调用完initialization。

调用完这句话之后,才把这块内存赋值给这个小T。如果是这样的话,那就不会出任何问题。可是很不幸的是呢,由于指令有可能会重排的关系,我再说一遍。指令有可能会重排这两句话发生的先后顺序有可能会不一样。

如果说不一样,A store先发生的时候,相当于先把这个内存地址扔到T里面了,然后再进行的初始化。OK如果是发生这样情况的时候。

就会发生我们刚才所说的双重检查单例里面有别的线程读到了那个半初始化状态的问题。好了。关于这一小段,看有没有同学有疑问的。有后面我们讲我们讲那个指令的时候,再再来说吧,好吧。好,如果有指令重排。

这样就会产生问题。因此这就如果有人问你这种DCL单例为什么要加volatile,你要解释到这个深度的时候啊,这道题搞定了。

系列 3:P128:【JVM】硬件层数据一致性 - 马士兵_马小雨 - BV1zh411H79h

刚才呢其实留了很多坑啊,估计有很多同学会有疑问说这个你这底层到底是怎么回事啊,它这个重开序到底是什么东西什么东西啊?这节课呢我们开始讲java memory model,java内存模型。

那这块内容呢又细又多又繁琐,我也不知道呃能不能够给大家讲的很很清晰很透彻。呃,咱们反正咱们多增加互动,你什么地方听着有问题的。我们呃多多相互进行探讨啊。因为我我这个内容呢越准备越多越准备越多。呃。

主要是就是由于咱们学员里头呢,还是有一些人去追究这些细节啊嗯。所以越准备越细越准备越细啊,这个我们慢慢慢慢讲讲听啊,如果不成的话,再往里挖。啊。

我我们现在来聊这个javajava memory model,就这块内容啊是又细又多又繁琐。呃,我来尝试着一点点的来给讲给大家听。那有同学说这个java memory model其实我讲了不少了也。

但是呢。那个这里面我们要解决一些什么样内容呢?就在这种高并发的情况下,java的内存模型到底是怎么提供支持的呃。一个对象弄出来之后,他到底在内存中到底是怎么布局的?好,我们主要讲解这两方面。

解决这两方面的问题,好吧。我们首先来看呢硬件层的这些并发优化的基础知识。注意这里面呢我先讲硬件,然后再来讲。呃,java的内存的模型呢,到底是在硬件的基础之上去怎么实现的,好吧。

因为我们聊java内存模型的实现,我要跟你聊呃,指令重排是吧?然后跟你聊呃,happens before原则,跟你聊什么八大这个是这八八大原子指令跟你说半天呢,你也不了解怎么实现的。所以。跟你讲那些。

你也要扣到硬件上来啊,因此呢在这里。我先给大家聊硬件,好吧,我们先把硬件聊一聊啊,然后呢再来讲java的内存模型,它是实际上是呃在这些硬件上进行架构的。呃,我们首先来聊的是这个存储器的层次结构。

这个是大家可以看这本书,叫深入理解计算机系统的原书第三版的第421页这个图我给大家拿下来了。这个是什么意思呢?这个的意思是。现在的这种CPU啊,这种硬件啊和呃原来的不太一样。它增加了很多很多的结构。

这些结构呢是通过缓存啊来进行的。当我们有1个CPU。有这个CPU呢,大家知道它速度特别快,这它比内存的速度大概要快100个数量级。然后它比硬盘的速度那就更多了,可能快100万个数量级吧。

差不多就这这么一个概念啊。嗯,当然呃更慢的呢是那个远程存储,远程网络存储我就不说了。所以现在的这种存储机的层次结构呢,是这么一种金塔型的。就是如果你文件特别大,存取速度要求不高的时候。

你甚至可以存在远程,存在磁盘上,这是没问题的。但是你要求我访问它的速度特别快的时候,你就得把磁盘上的某些文件给它放哪去啊,放内存里。放到内存里。好,如果我要求速度还快的时候。

我内存里面内容呢会放到我们的高速缓存里。这个高速缓存呢我们称之为L3,这个高速缓存也是在主板上的,因此是被所有的CPU所共享的。但是即便高速缓存,对于CPU来讲,它的速度在他看来啊也是慢的多,太慢了。

你慢的受不了。所以这时候我存取你里边数据的时候还特别慢,我怎么办呀?我在我CPU内部。还有两层缓存,第一层呢叫L2,第二层叫L1。然后最快的实际上是寄存器,就CPU内部最核心的计算单元。

只存储那么几个数,拿过来之后,我就算拿来之后就算算完就走算完就走,这是最快的叫寄存器。所以CPU要想读数据的时候做计算,读数据,读数据的时候怎么读呢?假如有一个数据要被读到CPU里去执行啊。

12这个数它的躺躺在硬盘上。他首先被漏到内存。然后CPU读的时候呢,首先是去尝试去高速缓存里面找。如果这个数在这儿呢,我就直接拿拿拿给CPU直接拿来用。因为这个速度非常快,他们两个之间离得比较近。

如果这个缓存里没有。他就会去下一层去找有没有这个数啊?如果有把它漏的到我最近这一集,再交给CPU。像CPU下次再去访问这个数的时候,速度就快了。所以这是一层一层一层一层的缓存结构。好,关于这个结构。

大家伙有一些什么样的问题没有?如果没问题,能理解这个结构的话,我们就继续。有问题的话,你直接提。总而言之,这个机格结构就是什么呢?离CPU越近。它的容量会更小,但是它成它会速度会更快。离CPU越远。

当然它就更慢。🤧。这跟双天尾派有有有有个鸟关系吗嗯。😀呵呵。😊,所以我们就是说CPU读一个数的时候,首先去最近的缓存里找,如果没有再去找下一层。如果没有再去找下一层。如果没有再去找下一层。

到内存里找着了,首先放到上一层,再放到这一层,再放到这层,然后再回来。好吧。关于这个速度到底能差多少?呃,这里呢我截了一个图。从。寄存器啊,如果是大概CPU周期一个时钟周期的话,那么L一大概要3到4个。

时间上呢1一个纳秒一个纳秒,这个纳秒是一个什么概念来着?呃,秒,然后是毫秒微秒纳秒应该是。10亿分之1吧,差不多11分之1秒啊,一个大秒。然后接下来是L2的开,L2开始,你要访问的时候。

大概需要10个使用周期。那么L3呢就是所有CPU共享的那个L3是40个使用周期。啊,你要到总线的话呢,那就更长了。主存的话呢,60到20个纳秒。啊,60到80个大秒。嗯。嗯。😊,好。

这里就会产生一个问题啊这里就会产生非常严重的问题。现在呢就我们再重新换一下这个模型的话啊,这个模型呢是呃CPU计算单元和计存器,这是最快的计算单元直接跟计存器相关来做计算的。好,这这是第一个核。

或者这是第一个CPU这是第2个CPU。好,假如我们有一个数在储存里,在那我们的内存里。就是那在内存里的时候,这个数它会被load到我们的。L3这个缓存上,但是需要注意的是,我刚才大家也看到了这个。

L2和L1。这两级缓存是在1个CPU的内部的。那也就是说会产生一个什么情况?会产生一个。我们的L3里面的或者说主存里面的这个数,它会被我们漏到不同的CPU内部。既然会落到不同的CPU内部。

那假如我的第1个CPU把X变成一,第二个CPU把X变成2。同学们,你们考虑一下。就会产生这个数据的不一致的问题。我们这两个之间到底要怎么样进行同步,数据的一致性在这儿就会产生问题。好。我我讲到这里。

不知道大家能不能理解这件事儿。就是说我如果用这种模型,它加强加快了效率,速度会非常快,但是它会产生数据不一致的问题。同学们。那好,如果能理解这件事儿的话,那现在到底是怎么解决这种数据不一致的问题呢?

你比如说两个县程,第一个县程在这个CPU里跑,第二个线程在这个CPU里跑,也有可能是超线程,超线程就是两个县程可以在同1个CPU里跑。那好,不管怎么样。

总而言之是啊这个CPU或者说这个线程里它改了这个数的话,另外一个线程到底怎么才能知道呢?或者另外1个CPU里到底怎么样才能知道呢?这是硬件级要解决的问题。那么硬件你要解决这个问题的时候,怎么解决呢?好。

听我说。硬件级要解决这个问题的时候,有几种方式啊。就多线程一致性的硬件层支持。实际让我们去读那个外部外部缓存,读memory读L3的时候,我是通过系统总线的。所以最简单一个办法就是把这个总线给它锁住。

咔嚓给锁住,什么意思呢?这句话的意思是说哎,你比如说啊。我们这里头改了这个数的话,大家伙都是通过一条总线去访问里面内容。我把这个我把这个把这儿给给这儿加个锁。给这儿加把锁。加班索的意思。

我这个CPU去访问这数的时候,我另外1个CPU不允许访问。相当于我叫我我是我我只有这把锁,其他其他CPU防不了。好,这是老的CPU干的这么一件事儿。这个呢叫总线索,这叫总线索,叫bus洛,叫总线索。

这个总线索大家想想。有谁有一些什么样的问题没有?同学们,你们想想。效率偏低嘛?为什么效率偏低啊?最最可最可还不还不是说我这个CPU要去访问X的问,而是说我这个CPU要去访问X给总线整个上了把锁。

另外1个CPU要去访问Y也得给我等着。为什么?因为他把整条总线全给你锁了。只有一个员部,其他的全国踏实在那待着。所以这个总线索是老的CPU才会这么用。新的CPU一般用什么呢?新的CPU用。

各种各样的一致性协议,我再说一遍,叫做各种各样的一致性协议。虽然说我们一直聊可能聊vololatile底层实现到底怎么实现的,就一致性怎么解决的。我们一般来聊是MESI可是我需要跟大家强调的是。

其实和MESI相关的这种协议非常多啊,特别多。有MEMIMESIMOSIsapsfirefly dragonagon这些都是数据一致性的协议。只不过英特尔的CPU用的是MESI协议。

所以大多数人用的是英特尔的CPU。所以一一般我们聊就是说我们呃底层的一致性到底是怎么实现的呀?是用MESI协议来实现。好,那MES2的协议到底是什么意思呢?非常详细的内容,大家呢可以呃参考一下这篇文章。

好吧。我把这篇文章给他家复制下来。这你如果说你们上那个计算机组成原理的课。呃,应该会学习到这方面协议的内容。不知道咱们有有没有有有没有在学这个课的啊。这是雷加的初始化,我来新建一个文件啊。

嗯,不用这个文件了。

GMM点MD。

小怪兽说上周刚学过老师PPT翻过去了嗯。也正常啊。姐人们。硬件层。数据一致性。硬件层属于一致性的,协议非常多啊。协议很多。In儿的。一那用MESI又称伊利洛因协议。呃,这个MESI的协议呢。嗯。😊,好。

大家可以参考一下这篇文章。这篇文章呢讲的还是比较细的。呃,但是这个协议内容呢其上它非常的细致。我在这里做一个简简要的介绍。好吧,这个协议内容是呃什么意思呢?其实就是它给每一个缓存的内容。

这叫缓存一致性协议嘛,给每一个缓存内容呢,做了一个标记。比如说我这个CPU里面我读了一个数进来X好,我给这个缓存内容做个标记。这个X和我们主存的内容相比,我到底有没有更改过,如果更改过。

我标记为M就叫moddify。如果这个内容我所独享,我标记为exclusive独享。如果说这个内容被别人我我读的时候,别人也在读,我标记为share。呃,如果说我这个内容在我读的时候被别的CPU改过了。

前面三个都很容易理解。如果说我读的内容被别的CPU改过了,我读的时候,我读进来的时候是2另外1个CPU把这里面的值变成三了。那么说明什么呢?说明我读的这个数已经是inval的,已经是无效了。

那么至于说我这几种状态到底什么情况下要进行处理,那么是根据我这个协议来的,我也也是根据我的指令来的。好,所以这个MESI的大概的意思其实就是这几种状态的一个组合。我再重复一遍,我改过叫modified。

我这个CPUCPU改过叫modified。我改过了,别人那里就就就是inval的了。啊,只有我在用,别人都连读都不读,只有我在用,它叫exclusive。我读的时候,别人也在读,叫share。

我用的时候别人改过了,叫invald。那好。所以它叫MIMESI的协议。那MESI的协议呢是通过这个协议来让各个CPU之间的缓存保持一致性。比如说举个最简单例子,如果有我我观察到我这个数是inval的。

但是我马上要对这个数进行计算的时候,我观察到它已经是inval的,我怎么办呀?我再去从内存里面把这数再读一遍。他就已经变成有效了。所以这个协议是这么来规定的。啊,我讲到这里。

大家是不是能大致理解这个MESI的一个意思?modified exclusive sharely valid的就是缓存的四种状态,以及对这四种状态的一个特征的处理。好,大致的一个意思,先搞明白。

当然你要是非要不详细到那个硬件里这种状态,什么情况下处理,这种状况下什么处理,这个对咱们来说这也真的没有必要啊。像这个就变成真的是变成那个那个呃组成原理的课了,是吧啊?过没有关系啊。

你大概理解什么意思就可以。既然是四种状态,那应该用两位啊,两个比特就可以标识了。但其实啊需要注意的是,这个MESI呢并没有完全解决锁总线的问题。这个锁总线在现在的CPU也是需要。MS我们称之为缓存锁。

原来的内容呢,我们称之为总线索。总线索,我们说效率比较低,缓存锁效率会比总线索要高,可是又会带来新的问题。有一些无法被缓存的数据,数据特别大,或者跨越多个缓存的数据好,这个时候必须使用总线索。因此。

现代的CPU的底层的一致性。是通过缓存一致性协议缓存锁加上总线索来实现的。好,我讲到这里,看大家能不能够理解这一块就说。现在。CPU的。数据一理性。实现。是通过什么呢?很纯熟。叫什么?请申请。

那么M现在呢。就是看对不起啊。吃饭了。MBSI啊等等各种各样的协议,指的都是锁缓存的这种协议。啊。

系列 3:P129:【JVM】缓存行、伪共享 - 马士兵_马小雨 - BV1zh411H79h

好,那刚才这小段如果没什么问题的话呢,我们来看缓存行的概念。好,这里是有可能会被问到。我再说一遍,缓存行这个概念是有可能会被面试中问到的。好我们来聊缓存行是什么意思?缓存行指的是什么呢?

指的是这样的一个东西。就是当我们要把内存里面的某一些数据放到我们CPU自己的缓存里的时候。他不会说把只只把这一个数据放进去。比如说我用到了一个数据,12,int类型,它只有4个字节。

但是我读这个缓存的时候,不会说只是把这四个字节读到我缓存里,而是为了提高效率,他会把四个字节后面的一堆内容夸机全都读进去。好,这个一般称作读读一个内容,把一块内容全读进去。

这一块内容是一个基本的缓存单位。这个缓存单位呢称之为catchline,称之为缓存行。这个缓存行目前多数长度为64个字节。

读取的时候。独取缓存以。can始 line为基本的。目前啊多数的实现64个字节。哦,那这里就会产生一个问题,产生一什么问题呢?就产生一特别好玩的问题。就是你分析一下,假如这个X和Y位于同一个缓存好。

我第1个CPU其实只用X,然后我一读的时候就把X和Y一块读进来了。假如我第2个CPU只用Y。然后我读的时候也会把XY1块读进来。哎,同学们,你们考虑一下,它就会产生一什么问题呢?会产生一个这样的问题。

就是如果我第1个CPU,我把X改了,我要通知其他CPU的话,注意我通知的时候不会只通知这一个内容,而是我通知说我整个缓存行被改过了,它是处于一个通知CPU啊,这个缓存行已经是inval的状态了。

麻烦你给我更新一下,结果他又重新把整个缓存行跨机又读了一遍。然后第2个CPU改完Y,他通知一下,结果第1个CPU跟Y没有关系,他只要读X,结果他又把整个缓存行又重新读了一遍。

两个互相无关的这样的值在这里变来变去的时候,竟然内部会产生这种缓存行的互相影响问题。因为他们位于同一行。好,我刚才讲的这个问题,不知道大家能不能理解好,这种问题叫什么呢?叫做伪共享。为共享什么概念呢?

就是位于。同一缓存黄的。两个。不同数据。对。两个不同。手据有锁定。产生互相影响。作共享问题。啊,这个问题面试确实是有人被问到过的。好,关于伪共享。是什么概念?在这里有没有同学不能理解的?没有问题。

你扣一。有问题啊,你直接提。杰杰潘生说,伟工想是不是不好,当然不好了。你想想看,我本来只用这一个数,结果呢。由于你用了我的邻居,结果你会影响我这个CPU在这里不停的跟这儿重新漏的整个缓存行。

重新漏的整个缓存行。那你是你想想看,你这你这个这个这个当然是不好的,对不对?那有同学我会说哇,这个老师会有会有这种情形吗?我告诉你有程序还能证明呢。所以我写了一个程序,但是这个程序呢实际上和并发有关系。

所以我写到了并发那个包里啊。他因为后面的这些东西呢,其实真的和内存的也有关系,和我们并发呢也有关系。呃我放在哪呢?都都有问题啊,我就挑一个仿,我放在了并发那个包里,我给大家记下来,记在笔记里。

大家看到笔记的时候去找就可以了。腿共享问题。好,是在这个文件里。这UC下面的。C208我把。项目打开这UC。

呃,大兵问为啥XY都会被引用,没有,都会被引用啊,是因为它位于同一个缓存行嘛,咱们去访问缓存行的时候啊。访问一个数据的时候,都会把整个缓存行都缓存起来。他俩是独立的,但是它位于同一行。他俩是独立的。

X四个字节Y四个字节。X4个字节Y4个字节,但是他俩挨着能能理解吗?所以1个CPU要去读X的时候,他会把整个行全都漏到自己的内存里。所以Y是不是就跟着进来了?另外1个CPU要读外的时候,整个行漏到内存。

X也就跟着进来了。那我这个CPU改了个Y。是不是整个行就数据都改了,我会通知其他CPU你你你把这行的内容全都给我更新一遍。所以我改了个外,结果导致我第1个CPU只用X的,就得把整个行重新重新一遍。大兵。

你听明白了吗?为什么会有混这种设计?硬件的设计上很多时候是按块来执行的,它并不是按一个字节一个字节一位一位来执行。读取整个块儿效率会更高。大兵在不在啊?不太理解这这个一行是个啥概念,一行就是一块内存。

你就理解就是一块连续的内存,64个字节字节数组能理解吧,64个字节。一个一个的字节数组,大兵能理解吗?嗯,对你就当就是1个6十4字节的数组就OK了。好吧,就这么简单。

不用理解他理解他给这6十4节起取了个名,就叫catch line,叫叫叫叫呃缓存行啊。不用去追究他的这个概念。缓存的一个一个一个级别的一个最小的单位,就是64个字64这个字节的数度,好吧。

64位是64位,这是64个字节。大哥,64个字节是多少位啊?64乘以8512位好吗?你这么晕呢嗯。😀H。😊,没事儿没事啊。偶尔被怼也是正常的啊,被老师怼也是正常,老师也经常被被被别人怼啊。嗯。

希望你们有一天赶紧怼怼老师啊。呃,其实教科学是一个互相促进的过程,有的时候你能怼怼我,也能促进教学质量啊。好不说了,主要主要是我还没有跟新同学们讲过这个自尊心的问题,我怕你自尊心受不了。

都给我放下子任写啊嗯。好。我说啊认真听认真听,我们来看这个缓存行的问题啊,缓存行就有产生一些很好玩的问题。你以前可能没有接触过。呃,但有一些优秀的开源软件,他内部已经开始考虑这个问题了。然后来注意看啊。

😊,嗯。嗯,说是 Sharon。好,你你认真看啊。呃我们来看这个小程序啊,这个小程序干了一件什么事呢?呃,我有一个呃class T这个class里边啊就只有一个volatile long。X到 L。呃。

就是一个浪类型,这浪类型是几个字节来着?大家还记得吗?8个字节对吧?将来呢我又弄了一个T的类型的数组,这个T类型数组呢呃呃呃耳瑞啊里边有两个值啊,第一个值呢是newT,第二个值也是一个newT。呃。

那大家想一下啊,这呃这就这个初静态初始化块完成之后啊,内存里面什么情况呢?内存里面是一个数组,这个数组呢有两个这这个数组里边指向的是一个new出来的对象啊。

这个对象里面的内容呢就只有一个8个字节的浪类型。大的字间。大个字典。好,这是第二个第二个是这个很简单啊。然后接下来呢我们来看我起了两个县程。第一个县程呢呃。第一个线流是循环了100万次。

然后把are零里面的那个X值不断的在产生变化。分析一下啊,听听我说,你看啊,这是第一第第一个线程,他会干嘛呢?把这个X的值啊不断的在里边对它进行变变第一个。对不起。这是八个字节,是一个数啊。一个数组。

010位置上一位置上指向了我们T那个对象,T那个对象里面只有一个值浪类小。这这边呢只有一个指浪类型。好,第一个线程呢会把这里面这个值不断的产生变化。刚开始是零,然后变成一变成二变成3。总而言之。

这个值是在不断变。第二个里面呢,这个值呢也在不断变。那大家分享,如果说刚好这两个位于同一个缓存行,这俩值。正好呢位于同一个缓存行。然后呢,又正好这两个县程是位于不同的CPU。

当然这两个线程应该是位于不同的CPU那就会发生什么情况呢?就是这第1个CPU啊,它是在不断的更新这个缓存行,第二个CPU也在不断的更新这个缓。我们就想模拟这么一件事儿。来看看他的执行时间。好。

关于刚刚才呃我讲的这一小段,有没有同学?有疑问的。啊,如果没有问题,哎,我来我来看看这个整个的两个线程的执行时间,好吧,跑一下 run。嗯。再再次跑一遍啊。再跑一遍。后一遍。反正大概的一个意思吧。呃呃。

三位三位,你记着前两位是28啊,扣掉后面6位,前两位是28就行了。21。28反正大概就这么一个数啊。呃,这是那个我们没没有。这这这这这个呢是我们这两个呢是位于同一个缓存行啊。呃。

然后我们再来看另外一种写法。你看这种写法啊,这种写法就就就比较好玩了。大家看能不能理解啊。这种写法首先来说呢,我们下面依然是啊依然是。呃。依然是这两个县程,这两个线程呢依然在不断的更新。

刚才的那个那个数那个X值。第二个线程呢也在不断的更新。另外一个呃X的值。然后这两个呢刚才是位于同一个缓存行。假如我想办法能让这俩不不位于同一个缓存行。我想个办法能让这两个呢不在同一个缓存行里。

它位与两个不同的行。那这两个县程之间互相呢就不会再有影响了。第一个线程会读第一个行进来。第二个线程会读第二个行进来。好,他们互相之间就不会再有影响了。理论上说,这个效率会比上一个效率要高。好,我这么讲。

大家能理解吧?所以我干了这么一件事儿。我定义了另外一个类,这个类呢叫padding。这类里面呢啥也没干啊,就来了8个浪类型的数。哥们儿这8个浪类型的数啊,对不起,7个啊7个P1到P7。七八五6。

64个字节8八64。对,七八五十6。然后我这个T是从padding继承,从padding继承的话。就会变成什么呢?我前面啊二话不说,先已经占了5656个字节。然后我会把我自己的这个存在后面。

所以这个东西自己就占一行。就这个T对象自己就占一行,因此他绝对不可能和另外一个T对象。位于同一个行列。那这种情况下,我们再来看它执行的顺序效率。109。109。不对呀,92。105。

这个数呢我除了1个除了1个100万啊,我把上一个数也除1个1100万做一个对比。我们先来看第一个啊,第一个是位于同一行的情况。我除以1个100万,让大家看清楚一点。不对呀。31。39。第二个没效率。

反而变低了啊。152。126。时间长了,什么情况啊,我看看啊。😊,实验没做成功啊,这个实验比较比较比较葛。有可能恰巧不在同一个混存行是吧?也有可能啊也有可能。1一startT2start。小爷。

Long。呃,我想想想问你可能出在哪儿啊?100万。哦,这是1000万啊,sorry。问题出在这儿啊,这个是1000万啊,那边是100万,对不起啊。😊,还说呢,看啊都都改成100万啊,对不起。

循环次数不对啊。😊,第一个啊都是100万,循环100万次。跑一下。50嗯,好。31完了来看那个第二个也循环100万次啊。好。38。17。23。23。25。第一个多跑两次。100万次还是太少了。

我们来来来1000万次,两边都改成1000万次啊。嗯,这个比较讨厌,我应该定义一个呃定义一个成员变量的啊。Iteration的是算了,懒得重新定一了。1000万次。这是第一个。第二个呢也来。

1000万次。然后第1个1000万次跑一下。270。好。311啊,大概就是二三百吧。第二个1000万次。176。107。115。好啦。现在大家是不是有点感觉了?呵。就是第二种方式呢。

虽然他多占了很多内存,就是他没事啊,把这些那个内存啊给那个缓存行做了一些对齐和填充,这叫缓存行对齐。然后。缓存行对齐对齐完之后呢,它的效率反而提升了。What。Yeah。所以这就是比较好玩的地方啊。

因此啊听我说。奇骏说100万L是什么型号?什么意思?这这这没看懂。你哪哪儿没看懂。浪类型L是浪类型。下划线是允许的。消防线是允许的呀。GDK哪个版本加的1。8还是哪个版本来着?啊,1。

8之后肯定是允许的啊。ok。呃。这个期是吧,这我就不不记得了啊,反正那个1。8之后肯定是允许的就行了。那通过这你就能看得出来,我们通过对缓存行的一个对齐,居然能够提高效率。这样能提高效率。好。

这件事呢已经被很多开源作者给用起来了。我在讲呃并发的时候讲过一个开源软件叫做drupor。大家还有印象吗?disruptor还有没有印象?号称那个单机效率最高的队列嘛,在它里面的原码里面有一个。

它里面关于那个它里面有一个。呃,这个有有有有一个它不是一个环嘛,这个环有一个这个我们叫它叫叫叫叫做cursor叫做呃游标,或者叫做指针。就这个指针大家还有印象吗?就这个指针呢用的非常的频繁。

而且是在多线程你要用好,它转来转去转来转去转来转去。如果说被多个线程,多个CPU所访问,互相之间缓存好有影响的,那这个效率就变低了。所以它这个指针里边内部定义的时候,居然是这么来定义的。

大家看看是不是能够理解了。在这个指针的前面,这个cursor的前面。他怼了7个long,在他后面又怼了7个 long。就保证这哥们不管是跟后面对齐或者跟前面对齐,他永远不会跟其他人混在同一个缓存行里。

啊,折子系说link transfer Q里边也有是吧啊。这个你可穿Q有没有我还真没有印象。既然折的细说有,那大家可以去读一下啊。那这就是这个缓存行怎么提高效率的地方。桃子说这样不浪费吗,浪费啊。

谁说不浪费了,肯定浪费啊。但是浪费的这点空间,跟我们提高的效率相比,只要还值不就行了吗?有利有弊,好吧。好,关于这件事情,我不知道大家理解理解清楚了是吧?所以这就是呃底层的这个MESI协议。

以及它的一些个实现细节,以及怎么能用MESI来帮助我们来够能够实现程序的效率啊。好听我说。呃,这个位共享问题怎么解决呢?解决的话就是使用。本存行的。对其能够提高效率。当然他会浪费一定的空间。

就看你浪费的空间值还是不值,以及你有多少个数要浪费这个空间嗯。

系列 3:P13:【多线程与高并发】线程的概念 - 马士兵_马小雨 - BV1zh411H79h

多进一些,复习的时候找视频比较难,呃这个嗯不用着急,我讲完之后呢,会把这些个总结为单独的一门小课,到时候你复习起来呢就容易的多了,今天呢我们来讲第一次课,我叫多线程高并发啊,内容上我就唯一重复了。

刚才跟大家说过了,这个xy的关掉机器有点慢,呃我先说一下,为什么要讲这个多线程高并发啊,原因是什么呢,原因是现在啊,嗯如果你想拿到一个比较高的薪水,在面试的时候呈现了两个方向的现象啊,第一个呢叫上天。

第二个呢是入地,那么入地的这部分呢,相当于就是那个很多特别基础的内容,就越问越基础,上天这部分呢高并发缓存,大流量是这部分的内容,今天我要讲的县城呢,实际上是入地这部分内容啊,土行孙这部分的内容。

我们呢先讲第一个,就是我们先从那个什么是线程开始,给大家复习,这个是给大家稍微复习一下啊,不知道有多少同学是基础不太好,说,什么是县城都不知道的,不知道有没有,如果确实有的话。

听我说这部内容我花的时间肯定不会太长,呃,老师的那门基础的课,就是特别特别老的那个视频里头,那个讲的基础的课程,如果你现成的概念不清楚的,先去那个课里头找到县城,那一章是第11章,先把那部分内容看完。

看完你才能听得懂后面的课,早不知道说清楚没有啊,同学们,那个亡命天涯说老师并不是很清晰,这个没办法,他是好多年前录制的嗯,那会儿那个屏幕最大的分辨率,还比不上现在的1/4呢。

所以这个是没有没有办法的事情啊,不过在代码应该是大致能看清楚,我看过,那么今天呢,我先从到底什么样是一个线程啊,来开始给大家复习,什么是县城。

有这么几个概念啊,第一个呢是什么是进程,什么是程序。

什么是进程,什么是线程,什么是先程是吧,这几个概念呢,嗯,现在啊我是在哪块儿给大家讲的,这,就这么几个基本的概念啊,第一个呢什么是呃一个进程,什么是一个县城,什么是一个携程,或者叫什么是一个先程。

那这个我们后面还会讲,这个不多说,那什么叫一个进程,什么叫一个线程,做一个简单的解释,你的硬盘上有一个程序,这个程序是什么呢,叫qq。ex e,这是一个程序,好吧,叫做program好。

这个程序是一个静态的概念,就是他扔在硬盘上,没事也没人理他,但是当你双击它唉啵它就弹出一个界面来,然后你输入你的号码密码,你就进去了,ok这个时候呢叫做一个进程,就是他起来之后。

一个程序运行起来之后叫一个进程,所以进程呢是相对相对于程序来说,它是个动态的概念,这个意思呃,作为一个进程里边儿最小的一个执行单元,其实呢它就叫一个县城,这块儿呢估计有的同学如果基础差,可能听不太明白。

我在这儿呢给大家做一个小小的演示,看这里啊,怎么样子才能起一个线程,线程启动的方式呢,我一会儿再讲啊,我们现在呢先定义一下呢,到底什么是县城呃,我定义了一个class,这class呢从哪个类继承呢。

从thread这个类继承好,重写它的run方法已经重写完了,在这里面我要想调这个run方法有两种方式,认真看,那么第一种是news net一点run,我就直接掉了。

可以在main方法里面我调的nt一点run,在这里面呢它会输出t1 ,然后在我的main方法里,调完了t一的run方法之后呢,又会不断的输出t2 ,sorry,不是t2 ,是main运行一下。

跑一下看看啊,好结果你会看到是吧,t一先输出t一或输出ma好,这种方式叫做方法调用,你直接弄了个t这个对象,然后调了他的run方法,先执行run方法,完了之后马上执行后面的输出main的内容。

但是呢你想运行这个run,还有一种方式,就是net一点start,为什么他用star的方法,是因为thread这个类里面有star的方法,裸体一start,然后与此同时main方法开始运行输出的结果。

你会看到的和原来大不一样,是may和t一交替输出,原因是什么呢,当你调star的方法的时候,从这个地方会产生一个分支,这个分支会和我的主程序一块运行,如果用图来表示的话。

run方法的调用相当于main方法开始,然后奔跑到run方法,那执行,执行完了之后再回来继续那方法执行,所以他先输出t1 ,然后再输出main,说来说去,在你的程序里头呢只有一条执行路径。

但是如果当我们调start的时候,好到这儿了,到点儿了,那个方法继续运行,与此同时,run方法同时运行,ok这个呢就叫做不同的线程同时运行好了。

所以现成的概念用一个最简单的啊,不用那个书上,书本上那些刻板的那些术语来定义的话,非常简单,一个程序里不同的执行路径。

系列 3:P130:【JVM】乱序问题 - 马士兵_马小雨 - BV1zh411H79h

O。这是呃硬件的数据一致性。那么讲到这儿呢,我们就聊完了。下面我们来看这个乱序问题。执行执行顺序的问题。好,听我说执行顺序这件事儿啊,就特别恶心了。执行顺序这件事呢,很多资料呢讲的也不全。

也也也也也细节也特别多。好多呢把各种的概念混在一起。这么来讲,所以很多文章你可能看了半天,看不太明白。啊,没有关系,我今天尝试着讲给大家听,尝试给大家讲明白,好吧。当然我要讲不明白的话呢。

大家就怼我就行了,好吧。好,我们继续继续看啊。😊,好,现在的CPU为了提高效率。他呢还会有各种各样的一些个优化。那么这个优化呢就叫做CPU的乱续执行。这个乱序执行怎么理解呢?就是说。当我们CPU啊。

由于它速度非常快,我们从内存里面读进来一些指令的时候。当执行这个指令的时候,另外的指令可以同时运行。这句话是什么意思?好。看这里。嗯,乱续之行这件事呢,我们这么来理解。认真看。

比如说我们CPU啊执行了我我我一次性从内存里面啊,这是我们内存。然后这是我们的CPU。CPU呢从内存里面读了5条指令,读进来了。读进来之后,他这条指令呢,比方说他进行啊算第一条指令的时候,1234。

算第一条指令的时候,第一条指令要干嘛呢?第一条指令要去内存里面的某个位置读一个数据。这个事很正常是吧?这条指令需要读一个数据。好,我们刚才说过这个CPU比内存快多少啊?100倍起步好吧。至少是100倍。

也就是说,如果我在执行第一条指令的时候。需要等着这个数读回来,我才能进行下一条指令的运行。好,在这种情况下,我这个CPU啊。就得等100倍的时间在这等着。好,我讲到这儿,有没有同学有疑问的?

所以现在的CPU就干一件事儿,就说这个指令去读数据的这段期间。我就会分析下面的指令。如果下面的指令跟我们上面这个指令没有直接的依赖关系。行。我下面的指令先运行。就是等着你回来的这段期间。

我就可以直接运行下面指令。等什么时候哥们儿,你把这数读回来了,我再接着运行。好,关于这一点,不知道我讲清楚没有,就是CPU为了提高效率。他会打乱。原来的这种执行顺序。会在。一条。指令。执行过程中。

比如说。去内存。读数据。大概要这个呢要慢100倍。这个时候去同时执行。另一条指令。前提是。两条指令。没有依赖关系。那什么叫没有依赖关系啊?我这是很容易理解啊。你说第一条指令叫intA等于8。

第二条指令叫A加A加加,你说它肯定有关系吗?100%有关系,你得有了这个值才行。第第一条指令啊这个这个举的不是很明,比不是很明晰,要intA等于8intB等于A。那么想想看这两条指令有没有依赖关系啊?

有啊,你这个A的值必须得先有了,我B的值才能有啊。所以这种情况下,他就不会乱续。但是没有依赖关系的情况下,他就会乱续执行。那举个形象点的例子啊,也是咱们网上我查了很多资料啊,他有有一个举得还挺形象的。

就是如果CPU在干这么几就几个指令,洗水壶、烧开水、洗茶壶、洗茶杯、拿茶叶泡茶。那但是其实呢他真正执行的时候是可以按乱序执行的。什么意思呢?就是我洗水壶烧开水的过程,我就可以洗茶壶洗茶杯吗?

就像多线程一样。对,没错,其实类似于内部的多线程。所以这个时候好,他就是一个乱序执行。呃,有一些文章我认为写的不错的,我就在这里给大家呢总结下来了。假如你。自己学习的过程之中,也可以去参考这方面的文章。

我读了很多篇,我认为对大家来说有帮助的,我就给给大家列在这里啊。好了。呃,这个乱序执行呢呃读的这个乱序执行呢很容易理解啊,听我说。这个读过程的乱乱序这行很容易理解。就是我我我我去内存那边读个数据。

因为它比较慢,所以我同时执行其他的指令。但是有很多情况下,还有别的指令,你知道吧?就就特别好玩的啊。呃。其实这个写指令也有也有可能是乱续的,什么意思呢?就是CPU啊。

在L一这个缓存和CPU中间还有一个缓存叫WC bufferfferWC。嗯。WC版粉注意不是厕所啊。注意这不是厕所的概念。

WC叫rightite combiningright combiningright写。那么combining合并叫合并写。合并写这么一个概念,合并写是什么意思呢?合并写的意思就是说。写操作。也可以。

进行合并。合并写的意思就是说,当我们CPU。这么一个情况啊,这个比较复杂啊,尝试解释一下,你理解就可以。这是我们的CPU。他需要给某一个数做计算,然后把这个结果写回到我们的主存里,写回我们主存的时候。

大家知道呃,他有1个L2,然后有1个L1。好,当我们写回到主存的时候呢,CPU呢计算了这个结果之后,他首先会把结果写到。L一里面。但是假如L一里面没有这个值,就是说它缓存没有命中,这时候怎么办呢?

它会写到L2里面。但是他写完写到L2的这个过程中,由于L2的速度非常慢,所以在写的过程之中。假如这个数。后续的一些指令也改变了这个指,他就会把这些指令合并到一起。扔到一个合并缓存里。

做做一个最终的计算结果,扔到我们的L2里。所以这个叫合并写,就是把好多步合并成一步原因的产生,还是由于哥们儿,你这太慢了,我这算好几步,你这我还没没没没访问到你。所以这是一个合并写的机制。

关于合并写这件事儿,看看有没有同学有疑问的,就是读我也可以乱序写,我也可以进行合并。

好,那写合并是一个什么概念呢?我们来看一个小程序。

嗯,这个java也能模拟出来吗?可以,这个java也可以模拟出来。大家看这里啊,这个就有点抽象了。当然目前面试还没有人问到过这么深入的内容。呃。尝试讲一下。尝试讲一下啊,也是第一次讲,讲的不好。

大家多提意见啊,合并写。给大家一个参考文章,然后告诉大家是在C0JUC里面啊,JUC下面的029。Right。Combining。

combine合并rightite combining合并写合并写什么意思呢?关于这个合并写呢有一个细节,就我刚才说了嗯。这个CPU呢会把。会把其中的一些个指令呢写到一个合并写,就合并写缓存里面。

就WC bufferffer。但这个缓存啊它它它的这个缓存可以说它比L一还要高啊,就是还比L一还要高级。我们说L1L2,然后整个大家伙一块共享的L3,还有呢储存。好。

但是这个buffer啊实际上它比L一速度还要快。比那个L2速度还要快。所以这个buffer非常贵。这个buffer一般就只有4个位置。一般就只有4个位置。所以如果只有4个位置的话,大家你考虑一下。嗯。

假如说我们同时写东西的时候,我们只要说不小于这四个位置。sorry,就是比这四个位置要小,我只写一个或者只写两个,只写三个。我同时可以把这几个位置全写好,全写好之后一次性的更到L2里。好,这是一种方式。

那么还有一种方式啊,假如说我要写一次性的写多少个呢?呃写写六七个七八个。那么这时候我要分两次才能够把这个合并的内容写到L2里。好,我再重复一遍啊,这里头有点绕。这里有点绕啊,我再重复一遍。

就是说由于合并写的这个buffer,它的它的位置非常少,它非常的宝贵,只有4个位置。现在CPU就只有4个位置。那么当我们往里头更新一些内容的时候,假如说我一次性的写不超过4个,我只写三个,或只写两个。

只写一个。好,这个时候这个合并写的内容它满了啪叽就会扔到我们的L2里。好,这是速度比较快。所以第二种方式呢,就是说如果我们写的比较多的话,它会分成两下啊。第一下呢写满一次,写写过去。

第二下再写满一次再写过去。所以这就产生了一个比较好玩的问题啊,这么一个问题。就是说假如。我们在程序里头要是经过我要同时修改,比方说6个位置。我是把它分成三个一组块。还是说我6个位置同时写会更快。

就产生了这么一个疑问。三个一组分成三个一组,这三个一组呢就保证这三个同时修改的时候,我这一个一个buffer满了之后,啪机马上写下去。但是如果我要是6个合并到一起的话。

他就要内部进行一些个并发性的东西进行控制。就说我这三个满了才能写,然后必须等着另外三个等等。不知道我大概的意思讲清楚没有?我们就来做这个实验。我们来看这小实验怎么做的,这小实验特别好玩。

这是我原封不动的拿了一个老外的程序拿过来的。老外这方面我觉得他做的真的挺到位的,特别好玩。啊,你注意看啊,这个干了一件什么事呢?其实呢他就做了两个循环。第一个循环是这么干的。

这个循环啊是同时改了6个位置。而瑞ABCDEF同时改了6个位置。这个循环我要循环。第二个循环干了一件什么事呢?第二个循环干了这么一件事儿。第二个在第二个循环里边是。第一个循它分成了两个循环啊。

第一个循环呢改其中的三个位置。第二个循环呢,改另外三个位置。那么你们分析一下,如果说这几个位置都一样的情况下,哪个效率会更高?一个位置就一个字节。这自戏就一个字节。你看啊这两种写法。

我再我我们再来看一遍。对,是4个位置。但是他有可能啊这个I的值有可能占一个位置。有可能占一个位置。所以这个事呢做的实验呢也你看啊这个B的值,这个值有可能占个位置,知道吧?这个值有可能占一个位置。

所以呢它这里实验用的是三个位置啊,就特别好玩。就在于这里。你看第一个呢,它是用。一下更改6个。第二个呢,居然是分开三个,再分开三个。这两个效率按照正常的一个想法,一定是第一个效率更高吗?是吧,同学们。

来,我们来看一眼第一个效率呢,第一个叫run case one,第二个呢叫run case two。第二个还分开了,还重新有一个负值。怎么想也都是第一个效率更高。但是正是由于这个合并写的技术。

White。我喜欢的次数太多了吗?啊,你看第一个循环。第二个循环看到了吗?你你从这个位数上就能看出来。当然他是连连着循环了三次啊,来看平均的结果。第一个循问。

single loop就是只有一个循环的情况下。第二个是分开的循环,split split loop效率差一倍。好,就不演示完了。为什么效率会差一倍?因为这种写法充分利用了合并写技术。😀Ha ha。😊。

😀Okay。😊,这有点太葛了是吧?😊,分三个不会差3倍。分三个不会差三倍啊,节节攀升。你分三个的话,你因为合并写技术只有4个字节。大哥,你要分三个的话,你里边每次写两个。

那那他还等得等着另外两个的值过来,我才能够一次性的刷过去。说这是不对的啊。超过4个字节不能合并。哎,这个A问题提的很好啊,A这个问题提到关键点上了。没错没错啊,我刚才没讲透的,应该就这点。

就是说你看啊咱们上面是6个,上面是6个会发生什么情况呀?一次性循环是6个嘛,这6个里头会有4个填满这四个字节的缓存,然后填满了之后,剩下的还有两个嘛,对吧?这两个就得等着等到下一次循环的时候。

有另外两个填过来,或者有别的那个CPU往里头填两个啊,对不起啊,是别别别的计算值往里头填两个。所以这个就不如一次4个一次4个一次4个,一次4个销率更高。嗯,这么来。合并写就快了。对。

正是由于CPU呢有一个特别高速的缓存,它只有4个字节。所以如果我们能让四个字节,每次都填4个,每次都填4个,每次都填4个。那相比第一种就是一次循环填6个,6个会分成4个一个,4个一组。

两个就得等着另外下一次循环的两个会比这种方法效率更高一些。因为像下面这种方式,他每一次循环都要等下一次循环填满。而是我们分开两组的情况下,就是一次性的咔机就填满,直接走直接走,就跟铲铲的铲铲铲土似的。

你每次都是一铲子满全满了,直接往上一扔搞定。但这铲子不满,你就在那等着嘛,等下一铲子装满了之后,你才能往上走,效率就要比一次性的全满严丝合缝的效率要低。三个没有填满,因为这还有个B呢,这还有一个呢B。

posted @ 2024-11-22 16:57  绝不原创的飞龙  阅读(216)  评论(0)    收藏  举报