Java中缀表达式转后缀表达式并计算后缀表达式的值
Posted Spring-_-Bear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中缀表达式转后缀表达式并计算后缀表达式的值相关的知识,希望对你有一定的参考价值。
一、中缀表达式转后缀表达式的思路分析
从左到右开始扫描中缀表达式:
-
遇到数字,直接输出
-
遇到运算符:
2.1 若为左括号 “(” 或栈为空则 直接入栈
2.2 若为右括号 “)” 将符号栈中的元素依次出栈并输出, 直到左括号 “(“ 出栈, “(“ 只出栈不输出
2.3 若为其他符号, 将符号栈中的元素依次出栈并输出, 直到遇到比当前符号优先级更低的符号,并将当前符号入栈 -
扫描完后, 将符号栈栈中剩余符号依次输出
二、中缀表达式转后缀表达式的代码实现
/**
* 将中缀表达式转换为后缀表达式,生成的后缀表达式各元素之间使用一个空格间隔
*
* @param infixExp 中缀表达式
* @return 后缀表达式 或 null
*/
public String infixToSuffix(String infixExp)
if (infixExp == null || infixExp.length() == 0)
return null;
Stack<String> operatorStack = new Stack<>();
List<String> infixList = infixExpIntoList(infixExp);
StringBuilder res = new StringBuilder();
// 从左至右遍历中缀表达式
for (String str : infixList)
// 如果是数字则直接输出
if (str.matches("\\\\d+"))
res.append(str).append(" ");
else if ("(".equals(str) || operatorStack.size() == 0)
// 左括号或栈为空则直接入栈
operatorStack.push(str);
else if (")".equals(str))
// 右括号需要将符号栈中的 "(" 括号之前的操作符全部输出,"(" 只出栈不输出
String op;
while (!"(".equals((op = operatorStack.pop())))
res.append(op).append(" ");
else
// 栈顶操作符优先级大于等于当前操作符,则弹出栈顶元素,结束后将当前操作符压入栈中
while (operatorStack.size() > 0 && getPriority(operatorStack.peek()) - getPriority(str) >= 0)
res.append(operatorStack.pop()).append(" ");
operatorStack.push(str);
// 将符号栈中剩余的操作符输出
while (operatorStack.size() > 0)
res.append(operatorStack.pop()).append(" ");
return res.toString();
三、对后缀表达式进行计算的思路分析
后缀表达式的特点是运算符位于与其相关的操作数之后。计算机求值步骤如下:
- 从左至右扫描后缀表达式
- 遇到数字将其压入栈中
- 遇到操作符则从栈中弹出两个操作数并计算,将计算结果再次压入栈中
- 如此往复直至扫描完整个表达式
- 弹出栈中剩余的数即为运算结果
四、后缀表达式运算的代码实现
/**
* 计算后缀表达式,要求传入的后缀表达式各操作符与操作数之间以空格间隔
*
* @param suffixExp 后缀表达式
* @return 计算结果
*/
public int calSuffixExp(String suffixExp)
String[] suffix = suffixExp.split(" ");
Stack<Integer> numStack = new Stack<>();
// 从左至右遍历后缀表达式
for (String str : suffix)
// 遇到数字则将其压入栈中
if (str.matches("\\\\d+"))
numStack.push(Integer.valueOf(str));
else
// 遇到操作符则从栈顶依次弹出两个操作数计算得到结果 res,并将 res 再次压入栈顶
numStack.push(calculate(numStack.pop(), numStack.pop(), str));
return numStack.pop();
五、中缀转后缀并求出运算结果完整版代码实现
package com.bear.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* @author Spring-_-Bear
* @datetime 2022/3/11 9:29
*/
public class Calculator
/**
* 计算后缀表达式,要求传入的后缀表达式各操作符与操作数之间以空格间隔
*
* @param suffixExp 后缀表达式
* @return 计算结果
*/
public int calSuffixExp(String suffixExp)
String[] suffix = suffixExp.split(" ");
Stack<Integer> numStack = new Stack<>();
// 从左至右遍历后缀表达式
for (String str : suffix)
// 遇到数字则将其压入栈中
if (str.matches("\\\\d+"))
numStack.push(Integer.valueOf(str));
else
// 遇到操作符则从栈顶依次弹出两个操作数计算得到结果 res,并将 res 再次压入栈顶
numStack.push(calculate(numStack.pop(), numStack.pop(), str));
return numStack.pop();
/**
* 将中缀表达式转换为后缀表达式,生成的后缀表达式各元素之间使用一个空格间隔
*
* @param infixExp 中缀表达式
* @return 后缀表达式 或 null
*/
public String infixToSuffix(String infixExp)
if (infixExp == null || infixExp.length() == 0)
return null;
Stack<String> operatorStack = new Stack<>();
List<String> infixList = infixExpIntoList(infixExp);
StringBuilder res = new StringBuilder();
// 从左至右遍历中缀表达式
for (String str : infixList)
// 如果是数字则直接输出
if (str.matches("\\\\d+"))
res.append(str).append(" ");
else if ("(".equals(str) || operatorStack.size() == 0)
// 左括号或栈为空则直接入栈
operatorStack.push(str);
else if (")".equals(str))
// 右括号需要将符号栈中的 "(" 括号之前的操作符全部输出,"(" 只出栈不输出
String op;
while (!"(".equals((op = operatorStack.pop())))
res.append(op).append(" ");
else
// 栈顶操作符优先级大于等于当前操作符,则弹出栈顶元素,结束后将当前操作符压入栈中
while (operatorStack.size() > 0 && getPriority(operatorStack.peek()) - getPriority(str) >= 0)
res.append(operatorStack.pop()).append(" ");
operatorStack.push(str);
// 将符号栈中剩余的操作符输出
while (operatorStack.size() > 0)
res.append(operatorStack.pop()).append(" ");
return res.toString();
/**
* 将中缀表达式各操作数、操作符元素分割添加到 List 中
*
* @param infixExp 中缀表达式
* @return list 或 null
*/
public List<String> infixExpIntoList(String infixExp)
if (infixExp == null || infixExp.length() == 0)
return null;
int len = infixExp.length();
List<String> infixList = new ArrayList<>();
// 从左至右遍历中缀表达式,依次将操作数和操作符加入 List 中
for (int i = 0; i < len; i++)
char ch = infixExp.charAt(i);
// ASCII 码在 [48,57] 的为数字,将非数字加入到 List 中
if (ch < 48 || ch > 57)
infixList.add(String.valueOf(ch));
continue;
// 将当前数字连接到数字字符串中
String digitsStr = "" + ch;
++i;
// 判断该数字接下来的字符是否是数字即是否是一个多位数
while (i < len && infixExp.charAt(i) >= 48 && infixExp.charAt(i) <= 57)
digitsStr += infixExp.charAt(i);
++i;
infixList.add(digitsStr);
// 因为 while 循环中 ++i 语句和 for循环中的 i++ 语句使 i 多自增 1,故此处 --i
--i;
return infixList;
/**
* 获得运算符的优先级:加减运算优先级为 0,乘除运算优先级为 1
*
* @param operator 运算符
* @return 运算符优先级代号
*/
public int getPriority(String operator)
switch (operator)
case "+":
case "-":
return 1;
case "*":
case "/":
return 2;
default:
return 0;
/**
* 计算两数运算结果
*
* @param num1 number
* @param num2 number
* @param operator operator
* @return 运算结果
*/
public Integer calculate(Integer num1, Integer num2, String operator)
switch (operator)
case "+":
return num1 + num2;
case "-":
return num2 - num1;
case "*":
return num1 * num2;
case "/":
return num2 / num1;
default:
System.out.println("非法的操作符");
return null;
以上是关于Java中缀表达式转后缀表达式并计算后缀表达式的值的主要内容,如果未能解决你的问题,请参考以下文章