第四章 栈与队列《大话数据结构》读后笔记
栈的定义
结构类似于手枪弹夹结构,后进去的却要先出来,后进先出的数据结构-栈。
浏览器的后退按钮就是访问历史记录的最近一条。
栈是限定仅在表尾进行插入和删除操作的线性表。
栈的插入叫作进栈也称入栈,压栈。类似子弹入弹夹。
栈的删除操作,叫出栈 累死弹夹中子弹的出夹(击发)
栈的顺序存储结构-顺序栈
线性表:数组结构实现。
两栈共享空间
让一个栈底为数组的始端,即下标0处。让另一个栈为栈的末端即下标为数组长度n-1处
如图所示, 两个栈分别用一个数组的头尾 向中间延伸。
这种数据结构,通常都是当两个栈空间需求有相反关系时。也就是一个栈增长时另一个栈在缩短的情况。如买股票一样,你买入一定有人卖出。
栈的链式存储-链栈
时间性能
- 链栈的进出栈只需要改变栈顶的指针位置即可。所以时间复杂度为O(1)。
- 顺序栈时间复杂度也为O(1)
空间性能
- 顺序栈需要事先确定一个固定长度,可能存在空间浪费
- 链栈长度无限制,不过需要每个元素都有一个指针域,也会增加内存开销
对比: - 如果使用过程中的元素变化很大,不可预料。那链栈会更好。
- 如果变化很小,可预期。使用顺序栈更好。
栈的应用-递归
递归的执行分为前行和退回阶段,递归的退回过程中,可能要执行某些操作,包括回复在前行过程中存储起来的某些数据。
在前行阶段每一层递归,函数的局部变量,参数值以及返回地址都被压入栈中。在退回阶段位于栈顶的局部变量、参数值、返回地址会被弹出。
栈的应用-四则运算表达式求值
四则运算:先乘除后加减从左到右,先括号内,后括号外。
栈应用-括号的处理:括号成对出现,有左一定有右,遇到左括号入栈,遇到右括号,就让栈顶的左括号出栈,期间让数字运算。
栈应用-先乘除后加减:表达式 “ 9 + (3 - 1) * 3 + 10/2”转后缀表达式"9 3 1 - 3* + 10 2/ +"
后缀表达式计算规则:
1.初始化一个空栈。此栈用来对要运算的数字进出使用。
2.后缀表达式中前三个都是数字,所以9、3、1进栈 如图:
3。接下来是“-”运算,将栈中1出栈作为减数,3出栈左右被减数,并运算3-1得到2,再将2进栈。
4。接着将表达式后面的数字3进栈
5。后面是“”,也就意味着3和2出栈。2与3香乘,得到6,并将6进栈。
6.下面是“+”,以此类推,栈中6和9出, 9和6相加,得到15,再将15 进栈
7。然后将10 2 进栈,接下来符号是/ ,因此栈顶2与10出栈,10与2相除得到5,将5 进栈
8,然后最后一个符号是+ 15加5 得20,把20入栈,然后没有符号了,然后出栈。最后结果20
表达式转为后缀表达式:
例:表达式 “ 9 + (3 - 1) * 3 + 10/2” -> "9 3 1 - 3 + 10 2/ +"
规则:从左到右便利每个数字和符号,若是 数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号优先级,是右括号或者优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
1.初始化栈,并依次遍历,遇到符号就进栈
2.当遇到符号为“)”,此时我们需要匹配此前的“(” ,所以栈顶依次出栈并输出,知道“(”出栈为止。此时为表达式:9 3 1 -
3.接着是数字3,输出,然后是 “” 因为此时栈顶为 +优先级“”因此不输出,* 进栈。此时:9 3 1 - 3
4.接下来是+ 此时栈顶元素 “*” 比 + 优先级高,饮食出栈,并输出
此时 9 3 1 - 3 * +
5.接下来是数字10 此时:9 3 1 - 3 * + 10 后面是符号除/ 所以 / 进栈。接下来输出2,此时:9 3 1 - 3 * + 10 2 最后将栈中全部出栈 此时:9 3 1 - 3 * + 10 2 / +
队列的定义
队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表
队列是先进先出 允许插入的一端为队尾,删除的一端为队头。