一、概念
栈: 是限定在表尾进行插入和删除操作的线性表。
注意:
- 首先栈是个线性表,栈元素具有线性关系,即前驱后继关系。
- 始终只能在表尾即是栈顶进行插入和删除操作,而不是栈底。栈底是固定的,最先进栈的只能在栈底。
进栈出栈的变化形式:
- 栈对线性表的插入和删除的位置进行了限定,但没有对元素进出的时间进行限制。
- 在不是所有元素都进栈的情况下,事先进去的元素也可以出站,只要保证是栈顶元素出栈就行。
如有1,2,3个数字依次进栈:
1进2进3进,3出2出1出
1进1出,2进2出,3进3出
1进2进,2出1出,3进3出等工5中变化方式。
因此,如果元素数量多,出栈的变化将会有很多种。
二、栈的抽象数据类型
三、栈的顺序存储结构及实现
- 用数组下标为0的一端作为栈底,首元素在栈底,变化最小。
- 定义top变量来指示栈顶元素在数组中的位置,必须小于StackSize。
- 当栈存在一个元素时,top=0。因此通常把空栈的判定条件定位top=-1。
1、进栈:栈顶指针加1,将新插入元素复制给栈顶空间
2、出栈:栈顶指针减1,将要删除的栈顶元素赋值给e
3、两栈共享空间
引入:
- push操作:首先判断是否已经栈满,再判断是栈1还是栈2,分别进行进栈操作即可。
- pop操作:只判断是栈1还是栈2,分别再判断是否为空,再进行弹栈操作。
总结:针对相同数据类型的栈的一个设计上的技巧,同数据类型是前提。
四、栈的链式存储结构及其实现
- 栈的链式存储结构,简称为链栈。
- 因为栈是在栈顶来做插入和删除操作的,所以链栈的栈顶放在单链表的头部比较方便。
- 另外已经有了栈顶在头部了,单链表中比较常用的头结点(包括头指针)也就失去了意义,通常对于链栈来说,是不需要头结点的,栈顶直接指向第一个元素。
- 对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间。
- 空栈,链表原定义是头指针指向空,那么链栈的空其实就是top=NULL。
1、进栈操作:
- 把当前的栈顶元素赋值给新结点的直接后继。
- 将新的结点s赋值给栈顶指针。
2、出栈操作:
3、将栈顶结点赋值给p。
4、使得栈顶指针下移一位,指向后一结点。
顺序栈和链栈的区别及应用场景
1、顺序栈和链栈的时间复杂度是一样的,均为O(1)。
2、空间性能:顺序栈需要事先确定一个固定的长度,存在村内空间浪给,但是存取是定位很方便。而链栈则要求每个 元素都有指针域,增加了内存开销,但是对于栈的长度无限制。
3、如果栈的使用过程中元素变化不可预料,最好用链栈,繁殖,如果元素变化在可控范围内则用顺序栈会好一点。(跟数组和 的区别是一样的)
五、栈的作用
1、递归----斐波那契数列
1)循环迭代实现
2)递归函数实现
分析:
递归定义:把一个直接调用给自己或通过一系列的条用语句间接地调用自己的函数,称作递归函数。
递归和栈的关系:
2、四则运算表达式求值
不需要括号的后缀表达式,也称为逆波兰表示。
后缀表达式:所有运算符号都是在运算数字的后面出现。
中缀表达式:所有的运算符号都在两个数字中间,也就是平常见的表达式