![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
平凡人笔记
文章平均质量分 59
平凡人笔记
平凡人做平凡事 成就不平凡人生
展开
-
网络通信IO模型-BIO
因为accpet会阻塞,如果因为没有客户端建立连接,就没有返回值,会一直阻塞,只有客户端建立连接,才能从阻塞变成返回,然后再读取客户端发送过来的数据,读取输入流并打印用户发送的数据,读取的话,也有可能变成阻塞状态,如果客户端一直不发送数据过来,服务器端就会一直阻塞,所以要把客户端读取的过程放到另外一个线程里面去做。刚才accept 3 阻塞在这里了,一个客户端连接进来之后,就会立刻返回一个代表客户端连接的文件描述符5,并且绑定了客户端端口号,原创 2023-05-28 23:02:43 · 1226 阅读 · 1 评论 -
网络通信IO模型上
每震荡一下,就会给cpu产生一个时钟中断,比如cpu正忙着读取某一个进程的指令执行呢,1/1000秒的时候,震荡了一下,这时候cpu会把这个程序的寄存器的值更新下,记录下此时执行的状态,即保护现场,然后从中断向量表中找到这个中断号对应的回调函数,这个回调函数是在内核启动的时候注册的,切换到另外一个进程之后,读取寄存器中的数据,即恢复现场,然后继续执行。cpu有一个时间分片的概念,比如在一个cpu的情况下,执行下内核里面的程序,再切换执行下用户空间中的程序,看起来很多程序在同时运行,其实是有先后顺序的。原创 2023-05-28 16:51:30 · 1420 阅读 · 0 评论 -
ChatGPT原理简介
贝塔系数(β)是一个权重, SFT表示有监督渲染出来的模型,把x输入之后,有监督模型会帮我们生成一个结果,强化学习ChatGPT也会生成一个结果,强化学习跟有监督之间的一个pk,两者做了一个除法,输出是一个句子,可以把输出一个句子叫输出一个分布或者输出它的概率分布,这时强化学习认为输入这个句子每个词的概率分布合在一起。是不是以后不上网吧就行了呢?我爸教育我,你这么做是不对的,我爸给了明确的标签,有了标准答案,我下次去网吧的时候,就会想一想是我不对,不是我爸不对,那这次我就不去网吧了,这是一个有监督学习。原创 2023-05-17 23:23:08 · 31711 阅读 · 13 评论 -
GPT前2代版本简介
承接上文2018年,Google的Bert和OpenAI的GPT绝代双骄,两者非常像,都是语言模型,都基本上是无监督的方式去训练的,你给我一个文本,我给你一个语言模型出来。GPT前两代没有什么特别的,第三代才有点大发神威。GPT还不是特别火的时候,已经预计每天产生450亿词,每小时生成100W本书,所以以后看到的东西,可能是AI生成出来的。这仅仅是22年5月份的GPT-3的情况。原创 2023-05-14 23:14:17 · 1837 阅读 · 2 评论 -
ChatGPT进化的过程简介
可以看到两者差距非常小,区别是两者使用的GPT版本不同。所以看了InstructGPT论文应该就可以知道ChatGPT大致怎么被训练出来的了。原创 2023-04-25 22:46:30 · 3132 阅读 · 0 评论 -
异构系统的事务统一处理模型Saga
XA和AT都是数据源代理,业务侵入型少;比如图1中这3个完全没有关系的服务,在总业务逻辑处理的时候,使用Saga的状态机来定义,调用服务1,再调用服务2,再调用服务3。Seata中的Saga事务模式是由外部的Saga提供的状态机来进行完成的,需要定义总流程,状态机里可以定义当前节点的调用服务,而且每个节点上可以配置当前这个调用服务的反向补偿节点。一阶段正向执行,比如T1和T2正常,T2到T3也正常,T3位置出现问题了, 就需要整体的回滚,这个时候就会进行反向补偿,把之前的已成功的状态都补偿回去。原创 2023-04-23 22:57:57 · 540 阅读 · 0 评论 -
分布式事务Seata-TCC事务模式
下单请求给到事务协调者,首先调用订单服务Try方法执行下单中的逻辑,然后调用库存服务,锁定库存,事务协调者如果没有收到问题反馈,就调用每个具体服务的Confirm,即调用订单服务Confirm执行支付逻辑,调用库存服务Confirm执行扣减库存的逻辑,如果扣减库存出问题了,就调用订单服务的Concel执行未支付或回滚的逻辑。TCC是二阶段提交协议,Try-Confirm-Cancel(资源预留、确认操作、取消操作),Try是对当前业务资源的检查,如果成功,则Confirm提交,否则Cancel回滚。原创 2023-04-23 19:52:16 · 525 阅读 · 0 评论 -
Seata强一致性事务模式XA的设计理念
如果库存减1了,订单并没有真正创建,这个时候读库存,读到的确实是99,这个99就是所谓的中间状态,这个就是脏读。AT、SAGA、TCC都是补偿型的,都会出现脏读的情况,当然Seata本身是有预防的,但确实会存在这些问题:可能会得到脏数据且最终一致性是允许有中间状态的,这也解释了为什么Seata支持XA,因为XA是强一致性的。如果一个参与全局事务的RM资源失联了,收不到分支事务的结束命令,那它锁定的数据就会被一直锁定,就有可能会产生死锁,这是XA协议要解决的核心问题,也是Seata引入XA模式要解决的问题。原创 2023-04-22 15:16:06 · 597 阅读 · 0 评论 -
分布式事务Seata-AT模式
一阶段,会拦截业务sql(比如订单先调用库存(库存减1),再生成订单),Seata解析sql语句,同时要找到当前要更新的业务数据,比如库存减1,在数据被更新前,保存undolog日志,再执行业务sql,更新之后的数据再保存到redolog日志。回滚的时候所用到的数据就在undolog,即在数据被正式更新之前所保存下来的原数据作为回滚的依据,通过回滚反向生成sql完成分支事务的回滚,事务结束后会释放所有资源和删除所有日志。TM发起全局事务的执行,不同的分支事务需要执行自己的本地事务。原创 2023-04-20 23:28:52 · 540 阅读 · 0 评论 -
分布式数据一致性解决方案推理过程
客户端从集群中节点3取数据的时候,因为它已经shutdown了(此时进程还活着,只是跟别的节点连不上 ,必须要找到另外一个小伙伴,2个节点的时候,才能对外提供服务), b和c只能从另外两台(节点1、2)取,这两台曾经又登记过a=3,所以对方一定能够取到正确的数据,这样就可以保证数据最终一致性了。为了解决可用性问题,本来不加b,a可以一直存活,加了b,b挂了,a没挂,给a写,还必须要同步给b,b还不在,只能阻塞等b恢复,即强一致性行为间接会破坏可用性。如果再有一个redis c,则出现问题的几率更高。原创 2023-04-19 00:00:13 · 218 阅读 · 0 评论 -
怎么设计秒杀系统?
在APP真正秒杀前,将要请求访问的页面资源缓存到客户端或CDN中,这样的话,在未来并发请求的时候,用户请求的是动态数据,而不是请求的静态数据,就不会因为请求数据量大,IO瓶颈等问题导致出现用户连接不上的异常。service服务通过MQ异步调用订单服务,将超出订单服务处理能力的流量放到MQ中,再由订单服务异步消费处理,这也是削峰的过程。用户确认订单信息之后,页面跳转进行购买付款的操作,通过接入层分流进入付款购买服务,付款购买服务查看订单的状态是否可以进行购买。订单系统生成订单,给用户返回请求成功。原创 2023-04-14 23:47:35 · 958 阅读 · 0 评论 -
Kafka是如何支持百万级TPS的?
程序读取文件,调用内核的read(fd 8)方法,由内核替代程序读取文件描述符fd 8,程序就进入了所谓的io阻塞状态,即由用户态切换到内核态,由内核调用驱动再去读取这个文件,内核驱动将文件数据读取到内核空间,内核再拷贝到用户空间给程序使用。这个空间和磁盘文件做了MMAP映射,从这个空间中读取文件相当于从磁盘中读取文件,即文件的数据是直接放到这个共享区域里面的,程序可以不通过磁盘读取文件,而是直接从这个共享区域里面读取,减少了一次内核到进程之间数据拷贝的过程。程序只需要打开文件,拿到输入流的文件描述符;原创 2023-04-12 23:11:16 · 846 阅读 · 0 评论 -
网络IO模型BIO->Select->Epoll多路复用的进化史
假设有一个客户端想通过TCP和tomcat 8080建立一个连接,fd3上一定会产生一个客户端建立连接的事件,这个事件一定会被内核的事件机制(中断机制)发现,所以内核会把这个区域的fd3拿出来,因为它有数据到达了,再放入另外一个区域里,另外一个区域放入fd3,只要tomcat这个程序未来调用过了epoll wait,就会把这个区域的fd3给tomcat,tomcat就会判断fd3的事件是有人建立了连接,所以它会调用accept接收并得到一个fd4,服务器资源会被瞬间填满,真正想去连接的人却挤不进去了。原创 2023-04-06 22:33:03 · 460 阅读 · 0 评论 -
MySQL 幻读问题
因为在RR(可重复读)隔离级别里,事务1的第二次查询没有生成新的readview,而是用的第一次查询时生成的readview,所以第二次查询返回2条数据,而不是3条数据,这就是幻读现象。select 执行的是快照读(某个版本数据的Read View),而update 执行的是当前读(最新的数据,即最新的Read View,因此更新了三条数据)。但是当快照读和当前读一起使用的时候才会产生幻读问题,因为执行了一个update操作,即用了当前读,此时读取的数据是不一致的,就产生了幻读的问题。原创 2023-04-02 19:30:54 · 384 阅读 · 0 评论 -
MySQL多版本并发控制MVCC实现原理
承接上文。原创 2023-04-01 19:08:29 · 441 阅读 · 0 评论 -
MySQL事务特性ACID实现原理
Mysql 索引特点MQ消费端如何保证幂等性?MySQL使用B+Tree的数据结构,尽可能少的层级或IO读取量的情况下,能够缓存或存储更多数据量且达到快速查询的效果。在进行索引存储的时候,索引的数据要放到磁盘里面,不可能将磁盘里面的所有文件一口气读到内存里面,因此要使用分块读取的方式,而操作系统本身进行内存和磁盘交互的时候是以页为单位的,按照页的整数倍作为某一个磁盘块来进行数据的读取。在进行数据读取的时候,还要确认一个事情:索引是要有key-value值的,key是指定的索引列,value是具体的行数据。索原创 2023-03-30 22:27:30 · 348 阅读 · 0 评论 -
MQ消费端如何保证幂等性?
承接上文RabbitMQ、RocketMQ、Kafka性能为何差距如此大?这是乐观锁的一种实现,每一次要对库存的数量+1,这种方式解决消息重复没有问题,但不太好,因为消息在生产的时候,生产者要判断id是不是重复的,如果是重复的,下一次version+1,相当于浏览器点击了2次。这种方式虽然可以解决消息幂等性问题,但要求生产者也要改动,一般情况下不推荐。并发不是很高用mysql实现,并发高用redis实现。在表上要构建一个唯一性的索引,电商平台有一个订单id,适合做唯一性的索引,比如在进行库存扣减的时候,每次原创 2023-03-30 22:24:11 · 298 阅读 · 0 评论 -
Mysql 索引特点
没有索引下推前,先根据name的值从存储引擎中拿到符合条件的数据,然后在server中对age进行数据过滤,有了索引下推之后,直接根据name和age从存储引擎中筛选对应的数据,返回给server,不需要做索引过滤;id是主键,name是普通索引, 先根据name值去name B+树找到对应的叶子节点,取出id值,再根据id值去id B+树中查找全部的结果,这个过程称为回表,回表的效率比较低,尽可能不要使用,避免回表的产生,因为需要回到原来的表里查询对应的数据记录。第一和第三个sql符合该原则;原创 2023-03-08 22:55:45 · 407 阅读 · 0 评论 -
Mysql Server原理简介
一个磁盘块16kb,读一次,3层,3个磁盘块,比如读取磁盘块1->磁盘块3->磁盘块7,依然读取了48kb的数据,假设磁盘块1中的p1+28占了10个字节,16*1024/10大约1600个子节点,第二层一个磁盘块也是1600个节点,第三层只能存16条,存满的话1600 x 1600 x 16=40960000,千万级别。所有的data都放到叶子节点里面去了,非叶子节点不存储实际的数据,只有在叶子节点才会存储实际的数据,这样的一个3层B+ Tree,如果存满的话,可以支持多少数据量的存储?原创 2023-03-06 22:45:47 · 1059 阅读 · 0 评论 -
HTTP的前世今生
那么tcp数据包1和3会提前达到缓冲区,tcp就会发现数据包1和3之间缺少了数据包2的字节范围数据,哪怕http2知道tcp数据包1中有stream id为1的数据帧,加上tcp数据包3中stream为1的数据帧,可以组装成一个完整的消息,也要耐心等待tcp至少重返服务器一次,来重传丢包的数据2的数据副本到达才能继续解包其他tcp数据交给应用程序层,就是丢失的tcp数据包2阻塞了tcp数据包3导致了tcp的线头阻塞,所以结论就是http2并没有完全解决线头阻塞的问题。原创 2023-03-01 22:11:48 · 354 阅读 · 1 评论 -
k8s node之间是如何通信的?
flannel虚拟出来了一组ip,然后进行node和node之间通信的时候,它实际上是通过node上实际的网络设备的ip地址进行路由。flannel network是10.1.0.0,10.1是整个集群总的网段,给每个node使用ip地址的第三位即给每个node再划分网段,每个node再用具体划分的网段再给pod分配ip地址。采用了扁平化的网络,这个网络的维护是flannel的demon,有新的node加入进来,通过etcd注册并分配这个node相应的网络空间,并且通知后台的damon用来控制报文的转发。原创 2023-02-27 15:01:43 · 699 阅读 · 0 评论 -
HTTP请求的详细过程
发生了第三次挥手,客户端收到了服务器的分手请求之后,带上+1的序列号和+1的确认码回复给服务器,于是服务器关闭了连接,客户端进入了定时等待时间,这两个报文的最大生存周期,不同的操作系统不一样,大约是1-4分钟即俗称的冷静期,冷静期后客户端才真正的断开。b站的响应结果是一样的,那起初DNS的域名是谁操作绑定在一起的,当然是b站所属的公司,注册了bilibili的域名,指定好域名的DNS,做好A记录解析来对应好服务器的ip地址,这样就可以通过域名访问b站了。如果你了解背后的原理再进行开发,那是见天地;原创 2023-02-27 14:53:33 · 293 阅读 · 0 评论 -
k8s service的底层实现
如果和当前的进程相关,就会进入filter表的INPUT这个步骤,当本机的进程有报文输出的话,会先走nat这张表的OUTPUT步骤,在这个步骤中可能再去做一个DNAT来决定这个报文的目的地址是原封不动的还是要做一些改动,然后再经过filter的OUTPUT链再走POSTROUTING就出去了,在POSTROUTING的时候还可以做一个SNAT(源网络地址的NAT),决定这个报文出去的ip地址是不是需要变化,源网络地址就是别人可以看到的这个地址,表示报文从哪里来的。原创 2023-02-23 14:50:16 · 360 阅读 · 0 评论 -
docker网络基础
vethe35b867@if4657是docker0在宿主机上新建的网络设备,和tomcat01容器里面的eth0@if4658正好是一对。local的简写,本地回环地址,127.0.0.1,它代表本地虚拟设备接口,默认被看作是永远不会宕掉的接口。本文简单介绍下,容器之间的网络访问、容器与宿主机之间的网络访问、宿主机上有哪些网络接口。docker使用的是linux的桥接,docker中所有的网络接口都是虚拟的。配对的网络接口,一端连接容器,一端连接网关,这样就可以实现容器之间的访问。原创 2023-02-23 14:50:16 · 384 阅读 · 0 评论 -
ingress服务
通过yaml文件创建ingress资源的时候其实就是在ingress的pod里面的nginx里面配置了路由关系,动态的加入了 order和user这样的配置,再通过nginx反向代理的方式进行请求的转发。这个是nginx ingress的一个注释,接受到外部的请求比如是api/user/v1,但是转发给user service或order service,按照根目录进行转发,去掉请求中的子目录,在DNS做域名解析的时候,一个域名只能对应一个ip,但这里有2个公网ip,所以这种情况怎么解决呢?原创 2023-02-23 14:49:12 · 170 阅读 · 0 评论 -
K8s调度器Scheduler
调度器给apiserver发出了一个创建pod的api请求,apiserver首先将pod的基本信息保存在etcd,apiserver又会把这些信息给到每个node上的kubelet进程,kubelet一直在监听这些信息,当kubelet发现这个pod的节点信息跟它当前运行的节点一致的时候,就会创建pod进程以及容器当中的docker image进程,创建相应的命名空间,使得进程之间互相隔离,这样pod就在这个节点上运行起来了。实际运用的场景比如前后端的pod运行在同一个node上。原创 2023-02-23 14:46:49 · 364 阅读 · 0 评论 -
CPU原理简介
当有了算法逻辑单元之后,整个计算的构成还需要其他的电路,比如时钟信号电路,一个是为了计时,再一个会不断的刷新电路,每刷一步电路就往前进一步做一个计算,因为到最后的时候,你会发现所有的计算都需要一个控制电路,控制电路必须一会联通,一会断开,每通一次整个的计算才会往前进一步。通一次电,计算才往前走一步,所以需要一个时钟电路,时钟电路需要电池信号,线圈一通电就会产生磁场,磁场把开关断下来,断下来之后就不通了,不通了之后,电池没电了,开关闭合,电流又通了,这样来回来去的。反之,当自变量取值相同时,函数为0;原创 2023-02-23 14:46:53 · 265 阅读 · 0 评论 -
线程的执行
地址线是一个寻址的线,QQ.exe这个程序放到内存之后,它一定会放到内存的某个地址上,比如这个地址是3号地址,在3号地址的起始位置是main方法,在起步的位置一定会放一条指令,操作系统会通知cpu,你去读3号地址,先把指令读过来,读过来指令如果是add,它就会通知地址线,再把后面的2个数字都读过来,读到寄存器,然后计算单元开始做add计算,计算完了之后,存到某个寄存器,然后再写回内存。一个程序的执行,首先把可执行文件放到内存,找到起始位置即main开始的地址,进行读取指令和数据,进行计算并写回内存。原创 2023-02-23 14:44:09 · 671 阅读 · 0 评论 -
CPU缓存一致性协议原理
一个long类型的x是8个字节,这2个x位于同一个缓存行的概率极大(尤其这2个x位于同一个数组,在内存中是挨着的),2个cpu分别修改一个x,2个x在一方cpu都有缓存,修改了其中一个需要通知另外一个,每改一次通知一下,总之在修改的时候需要触发一种机制需要另外的cpu跟我保持一致,如果这样的话,耗时当然会比较长。当要访问一个数据的时候,干脆每一次缓存一小块的数据,这一小块数据里面包含了整个数组的数据,当访问数组中的任意元素数据的时候,就可以直接从缓存中读取到了,这一块的数据被称为缓存行。原创 2023-02-23 14:43:17 · 325 阅读 · 0 评论 -
证明CPU指令是乱序执行的
单线程的情况下,2个指令乱了顺序执行没有关系,反正最终的结果是一样的,但是在多线程的情况下,非常有可能出现你不想看到的情形,比如x=0、y=0的情况,比如在预知中没有这种情况,但是多线程的情况下,会出现,所以一定会影响整个多线程程序的运行,单线程的程序不会影响。这两种是乱序执行的排列组合,比如第一个场景是线程1先执行x=b、线程2执行y=a,切换到线程1执行a=1,切换到线程2执行b=1,结果是x=0、y=0。第一种组合先执行a=1、x=b,后执行b=1、y=a,得到的结果是x=0、y=1。原创 2023-02-23 14:43:11 · 752 阅读 · 0 评论 -
DCL单例模式是如何保证数据安全的?
第一个线程判断对象为空,在获取锁之前,切换给了第二个线程执行,第二个线程判断对象为空,获取锁,上完锁后,new对象,把锁释放,然后第二个线程结束,在这个时候第一个线程继续运行,因为第一个线程已经判断完了,直接申请上锁,此时是可以上锁成功的,因为第二个线程已经把锁释放了,线程1又new了一个对象。这样缩小了锁的粒度,不将业务代码的是否等于空的判断加锁,等判断为空之后,再上锁,上完锁,再new对象,这是追求效率的写法,但在多线程访问的情况下能不能保证数据的一致性?原创 2023-02-23 14:39:40 · 217 阅读 · 0 评论 -
JVM级别内存屏障如何禁止指令重排序的
为什么有一个空指令存在,因lock指令在锁总线的时候,这条指令后面必须跟一条指令,后面指令不能为空,所以后面得跟一条指令,但是后面跟的又不能有任何作用,如果有任何作用,中间改了别的值,也不对,所以设计了这么一个指令,往某个寄存器上加了个0,跟没有操作一样,主要为了迎合lock指令的参数要求即后面必须跟一个指令,其实只要有一个lock指令就足够了。java写的volatile,jvm编译执行,java是解释执行的,所以要想了解volatile怎么实现的,得去读hotspot解释器的代码,看是怎么解释完成的?原创 2023-02-23 14:37:08 · 896 阅读 · 2 评论 -
虚拟机指令集&栈与函数调用
指令集save&loadIMM全称load immidiatily立即加载数据到寄存器LEAload effective address加载地址LC/LI/SC/SIload char/load int:将char和int加载到寄存器save char/save int:将char和int从寄存器加载到内存PUSH将寄存器的数据推到栈顶stack peek举例ax是通用寄存器pc是代码区指针program counter指向当前正在执行的指令这些指令背原创 2022-03-13 20:03:13 · 3497 阅读 · 0 评论 -
C语言编译器概要设计思路一
700行代码自制C语言编译器一编译器1、编译器定义将高级别语言翻译成更底层的机器可执行的语言2、工业级编译器的编译过程编译过程分前端和后端两个阶段2-1 前端前端即parser:将源代码翻译成中间代码,以便给后端程序进一步处理parser过程分两个步骤词法分析即tokenize词法分析的目标是把人类语言简单处理一下告诉计算机这些词都是什么含义比如把int单词识别出来告诉计算机是整型;add识别出来告诉计算机是一个函数语法分析通过词法分析计算机已经知道每个词是什么意思通过语法分原创 2022-03-07 00:22:41 · 1447 阅读 · 0 评论 -
自动化运维环境搭建过程
本文介绍下"代码提交自动部署到云原生并实时查看服务的运行状态"运行环境的搭建过程k8s方式安装gitlab下载gitlab yaml文件git clone https://gitee.com/pingfanrenbiji/gitlab安装postgresql、redis、gitlab镜像下载docker pull sameersbn/postgresql:10docker pull sameersbn/redisdocker pull sameersbn/gitlab:11.8.1k8原创 2022-02-23 17:50:47 · 900 阅读 · 0 评论 -
逻辑回归简单理解
逻辑回归是用来解决二分类问题的什么是分类问题这是多种不同的动物以及它们不同的特征每种动物属于不同的种类有一条新的数据 知道它的特征 这些特征都属于特征列 预测这个是哪个种类的动物种类那列是属于目标列这种判断每条数据所属类别的问题属于分类问题二分类问题当分类问题的目标列只有两种情况时属于二分类问题比如把动物类别修改为是否为哺乳类回归和分类的区别不要被逻辑回归的回归二字所欺骗逻辑回归其实是解决的分类问题回归模型的输出是连续的分类模型的输出是离散的举例说明:左图:x轴表示每原创 2022-02-14 18:30:13 · 597 阅读 · 0 评论 -
快排序算法
承接上文归并排序及小和问题归并排序扩展-逆序对问题在一个数组中,左边的数如果比右边的数大,则两个数构成一个逆序对,找到逆序对的数量比如 3,2,4,5,0所有的逆序对是3,2; 3,0; 2,0; 4,0; 5,0上文的小和问题是 求右边有多少个数比左边的数大这个题目是求右边有多少个数比左边的数小所以逆序对的问题和小和问题是等效的归并排序为什么不会重算和漏算或归并排序的实质一个数组[a,b,c,d,e,f,g,h,i]就看数字c 看它经历什么样的心路历程一开始数组是这么被分的原创 2022-01-22 23:36:09 · 345 阅读 · 0 评论 -
归并排序及小和问题
归并排序mergeSort先让左侧部分排好序变成了1,2,3再让右侧部分排好序变成了2,5,6怎么样让它整体都有序呢merge在一起就行了准备一个辅助空间 谁小拷贝谁左侧下标指向1右侧下标指向2左侧如果小于等于右侧先拷贝左侧的如果右侧小于左侧则先拷贝右侧如图 1小拷贝1 指针往下动相等的时候 默认拷贝左边的 指针再往右动3>2 右侧小拷贝右边的 指针往右动3<5 拷贝3 指针越界 将剩下的拷贝过来小结左侧部分排好序右侧部分排好序利用merg原创 2022-01-22 14:15:17 · 577 阅读 · 0 评论 -
递归行为时间复杂度估算
承接上文递归算法递归行为时间复杂度估算master公式T(N)=a * T(N/b) + O(N^d)1、T(N)指母问题的数据量是N级别的母问题有N个数据 规模是N2、T(N/b) 子问题的规模都是N/b的规模就是说母问题的规模是N个数据但每一次的子过程规模是等量的都是N/b的规模3、a表示这个子问题被调了多少次4、O(N^d) 表示除了子问题之外剩下过程的时间复杂度这样一类问题的递归 可以用master公式来求解时间复杂度结合上文的递归算法来理解下master公式proce原创 2022-01-20 09:40:55 · 253 阅读 · 0 评论 -
递归算法求最大值
求数组中的最大值该函数的功能是 在L和R范围上返回最大值1、 L=R表示就一个数 最大值是它自己2、如果不止一个数 就求中点的位置一般的写法是 (L+R)/2但这些写有问题 如果数组长度很大 L+R可能会溢出溢出之后 结果可能为负值可以写成 L + (R-L)/2(R-L)/2 表示 L ~ R 之间距离的一半L 加上 一半的距离 也是 L ~ R 的中点这个结果是不溢出的 因为 L、R都不溢出,R>L,所以R-L也不溢出更简洁的写法L + ((R-L)>>1)原创 2022-01-20 08:27:37 · 3072 阅读 · 0 评论