栈和队列

1.栈

2.栈的典型应用场合

1)逆序输出:输出次序与处理过程颠倒,递归深度和输出长度不易预知

2)递归嵌套:具有自相似性的问题可递归描述,但分支位置和嵌套深度不固定

3)延迟缓冲:

4)栈式计算:RPN,基于栈结构的特定计算模式

3.进制转换

4.括号匹配

思路:消去一对紧邻的左右括号,不影响全局的匹配判断

问题在于如号找到这对括号?如何使问题的这种简化得以持续进行?

顺序扫描表达式,用栈记录已扫描的部分

反复迭代:凡遇"(",则进栈;凡遇")",则出栈,若最后一个)处理完后,整个栈变空,原来的表达式为匹配的

使用栈结构
import
java.util.Stack; public class StackDemo{ public static void main(String [] args){ String str="(1+2+((22+2)*98)+(32-2))*22"; StringBuilder sb=new StringBuilder(str); Stack<Character> stack=new Stack<Character>(); int len=sb.length(); for(int i=0;i<len;i++){ char c=sb.charAt(i); if(c!='('&&c!=')') continue; if(c=='('){ stack.push(c); }else if(c==')'&&!stack.empty()){ stack.pop(); }else{ System.out.println("not match"); } } System.out.println(stack.empty()); } }

使用计数器进行判定是否匹配
以0开始,以0结束

采用栈结构,可以便捷地推广至多种括号并存的情况。

5.栈混洗

A---->S---->B

栈混洗计数

catalan(n)=(2n)!/(n+1)!n!

任意三个元素能否按某相对次序出现于混洗中,与其他元素无关

甄别栈混洗:

对于任何1<=i<j<k<=n,[...,k,...,i,...,j...]必非栈混洗

一个排列如果不包含上述序列,则一定是栈混洗

O(n)算法,直接借助栈A,B和S,模拟混洗过程,每次S.pop()之前,检测S是否已空;或需弹出的元素在S中,却非顶元素

每一栈混洗,都对应于栈S的n次push与n次pop操作构成的序列

  (        (         (         )          )         (          )       )
push(1)   push(2)     push(3)    pop(3)      pop(2)    push(4)     pop(4)   pop(1)

6.中缀表达式求值

计算次序未必与扫描的次序一致,将所有扫描过的部分保存到栈中

求值算法=栈+线性扫描

使用两个栈,分别存放运算符和数字

当数字栈中遇到连续数字时,应将当前数字栈顶的数乘以10加上当前数字再入栈。

“(”后遇到运算符时,大部分都执行运算符入账操作,“)”后遇到运算符时,大部分都执行运算符出栈操作。

7.逆波兰表达式,RPN

在由运算符和操作数组成的表达式中不使用括号,即可表示带优先级的运算关系

0 ! 1+ 2 3 ! 4 - 5 ^ - 67 * - 8 - 9 +

只需一个栈即可,每遇到一个数字则入栈,每遇到一个操作符则执行计算

8.中缀表达式到RPN表达式的转换

(0!+1)^(2*3!+4-5)

{([0!]+1)^([(2*[3!])+4]-5)}

{([ 0 ] ! 1 ) + ( [ ( 2 [3]! ) *  4 ] + 5) - }^

0 ! 1 + 2 3 ! * 4 + 5 - ^
变换之后,数字的相对次序并没有改变

转换算法:

若读取的为数字则直接入RPN栈,如果读取的为运算符,只有当运算符栈顶的元素优先级高于该运算符时,将栈顶的运算符出栈,压入RPN栈

原文地址:https://www.cnblogs.com/lvjygogo/p/8534685.html