- 博客(124)
- 收藏
- 关注
原创 【分布式锁解决超卖问题】setnx实现
假设还是上边的情况,线程1卡顿,锁自动释放,线程2进入到锁的内部执行逻辑,此时线程1反应过来,然后删除锁,但是线程1,一看当前这把锁不是属于自己,于是不进行删除锁逻辑,当线程2走到删除锁逻辑时,如果没有卡过自动释放锁的时间点,则判断当前这把锁是属于自己的,于是删除这把锁。方法,当有多个线程进入时,我们就利用该方法,第一个线程进入时,redis 中就有这个key 了,返回了1,如果结果是1,则表示他抢到了锁,那么他去执行业务,然后再删除锁,退出锁逻辑,没有抢到锁的线程,等待一定时间后重试即可。
2024-11-23 23:47:26
1128
3
原创 【Redis 缓存策略】更新、穿透、雪崩、击穿、布隆过滤
用户的数据一般都是存储于数据库,数据库的数据是落在磁盘上的,磁盘的读写速度非常慢。在高并发的情况下,需要对数据库进行庞大的 CRUD,很容易导致数据库崩溃。所以为了避免用户直接访问数据库,一般都会用 Redis 作为缓存层。Redis 是基于内存的,我们可以将数据库的数据缓存在 Redis 里,相当于数据缓存在内存,内存的读写速度比硬盘快好几个数量级。这样用户在访问数据的情况下,可以直接在缓存中获取,这样大大提高了程序的运行效率,也在一定程度上降低了数据库的访问压力。
2024-11-22 20:56:33
2096
12
原创 基于Redis实现的手机短信登入功能
(2)登入注册时创建用户,用户信息需要保存到 Redis 中,此时的 key 建议用一个随机的 token(建议不要用手机号码,因为之后这个 token 会传入前端,有泄露风险),value 存放用户信息。后,我们会将其存放在 Session 中,每一个不同的请求就会对应一个 Session,它们 SessionID 肯定是唯一的。当项目中存在多个拦截器,那么的执行顺序是根据方法而定的,拦截器所有的 preHandle 方法是按照拦截器的 order 升序执行的,如果 order。答案肯定是不需要的。
2024-11-19 23:31:58
1689
6
原创 【苍穹外卖】学习日志-day2
启用禁用员工账号需求分析代码开发启动员工账号,就是更改当前列的状态。我们可以复用修改员工信息的 Mapper 只更改前端传过来的状态即可。编辑员工信息需求分析我们的编辑员工的业务需求其实需要设计两个接口,在编辑员工之前需要按照 id 查找指定的编辑员工的信息。根据 id 查找员工设计代码开发编辑员工信息的代码开发ServiceMapper 与 启用禁用员工账号相同。
2024-11-17 17:22:33
771
原创 【苍穹外卖】学习日志-day1
为了增加安全性,有必要对数据库中需要保密的信息进行加密,MD5 算法可以很好地解决这个问题,因为它可以将任意长度的输入串经过计算得到固定长度的输出,而且只有在明文相同的情况下,才能等到相同的密文,并且这个算法是不可逆的,即便得到了加密以后的密文,也不可能通过解密算法反算出明文。
2024-11-15 22:35:26
1446
2
原创 【SpringBoot】黑马大事件笔记-day3
同时,需要指定一个实现了 Validator 接口的验证器类,用于验证该注解所标记的字段或参数是否符合自定义的校验规则。分页查询是在 web 开发中常用的一种技术,当某个页面查询返回的数据量较大时,为了提高性能和用户体验不能将所有数据一次性返回给过前端,这时候就需要用到分页查询了。在文件列表这里就可以查找自己的图片了,不过需要注意的是在OSS中我们是 url 的格式存储的,所以上传的文件名与 OSS 存储的文件名不一样也是应该的。元注解是专门用来注解其他注解的注解,简单来说就是专门为自定义注解提供的注解。
2024-11-11 22:25:33
963
原创 【SpringBoot】 黑马大事件笔记-day2
新增的时候只需获取 ThreadLocal 中的用户 id 进行有效的插入即可,Mapper 并不涉及 id 的操作,所以获取请求时不需要传入 id;所以 @NotEmpty 就相当于 groups= {Add.class,Update.class},而 @NotNull(groups = Update.class) 指定了校验项,所以只有更新的操作才进行校验。Validator 校验框架提供了分组校验,可以帮助我们快速的实现这样的需求。把校验项进行归类分组,在完成不同的功能的时候,校验指定组中的校验项。
2024-11-10 21:23:39
1498
4
原创 【Springboot】黑马大事件笔记 day1
使用 ThreadLocal 后 token 就存在 ThreadLocal 中,就不需要再去等待 token 的传递,可以做到随用随取。简单来说,就是在用户登录成功以后,为用户颁发一个token(令牌),用户便可以使用这个 token 令牌访问后台的接口。如果匹配就进入首页;于是在创建用户信息时,我们的 Service 层就可以通过这种方式将用户输入的密码,转化成难破译的校验码 (字符串) 添加到数据库中。它的特点是,每个线程都有该变量的一个副本,线程之间互不影响,实现了线程间的数据隔离。
2024-11-09 23:19:56
1378
1
原创 基于 SpringBoot 实现QQ邮箱验证码注册功能
找到并开通以下的邮件协议服务,而且服务开启也较为简单,需要我们发送一个短信到指定的号码,开启后平台会提供一个授权码,一定要记住这个授权码,发邮件的时候需要这个。host 是根据服务主机区分,网易邮箱是 smtp.163.com, qq邮箱是 smtp.qq.com。其中的 username 是你第一步中操作的邮箱账号,nickname 是接收者收到邮件中显示的发件人。发送邮件的核心依赖是 mail ,由于该项目还涉及其他依赖就全都导进来了。(1)首先打开QQ邮箱,点击设置并来到账号页面。
2024-11-06 20:20:40
1599
2
原创 【Java SpringIOC与ID随感录】 基于 XML 的 Bean 装配
也就是说,对象的创建和依赖关系的维护从程序员的手中转移到 BeanFactory 我们将这个现象称之为控制反转(IOC),在 BeanFactory 工厂中负责注入每一个依赖关系的这种行为称之为(ID)。我们发现结果为 true ,说明创建的是同一个对象,所以这种默认标签 singleton 创建的是单例的。我们的实体类的属性赋值,是 IOC 通过 property 中的 value 标签直接赋值给对象属性吗?他⽀持⼴泛的应⽤场 景,有着活跃⽽庞⼤的社区,这也是 Spring 能够⻓久不衰的原因。
2024-10-29 20:53:45
1179
2
原创 【Java Maven框架】
此时使用的就是 mysql8.0 的版本。依赖冲突问题最好在导入依赖的时候先想会发生什么冲突,如果等到发生了冲突再来排查,这样排查的时间成本会很高,因为一个项目导入的依赖是非常多的。例如:项目的依赖一多,假设某天需要修改一个依赖的版本号,我是不是还需要去那么多依赖中去找,这就显得很麻烦。我们之前添加依赖,都是直接添加坐标三要素即可,但是它还有一个隐藏的标签 - scope,决定这个依赖的依赖程度。这里举个例子,比如,你可能在编译的时候只需要 API、JAR,而只有在运行的时候才需要 JDBC 驱动实现。
2024-10-27 12:46:13
965
3
原创 【Java IO】控制程序启动 + 微信定时消息发送
首先我们可以写一个递归查找文件的代码,在找到该文件的前提下调用 Runtime 类 exec 方法便可实现启动程序的操作。文件与信息之间的传输都是以 IO 流作为媒介的,学习完 IO 流后,我们就可以用它来做一些有趣的小功能。微信定时消息发送需要三个属性,接收者、时间、内容,而下述操作是从当前目录下的 test.txt 中读取文件并转化成字符串的形式传入。那么想实现上述的功能其实很简单,我们只需要让鼠标移动到 “登入” 位置,再模拟点击两次即可。它的功能还不仅限于此,还能自动发送信息哦。
2024-10-23 20:34:17
962
6
原创 【Java 定时任务】小顶堆与时间轮算法介绍 + 多线程代码练习
但 HashedWheelTimer 是一个粗略的定时器实现,之所以称之为粗略的实现是因为该时间轮并没有严格的准时执行定时任务,而是在每隔一个时间间隔之后的时间节点执行,并执行当前时间节点之前到期的定时任务。不过具体的定时任务的时间执行精度可以通过调节 HashedWheelTimer 构造方法的时间间隔的大小来进行调节,在大多数网络应用的情况下,由于 IO 延迟的存在,并不会严格要求具体的时间执行精度,所以默认的 100ms 时间间隔可以满足大多数的情况,不需要再花精力去调节该时间精度。
2024-10-20 20:07:08
1490
4
原创 【Java 并发编程】线程池理解与使用
一般都是创建任务、创建线程、启动线程,任务结束后系统就会销毁线程,但是这种方式一个线程只能执行一个任务并不能复用。如果还有任务的话,还需要再创建一个线程去执行它。在数据量庞大的情况,就需要频繁创建与销毁线程,我们知道构造一个线程的开销是非常大的,这样的话就可能会导致系统崩溃。那么一个线程能不能复用呢?答案是可以的,线程池就提供了线程回收机制,可以重复利用已创建的线程降低线程创建和销毁造成的消耗。通过打印结果可以知道通过线程池,可以做到一个线程执行多个任务。所以线程池就是一个可以复用线程的技术。
2024-10-18 21:23:24
1112
5
原创 【Java 并发编程】阻塞队列与仿真餐厅
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。在传统的生产者与消费者模式下,假设存在多个生产者线程和消费者线程,它们共享一个有限容量的缓冲池(阻塞队列)。这些逻辑容易出错且不易维护。举个生产者与消费者栗子,假设没有阻塞队列,如果生产者与消费者两个线程之间需要通信协调,那么这两个线程的方法中必然有对方的 “影子”。
2024-10-17 22:57:26
1121
2
原创 【Java 并发编程】单例模式
(3) 关于上述代码,getInstance 是不需要参与锁竞争的所有线程都可直接进入,那么现在就开始第二步判断,如果实例对象没有创建,那么所有线程都会去争抢锁,抢到锁的那个线程会开始创建实例对象。以上代码我们可以发现这个对象并不会随着类加载而创建,而是在第一次访问单例类的实例时才去创建(第一次调用 getInstance 方法),我们将这种延迟创建的行为称之为 “懒汉”。那么可以把这个类设置为单例的,这样只需要创建一次对象并且重复使用这个对象就好了,而不用每次去访问数据库都要创建链接对象。
2024-10-15 20:21:36
1436
3
原创 【Java 线程通信】模拟ATM取钱(wait 和 notify机制)
在多线程里面要实现多个线程之间的通信,除了管道以外,只能通过共享变量的方式来实现,也就是说第一个线程修改了公共共享变量,别的线程获得修改后的变量的值,从而完成数据的一个通讯;但是多线程的本身是具有并行执行的一个特性,也就是说,在同一个时间,多个线程是可以同时执行的,那么这种情况下,其它现在在访问共享变量之前,必须要知道,第一个线程已经修改了这个共享变量,否则就需要等待,或者是拿到原始数据,基于此基础上运输,产生数据不一致的场景;wait() 方法用来线程间通信,如果设置了时间,就等待指定时间;
2024-10-14 13:14:36
1221
3
原创 【MySQL】数据库基础指令(一)
个人感觉 MySQL 没有太多的逻辑问题,只有对语句的熟练使用,会对数据进行增删查改操作即可。本章节的内容将会收集一些常用的 MySQL 的指令的使用。目录前言解决MySQL无法输入中文字符的问题数据库操作显示当前的数据库创建数据库删除数据库使用数据库数据表操作创建表显示当前的数据表查看表结构删除表表的新增单行数据 + 全列插入多行数据 + 指定列插入表的查询全列查询指定列查询查询字段为表达式为查询字段取别名去重查询排序查询排升序排降序条件查询分页查询解决MySQL无法输入中文字符的问题。
2024-10-13 19:53:17
1400
1
原创 【Java 并发编程】理解同步锁、可重入锁与死锁问题
根据程序的多次运行,发现结果总是随机且小于 100000 的数,原因是只要有锁就已经满足了进入同步方法或者同步代码块的资格,而不同的对象产生的锁也是不同的,以上 t1 线程拿到了 o1 对象的锁,t2 线程拿到了 o2 对象的锁,两个线程都可以自由的访问 run ,程序就又并发执行了。关于代码块的锁对象,其实只要是一个对象就行,可以是当前对象的 this,也可以是当前类的class, 也可以用 Object 或者 Object 的子类创建的对象都可以。,也就是说 t1 线程还是可以拿到锁的。
2024-10-12 09:28:40
1472
4
原创 【Java 并发编程】解决多线程中数据错乱问题
再假设现在 t2 线程现在被唤醒,并完美的执行三个步骤:由于 t1 线程并没有修改内存所以 t2 寄存器从内存中读取到的值仍然是 0,然后加 1 修改内存,此时内存的值为 1。试想一下,如果这两个操作不具备原子性,假设从 用户A 取走 100 元之后,操作突然终止了,那么 用户A 把钱取走了,但是银行账户的钱并没有减少。一个银行账户中有 1000 元,现在有 用户A、用户B分别从这个账户中取钱:那么必然包括两个操作:A向银行取钱,B向银行取钱,如果两次取钱都与银行存款相对应则证明银行的取钱操作是成功。
2024-10-09 22:24:33
1753
4
原创 【Java 并发编程】多线程安全问题(上)
虽然并发编程让我们的 CPU 核心能够得到充分的使用,程序运行效率更高效。但是也会引发一些问题。比如当进程中有多个并发线程进入一个重要数据的代码块时,在修改数据的过程中,很有可能引发线程安全问题,从而造成数据异常。i
2024-10-08 22:51:27
1196
2
原创 【Java 并发编程】初识多线程
到目前为止,我们学到的都是有关 “顺序” 编程的知识,即程序中所有事物在任意时刻都只能执行一个步骤。例如:在我们的 main 方法中,都是多个操作以 “从上至下” 的顺序调用方法以至结束的。虽然 “顺序” 编程能够解决相当大的一部分问题,但是当所有的方法全部推在一个 “队列” 里面,如果前面的方法没有执行完,后面的方法就轮不到。这样程序的运行效率必然十分低下。对于一些问题,能够同时执行程序的多个部分,就会十分方便且必要。而并发编程的设计就是为了专门解决这一类问题。
2024-10-06 23:12:30
953
2
原创 Java 之深入理解 String、StringBuilder、StringBuffer
String 类被 final 修饰,表明该类不能被继承;value 被 final 修饰,表明 value 自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改String 类 不能被继承:该类被 final 修饰String 类是不可变的:value[ ] 被 final 修饰,表明 value[ ] 自身的值不能改变String 类可以序列化,可以和其他 String 比较其大小:实现了 Comparable 接口。
2024-10-03 16:23:12
1473
4
原创 【初认 Java 哈希表】看这一篇就够了
数组是我们平时常见的并且经常使用的一种数据结构,那么它具有什么优点呢?我们都知道,在我们知道数组中某元素的下标值时,我们可以通过下标值的方式获取到数组中对应的元素,这种获取元素的速度是非常快的但是呢,数组也是有一定的缺点的,如果我们不知道某个元素的下标值,而只是知道该元素在数组中,这时我们想要获取该元素就只能对数组进行线性查找,即从头开始遍历,这样的效率是非常低的,时间复杂度为 O(N)链表中查找对应元素也是如此,需要从头开始遍历整个链表,时间复杂度为 O(N)
2024-09-29 19:52:51
988
3
原创 窥探 引用拷贝、浅拷贝、深拷贝 的那些事 (clone版)
对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。缺点也很明显,由于所指向的是同一个对象,所以任意一个变量操作了对象的属性,都会影响另一个变量。深拷贝是一种完全拷贝,无论是基本类型还是引用类型都会完完全全的拷贝一份,在内存中生成一个新的对象。修改其中的一个对象会影响到另一个对象。
2024-09-21 16:56:08
892
1
原创 Java内部类,看这一篇就够了!
在 Java 中,我们通常将不同的类组织到一个包下,对于一个包中的类来说,它们是同一个层次,可以说在没有使用继承等条件下,类与类之间是没有联系的。还有一种类,它是定义在另一个类或者一个方法的内部,这样的类叫做内部类。内部类也是封装的一种体现 ~注意:内部类和外部类共用同一个 java 源文件,但是经过编译之后,内部类会形成单独的字节码文件一般来说,内部类分为成员内部类、局部内部类、匿名内部类和静态内部类成员内部类。
2024-09-15 21:16:10
3261
4
原创 3分钟带你快速了解 Java 接口
即一个接口可以有多个父类接口,与类的继承相似,子类接口要扩展某个父类接口,将会获得父类接口中的所有抽象方法、常量属性、等等。在 Java 程序中,接口里的方法都是抽象的或者是公有的,在声明的时候可以省略掉关键字 public 和 abstract,因为它的方法都是编译器隐式加上的(与上文的接口中的变量一样)。程序中创建了接口后,接口的方法和抽象类是一样的,它的方法都是抽象的,也就是说接口不具备有实现的功能(不能被创建对象)它只是指定要做那些工作,而不管怎么去做。在我们现实生活中接口的例子十分的常见。
2024-09-13 19:47:53
870
1
原创 3分钟教你学会Java抽象类
比如说,Person 抽象类中定义了一个抽象方法 eat(),表明所有人都要吃东西,但需要对应子类去扩展实现,拿我之前多态的例子来讲就是:教师吃教师餐,学生吃学生餐。抽象类是从多个具体类中抽象出来的父类,它具有更高层次的意义:从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的目标,从而避免了子类设计的随意性。模式的设计,抽象类作为多个子类的通用模板,子类可以在抽象类的基础上进行扩展、改造,但是子类总体上会保留抽象类的行为方式。抽象类的子类必须实现抽象类定义的方法。
2024-09-12 21:35:31
903
1
原创 【Java 类与对象】多态
在这个过程当中,我们不应该在原来老的类上进行修改,因为原来的类,可能还在有用户使用,正确做法是:新建一个新手机的类,对来电显示这个方法重写就好了,这样就达到了我们当今的需求了。如果调用子类型对象的一个虚方法,编译器将无法找到真正需要调用的方法,因为它可能是定义在父类型中的方法,也可能是在子类型中被重写的方法,这种情形,只能在运行时进行解析,因为只有在运行时期,才能明确具体的对象到底是什么。这种方法比较符合实际的开发,因为一个大型项目都不是一个人写出来的:一般是由一些人写类,一些人再写调用类的功能。
2024-09-10 15:37:28
881
2
原创 【Java 类与对象】继承篇
在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分。这里稍微解释一下,我们创建对象先初始化父类,然后走 Derived 的构造方法,分别初始化了子类 Derived 、Base ,因为父类和子类的方法同名构成重载,所以我们要根据参数来判断是调子类方法还是父类方法 -- 无参的是子类 Derived ,有参的是父类 Base。时刻牢记, 我们写的类是现实事物的抽象。
2024-09-08 10:55:57
912
3
原创 【java 类与对象】静态成员与代码块
而我们之前之所以能够直接调用,是因为我们的方法需要依赖对象,有隐藏的 this 帮我们调用了。答:java 中,被 static 修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。:在 java 中,被 static 修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。定义在类中的代码块,使用 static 定义的代码块称为静态代码块,一般用于初始化静态成员变量。不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中。
2024-09-06 17:58:04
1109
原创 【Java 类与对象】语法篇(一)
定义了一个类,就相当于在计算机中定义了一种新的类型,与 int,double 类似,只不过 int和 double 是 java 语言自带的内置类型,而类是用户自定义了一个新的类型,比如以上介绍的 Student 类。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。一个是测试这个程序的启动类,我们一般使用一个类嵌套 main() 方法,它的作用就是创建你的新类的对象,然后使用点(.)运算符访问那些新对象的方法和变量。
2024-09-04 20:57:22
842
原创 【旋而又旋,旋妙之门】AVL 树的性质
我们插在 6 的左边,那么 6 的平衡因子减一,同理 7 的左子树高度加一,那么 7 的平衡因子减一,再继续向上 5 的右子树的最高高度并没有发生改变,所以 5 的平衡因子不发生改变。如果我们想要在 9 后面插入一个节点,那么 8 的平衡因子就会变为 2,此时的AVL树不平衡,根据平衡因子的绝对值必须小于等于二的原则,我们需要对树进行旋转。说明 parent 的平衡因子更新前是 1 / -1,插入节点插入在高的那边进一步加剧了 parent 所在的子树的不平衡,已经违反违规了,需要旋转处理。
2024-07-23 15:00:22
733
1
原创 数据结构-分析期末选择题考点(广义表)
广义表,又称列表,也是一种线性存储结构,既可以存储不可再分的元素,也可以存储广义表,记作:LS = (a1、a2、…、an),其中,LS 代表广义表的名称,an 表示广义表存储的数据,广义表中每个 ai 既可以代表单个元素,也可以代表另一个广义表。广义表表尾总是广义表,表头可能是也可能不是,例如广义表(a,b,c)表头为a不是,而广义表((a),b,c)表头为(a)是一个广义表。C = (a、(b、c、d)): 广义表 C 中有两个元素,原子 a 和子表 (b,c,d)
2024-06-30 11:29:31
1277
原创 数据结构-分析期末选择题考点(图)
在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(1)每个顶点出现且只出现一次(2)若A在序列中排在B的前面,则在图中不存在从B到A的路径此拓扑排序的思想是:(1)从有向图中选取一个没有前驱的顶点,并输出之(2)从有向图中删去此顶点以及所有以它为尾的弧以上便是。
2024-06-29 18:24:34
1164
1
原创 数据结构-分析期末选择题考点(串、数组)
承接上回,我们来复习串这一章的内容 ~说到,其实也不难,不过考点分布算是有点多。这里我们依旧是以题型进行分析:算法:一般考在哪个位置与匹配 (大概率)算法:给出一个串求其t 数组 (大概率) 串的以及(比如说特殊线性表,存储的数据元素是字符)给出一个求数量串的大概考点便是以上这些,我们再来聊一聊考数组的话,肯定是不会给你一维数组的,要考也是考二维,常以计算一个二维数组中的某个空间地址出题计算二维数组中的某个空间。
2024-06-28 21:41:44
1093
原创 数据结构-分析期末选择题考点(排序)
再找比基准大的元素,找到后交换。(2)归并排序是一种二分排序算法,每次都需要给 n 个元素排序,排序的过程需要 logn,即树的高度,所以时间复杂度为 nlogn。快速排序以基准值为中心,对元素进行划分,这里 28 为基准值,则小于 28 的和大于 28 的进行交换,完成一次划分。排序的思想是每次选出最值,放在已排序序列的末尾,如果最值有多个,而选出的为最后一个最值,会导致相对位置发生变化。这种题就考的是对所有排序的模拟了,需要你了解所有排序的实现原理,属于偏难的题目,小概率会出。题型大概就是初始化建堆。
2024-06-26 18:08:54
997
2
原创 C语言数据结构-分析期末选择题考点(一)
p 已经没有 q 的联系方式了,但是题目还想让我们用原来的联系方式找到 q ,p 的现任是 s 啊,p 的 next 存的是 s 的联系方式,所以 B 也不能选(不知道我这么说,老铁们听不听得懂,应该很好理解吧)简单复习一下应该没什么问题,其次便是结构了,我们的队列也有顺序队列、链式队列,链式队列没什么考点,而顺序队列还可以考进入。A选项为头插,不需要遍历链表,B选项为尾插,也不需要遍历链表,C选项为头删,不需要遍历链表,只有D选项,为尾删,需要遍历单链表,找到尾节点的前一个节点。
2024-06-25 11:25:23
1578
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人