目录
题目完成进度
1/3
栈是一种“先进后出”的线性数据结构。栈只有一端能够进出元素,我们一般称之为栈顶,另一端为栈底。添加或删除栈中元素时,我们只能将其插入到栈顶(进栈),或者把栈顶元素从栈中取出(出栈)。
先来两道例题——
CH128 Editor
CH130 火车进出栈问题
表达式计算
栈的一大用处是做算数表达式的计算,算数表达式通常有前缀、中缀、后缀三种表示方法。
1.中缀表达式:就是最常见的表达式,如:$3*(2-1)$
2.前缀表达式:又称波兰式,形如“$op\ A\ B$”,其中“op”是一个运算符,如:$*\ 3\ -\ 2\ 1$
3.后缀表达式:又称逆波兰式,形如“$A\ B\ op$”,如:$2\ 1\ -\ 3\ *$
前缀和后缀表达式的值的定义是,先递归求出$A,B$的值,二者再做$op$运算的结果。这两种表达式不需要括号,其运算方式是唯一确定的。对于计算机来说,最容易计算的是后缀表达式,可以使用栈$O(N)$求值。
接下来详细说一下三种表达式在计算机中的求值方法:
首先是最容易求值的后缀表达式
后缀表达式求值
1.建立一个用于存数的栈,逐个扫描该后缀表达式中的元素。
(1)如果遇到一个数,则把这个数入栈
(2)如果遇到运算符,就取出栈顶的两个数进行计算,把结果入栈
2.扫描完成后,栈中恰好剩下一个数,就是该后缀表达式的结果。
如果要用计算机计算中缀表达式的结果,最快的办法是把中缀表达式转化成后缀表达式,再使用上述方法求值,这个转化过程同样可以使用栈来$O(N)$地完成。
中缀表达式转后缀表达式
1.建立一个用于存运算符的栈,逐个扫描该中缀表达式中的元素。
(1)如果遇到一个数,输出该数
(2)如果遇到左括号,把左括号入栈
(3)如果遇到右括号,不断取出栈顶并输出,直到栈顶为左括号,然后把左括号出栈
(4)如果遇到运算符,只要栈顶符号的优先级不低于新符号,就不断取出栈顶并输出,最后把新符号进栈
2.依次取出并输出栈中的所有剩余符号,最终输出的一个序列就是一个与原中缀表达式等价的后缀表达式。
当然,我们也可以不转化成后缀表达式,而是使用递归法直接求解中缀表达式的值,时间复杂度为$O(N)$。
中缀表达式的递归法求值
目标:求解中缀表达式$S[1~N]$的值。
子问题:求解中缀表达式$S$的子区间表达式$S[L~R]$的值。
1.在$L~R$中考虑没有被任何括号包含的运算符:
(1)若存在加减号,选其中最后一个,分成左右两半递归,结果相加减,返回
(2)若存在乘除号,选其中最后一个,分成左右两半递归,结果相乘除,返回
2.若不存在没有被任何括号包含的运算符:
(1)若首尾字符是括号,递归求解$S[L+1~R-1]$,把结果返回
(2)否则,说明区间$S[L~R]$是一个数,直接返回数值
单调栈
之前单独写过专题笔记,直接走链接吧,搬运一下例题——
poj2559 Largest Rectangle in a Histogram
借助单调性处理问题的思想在于及时排除不可能的选项,保持策略集合的高度有效性和秩序性,从而为我们作出决策提供更多的条件和可能方法。
队列是一种“先进先出”的线性数据结构。一般来讲,元素从右端进入队列(入队),从左端离开队列(出队)。于是我们称队列的左端为队头,右端为队尾。
元素进行多次入队、出队后,用于实现队列结构的数组的开头空间部分就会被严重浪费,所以我们经常将其优化为“循环队列”,也就是把队列看作一个首尾相接的环,只要队列中的元素个数在任意时刻都不超过环长,那么随着入队和出队操作的