基础计算机器的实现(栈的应用)
基础计算器的实现(栈的应用) :
中缀表达式 转变成 后缀表达式(逆波兰表达式):
中缀表达式:不适合使用程序进行计算;
特别要注意的是:整个过程序需要两个栈,第一个栈是 运算符栈, 第二个栈是 存储中间结果的栈;
流程
1.初始化两个栈:运算符栈s1和储存中间结果的栈s2;
2.从左至右扫描中缀表达式;
3.遇到操作数时,将其压s2;(没有任何异议)
4.遇到运算符时,比较其与s1栈顶运算符的优先级:
- 如果s1为空,或栈顶运算符为左括号“(”,则将此运算符直接入栈;
- 否则,若当前运算符优先级比栈顶运算符的高,也将运算符压入s1(疑问点: 注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
- 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;
5.遇到括号时:
- 如果是左括号“(”,则直接压入s1;
- 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃;
6.重复步骤2至5,直到表达式的最右边;
7.将s1中剩余的运算符依次弹出并压入s2;
8.依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)
例如,将中缀表达式“1+((2+3)×4)-5”转换为后缀表达式的过程如下:
因此结果为:1 2 3 + 4 × + 5 -
62f6091_b.jpg)

来源:知乎
1+((2+3)×4)-5 转换为逆波兰表达式过程解释说明:
流程解释:
遇到 1 将操作数放置到 中间结果栈中 ;
运算符栈:S1=>[] , 中间结果栈:backExp=>[1]
遇到 + 将运算符放置到 运算符栈中。
运算符栈:S1=>[ + ] , 中间结果栈:backExp=>[ 1 ]
遇到 ( 将( 直接放入运算符栈。
运算符栈:S1=>[ + ( ] , 中间结果栈:backExp=>[ 1 ]
遇到 ( 将( 直接放入运算符栈。
运算符栈:S1=>[ + ( ( ] , 中间结果栈:backExp=>[ 1 ]
遇到 2 将2直接放入中间结果栈。 =>(因为运算符栈顶是“左括号”)
运算符栈:S1=>[ + ( ( ] , 中间结果栈:backExp=>[ 1 2 ]
遇到 + 将+直接放入运算符栈。 =>(因为运算符栈顶是“左括号”)
运算符栈:S1=>[ + ( ( +] , 中间结果栈:backExp=>[ 1 2 ]
遇到 3 将3直接放入中间结果栈。
运算符栈:S1=>[ + ( ( +] , 中间结果栈:backExp=>[ 1 2 3 ]
遇到 ) , 依次弹出 栈中元素 并加入 中间结果栈中, 并且删除 ()
运算符栈:S1=>[ + ( ] , 中间结果栈:backExp=>[ 1 2 3 +]
遇到 * , 栈顶为左括号,直接入栈
运算符栈:S1=>[ + ( * ] , 中间结果栈:backExp=>[ 1 2 3 +]
遇到 4 , 操作数直接入中间结果栈
运算符栈:S1=>[ + ( * ] , 中间结果栈:backExp=>[ 1 2 3 + 4 ]
到 ) , 依次弹出 栈中元素 并加入 中间结果栈中, 并且删除 ()
运算符栈:S1=>[ + ] , 中间结果栈:backExp=>[ 1 2 3 + 4 * ]
到 - , 依次弹出 优先级比 减号不低的 运算符 ,然后入栈;
运算符栈:S1=>[ - ] , 中间结果栈:backExp=>[ 1 2 3 + 4 * +]
最后,将运算符栈中的元素,依次弹出到中间结果栈;中间结果栈依次弹出,其逆序就是逆波兰表达式(后缀表达式)
运算符栈:S1=>[] , 中间结果栈:backExp=>[ 1 2 3 + 4 * + - ]
逆波兰表达式源码实现(不支持括号):
public class Solution{
public int calculate(String exp) {
return calResult(backTempExp(exp));
}
// 计算后缀表达式
public LinkedList<String> backTempExp(String exp) {
Stack<String> s1 = new Stack<String> ();
LinkedList backExpr = new LinkedList();
for(int i = 0; i < exp.length(); i++ ) {
if(Character.isDigit(exp.charAt(i))) {
int k = i+1;
while(k < exp.length() && Character.isDigit(exp.charAt(k)))
k++;
backExpr.addLast(exp.substring(i,k)); // 注意这个api 是前开后闭的区间
//ystem.out.println(exp.substring(i,k));
i = k-1;//需要回退一格
continue;
}
if(exp.charAt(i) == '+' || exp.charAt(i)=='-') {
while(!s1.isEmpty()) {
backExpr.addLast(s1.pop());
}
s1.push(""+exp.charAt(i));
continue;
}
if(exp.charAt(i) =='*'||exp.charAt(i)=='/' ) {
// if(!s1.isEmpty())
// System.out.println("s1.peek():"+ s1.peek());
while(!s1.isEmpty() && (s1.peek().equals("*") || s1.peek().equals("/")) ) {
//System.out.println("s1.peek():"+ s1.peek());
backExpr.addLast(s1.pop());
}
//System.out.println(""+exp.charAt(i));
s1.push(""+exp.charAt(i));
}
}
while(!s1.isEmpty()) {
backExpr.addLast(s1.pop());
}
return backExpr;
}
int calResult(LinkedList<String> backExpr) {
// for(String s : backExpr)
// System.out.println(s);
Stack<Integer> stk = new Stack<Integer> ();
for(String s : backExpr) {
if(Character.isDigit(s.charAt(0))){
stk.push(Integer.valueOf(s));
continue;
}
int num1 = stk.pop();
int num2 = stk.pop();
switch (s) {
case "+":stk.push(num1 + num2); break;
case "-":stk.push(num2 - num1); break;
case "*":stk.push(num2 * num1); break;
case "/":stk.push(num2 / num1);
}
}
return stk.peek();
}
}
支持括号支持逆波兰表达式
特别注意:在运算符栈中呢,先出栈相当于是先访问
import java.util.LinkedList;
import java.util.Stack;
public class Leetcode227 {
public static void main(String[] args) {
Solution s= new Solution();
String newStr = " 3+5 / 2 "; //"1+((2+3)*4)-5";
int k = s.calculate(newStr);
System.out.println(newStr + "=" + k);
}
}
class Solution{
public int calculate(String exp) {
return calResult(backTempExp(exp));
}
// 计算后缀表达式
public LinkedList<String> backTempExp(String exp) {
Stack<String> s1 = new Stack<String> ();
LinkedList<String> backExpr = new LinkedList<String> ();
for(int i = 0; i < exp.length(); i++ ) {
if(Character.isDigit(exp.charAt(i))) {
int k = i+1;
while(k < exp.length() && Character.isDigit(exp.charAt(k)))
k++;
backExpr.addLast(exp.substring(i,k)); // 注意这个api 是前开后闭的区间
i = k-1;//需要回退一格
}
else if(exp.charAt(i) == '+' || exp.charAt(i)=='-' || exp.charAt(i) =='*'||exp.charAt(i)=='/' ) {
while(!s1.empty() && !s1.peek().equals("(") && !compareOperator(exp.charAt(i), s1.peek().charAt(0))) {
backExpr.addLast(s1.pop());
}
s1.push(String.valueOf(exp.charAt(i)));
}
else if(exp.charAt(i) == '(' || exp.charAt(i)==')' ) {
if(exp.charAt(i) == '(')
s1.push(String.valueOf(exp.charAt(i)));
else{
String op = s1.pop();
while(!op.equals("(")){
//System.out.println(op);
backExpr.addLast(op);
op = s1.pop();
}
}
}
//System.out.println(exp.charAt(i));
}
while(!s1.isEmpty()) {
backExpr.addLast(s1.pop());
}
return backExpr;
}
boolean compareOperator(Character a , Character b) {
int p1 = 0 , p2= 0;
if(a == '*' || a =='/')
p1 = 1;
if(b == '*' || b =='/')
p2 = 1;
return p1 > p2;
}
//从逆波兰表达式中计算结果:
int calResult(LinkedList<String> backExpr) {
// for(String s : backExpr)
// System.out.println(s);
Stack<Integer> stk = new Stack<Integer> ();
for(String s : backExpr) {
if(Character.isDigit(s.charAt(0))){
stk.push(Integer.valueOf(s));
}
else {
int num1 = stk.pop();
int num2 = stk.pop();
switch (s) {
case "+":
stk.push(num1 + num2);
break;
case "-":
stk.push(num2 - num1);
break;
case "*":
stk.push(num2 * num1);
break;
case "/":
stk.push(num2 / num1);
}
}
}
return stk.peek();
}
}
蒻霁自己的实现(最老的版本)
class Solution {
public int calculate(String s) {
if(s==null || s.length() ==0)
return 0;
Stack<Integer> nums = new Stack<Integer> ();
Stack<Character> operator = new Stack<Character> ();
int i=0;
while(i < s.length()) {
while( i < s.length() && s.charAt(i) == ' ')
i++;
if(i >= s.length())
break;
if(s.charAt(i) <='9' && s.charAt(i) >='0' ) {
int num = 0;
while(i < s.length() && s.charAt(i) >='0' && s.charAt(i) <='9') {
num*=10;
num += s.charAt(i) -'0';
i++;
}
nums.push(num);
}
else {
while(!operator.isEmpty() &&
(
(s.charAt(i) == '+' || s.charAt(i)=='-') ||
( (s.charAt(i) == '*' || s.charAt(i)=='/') && (operator.peek() == '*' || operator.peek() =='/') )
)){
Character op =operator.pop();
int num1 = nums.pop();
int num2 = nums.pop();
if(op == '*') {
nums.push(num1 * num2);
//System.out.println(num1 + "*" + num2 + " " + (num1 * num2));
} else if(op == '/') {
nums.push(num2 / num1);
//System.out.println(num2 + "/" + num1 + " " + (num2 / num1));
} else if(op == '+') {
nums.push(num1 + num2);
//System.out.println(num2 + "+" + num1 + " " + (num2 + num1));
} else {
nums.push(num2 - num1);
//System.out.println(num2 + "-" + num1 + " " + (num2 - num1));
}
}
operator.push(s.charAt(i));
i++;
}
}
while(!operator.isEmpty()) {
Character ch = operator.pop();
int num1 = nums.pop();
int num2 = nums.pop();
if(ch == '+')
nums.push(num1 + num2);
else if(ch == '-')
nums.push(num2 - num1);
else if(ch == '*')
nums.push(num2 * num1);
else
nums.push(num2 / num1);
}
return nums.peek();
}
}
注意:
Character.isDigit() //判断是否是一个字符串
str.substring(start,end) // [start,end);

浙公网安备 33010602011771号