栈是限定仅在表尾进行插入和删除操作的线性表。
队列是只允许在一端进行插入操作、而在另一端进行删除操作的线性表。
先进后出 栈
我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的
栈称为空栈。
栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。
栈的插入:进栈,压栈
栈的删除:弹栈
对于顺序栈,栈底是表头,栈顶是表尾
对于链栈, 栈底是表尾,栈顶是表头。没有头结点
4.4栈的顺序存储结构
一开始要定义好数组大小
top=-1 空栈
4.5两栈共享空间
stackoverflow
判断是否满栈:top1+1==top2
4.6栈的链式存储结构 —链栈
不需要提前定义大小,原则上栈可以一直增长
不需要头结点
顺序栈和链栈
时间复杂度都是一样的,都是O(1)
空间复杂度,O(1)
顺序栈需要事先确定一个固定长度,可能会浪费空间;但是存取定位很方便
链栈,栈的长度无限制
栈的应用-递归
斐波那契数列
迭代和递归的区别是:迭代使用的是循环结构(while for),递归使用的是选择结构(if)。
递归能使程序的结构更清晰、更简洁、更容易让人理解,从而减少读懂代码的时间。
但是大量的递归调用会建立函数的副本,会耗费大量的时间和内存。
迭代则不需要反复调用函数和占用额外的内存。
因此我们应该视不同情况选择不同的代码实现方式。
有时候使用递归虽然很简洁,但是时间效率有可能很差。
对于这种题目,我们可以用递归来分析问题,
但是写代码的时候,用数组来保存中间结果,基于循环实现。
绝大部分动态规划题目,都是按照这两步做的
编译器使用栈来实现递归
栈的应用:四则运算求值
四则运算表达式求值:后缀表示法(逆波兰表示法)。
中缀表达式转为后缀表达式:
要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:
1.将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
2.将后缀表达式进行运算得出结果(栈用来进出运算的数字)。
队列Queue
只允许在一端进行插入操作,而在另一端进行删除操作的线性表
FIFO 先进先出
4.12队列的顺序存储结构
队列顺序结构的不足:假溢出
解决:循环队列
front 指向队头元素
rear 指向队尾元素的下一个位置
循环队列满的条件是
(rear+1)%QueueSize == front
通用的计算循环队列长度公式为
(rear-front+QueueSize)%QueueSize
链队列一定有头结点
空队列,front和rear都指向头结点
总的来说,在可以确定队列长度最大值的情况下,建议用循环队列,如果你无法预估队列的长度时,则用链队列。
栈和队列,都是特殊的线性表,只不过对插入和删除做了限制