栈和队列相关的

1.栈(Stack)

定义:栈是一种特殊的线性表,仅允许在固定的一端进行插入和删除操作,进行插入和删除操作的一段称为栈顶另一端称为栈底遵循先进后出原则

栈的底层:栈的底层是一个数组

我们通过idea去看stack这个类会发现它的无参构造函数是空的,但他继承了vector,vector类里面是数组

1.2栈的使用

方法                                             效果

stack()                                     构造一个空的栈

push()                                       往栈里存数据

pop()                                         弹出栈顶数据(也就是删数据)

peek()                                         获取栈顶元素但不删除栈顶元素

empty()                                       判断栈是否为空

 size()                                           获取栈里面数据的个数

1.3栈的模拟实现

说明:栈的底层是一个数组,所有我们先定义一个elem数组,定义一个usedSize记录当前栈里有几个数据。

1.往栈里放数据

说明:首先我们得先判断栈有没有满,然后去放。我们通过画图可以知道,usedSize的值就是你下一个要放数据的位置。

2.弹出数据和观察数据(这里俩个方法放一起来看一下俩个的区别)

说明:首先判断是不是空,如果不是就进行下面的弹出或者观察。这里重点看一下弹出这个--usedSize,是如何删的。假如我们栈里已经有3个数据了,那么usedSize等于3,--usedSize为2,会在2下标覆盖一个值。  而usedSize-1,就是2下标的元素返回.

3.利用递归将链表倒着day

说明:递归得去找终止条件,当head.next ==null的时候你就去打印当前val,当不等于null的时候就调用它本身,往后走。当等于了null的时候就会打印,然后归着往前打印。

4.利用栈去逆着打印链表

说明:我们要把链表里的节点去存在栈里,这个栈的类型就是 ListNode的, 循环链表往栈里面放,放完后,当栈里不为空的时候,循环着把栈数据一个一个弹出并打印。

5.逆波兰表达式求值

说明:逆波兰表达式又称为后续表达式,是由中序表达式经过计算得到的(这个计算是从左到右,先乘除加括号,后加减加括号,然后把括号里的符号提到包它括号的外边)

此题思路:当我们那到逆波兰表达式的时候,我们先对存它的数组进行遍历,同时判断它是整数还是符号,是整数的话,我们就把它放到栈里不是的话,我们得把栈里的数据弹出,先弹出的放符号右边,后弹出的放符号左边,进行相关计算,再把计算得到的值放入栈里,最后数组遍历完成后,栈弹出的数据,就是逆波兰表达式计算后的结果。

6.括号匹配

说明:先把存放括号的字符串遍历出来,拿出来就是字符型,先把左括号全部放到栈里面,然后去判断,当不是左括号的话,我们需要当下栈是空吗,如果是,就是括号)(的情况,说明不匹配,如果不为空,我们peek一下栈顶元素,看看当前这个括号和它匹配嘛,如果匹配就把栈的这个括号弹出,字符串继续往后遍历。当遍历完字符串的时候,去判断栈是不是空,是空就是匹配的了,不是就是不匹配的。

7.出栈入栈次序匹配 给定俩个序列比如12345,去判断45321,是不是12345的出栈序列

说明:思路俩个序列分别拿数组存,首先我们去遍历我们的第一个序列,把数据存入栈中,当栈中的数据和第二个序列相同的时候(同时栈不为空且第二个栈还没遍历完),我们就需要把栈里的元素弹出,第二个序列往后遍历。当遍历完的时候,如果栈为空,那么我们第二个序列就是第一个序列的出栈顺序。

8.利用栈求一组数据的最小值(比如1,-1,-2,3)

思路:我们定义俩个栈一个普通栈,一个最小栈,当我们第一次放数据的时候(如果普通栈为空),我们俩个栈都放数据第二次放的时候就需要拿放的元素和最小栈栈顶元素比较,如果放的元素小于等于最小栈的栈顶元素,那么俩边都放,否则就放到普通栈顶

出栈操作,当俩栈顶元素相同时,就都出栈,不同时,只出普通栈栈顶元素

最小栈栈顶元素就是这组数据的最小值

9.栈,虚拟机栈,栈帧概念区分?

栈是数据结构

虚拟机栈是一块内存

栈帧是方法调用时在虚拟机栈上开辟的内存

2.队列

2.1队列先进先出

队尾进,队头出

队头

|        |

|        |

|        |

|        |

队尾

链表可以实现栈

双向链表,不管是从尾巴进头出,还是从头进尾巴出,时间复杂度都O(1)

单向链表,如果记录了last,从尾巴进入的时候时间复杂度为O(1),从尾巴出的时候时间复杂度为O(n)

单向链表,如果从头进,时间复杂度O(1),出的时候时间复杂度O(1);

链表可以实现队列

双向链表,不管是头进还是尾进时间复杂度都是O(1)

单向链表,如果记录了尾巴,从尾巴进,从头出队,时间复杂度是O(1)

单向链表,如果记录了尾巴,从头进队,从尾出队,因为你得知道最后一个节点的前一个节点,所有你出的时候,时间复杂度为O(n)

2.2队列的使用

在java中,Queue是一个接口,底层通过链表实现

相关方法:

注意Queue是一个接口,在实例化时候必须实例化LinkedList对象,因为LinkedList实现了Queue接口。

注意:它也有add方法,add方法与offer区别是,add会报异常,offer不会,比如说满的了话add会报异常,offer不会。

2.3队列的模拟实现

下面是对这个单链表模拟的队列方法的实现

注意:因为我们是拿链表模拟实现的队列,对列先先出,同时我们复杂度得O(1),所有我们入队都是从尾巴入,也就是尾插

1.往队列里添加数据

2.获取当前队列有多少元素

3.出队列

4.peek队列元素

2.4循环队列

这个东西简单来说就是数组首尾相连

下面是一个图来方便理解:

我们定义一个front,一个rear 去指向这个循环数组的0下标

rear代表我们要放入元素位置的下标

因为一开始rear和front都在0开始放元素和出元素(先进先出),等到最后转回来,这个数组又为空了,一开始为空最后还为空,所有我们就有俩个方式代表它满:

1.当rear == 数组.length-1

2.留一个为满法(这里我们写这种的)

我们要假设一下,当我们rear到了6下标还有要放的就有可能从7下标到0下标过0了

所有rear+1去让rear走肯定不行,这里我们就要观察发现(rear+1)%数组.length可以实现

2.41设计循环队列

 3.双端队列

简单来说就是,你入队列出队列,俩边都可以

双端队列是Deque

在实际工程中,使用Deque接口是比较多的,栈和队列均可以使用

Deque<Interger> stack = new ArrayDeque<>;双端队列的线性实现

Deque<Interger> stack = new LinkedList<>;双端队列的链式实现

4.面试题

1.用队列实现栈

说明:思路就是利用俩个队列去实现,外面栈的功能。具体细节思路在代码中有标识 .

                                                                                                      ---------------- 努力想找工作的茶茶

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值