public class PolandNotation {
/**
* @author hoy
* 中缀表达式 -> 后缀表达式list<String>
* 思路:
* 1. 创建一个堆栈,operatorStack<string> 用于保留运算符; 创建一个list,postfixList<string> 用于保留中间结果。
* 2. 原始中缀表达式 -> 中缀表达式list<string>
* 3. 中缀表达式list<string> -> 后缀表达式list<string>:遍历list,临时变量为 item
* 3.1 item为数字:入栈 postfixList。
* 3.2 item为 ( :item 入栈 operatorStack。
* 3.3 item为 ):逐个从 operatorStack 出栈,并入栈 postfixList,直到碰到 (,且删除 (。
* 3.4 item为*,/,+或-的运算符,循环查看operatorStack的top:
* 3.4.1 若
* a. operatorStack 为空 或
* b. top为( 或
* c. item 优先级大于 top
* 则:item 入栈 operatorStack
* 3.4.2 否则:top 入栈 postfixList,继续 2.2.1 比较下一top
* 4. 将字符栈中剩余字符逐个出栈,并加入输出 postfixList,返回输出list
*
* @param originalExpression - 原表达式,元素用空格隔开。如"7 * 4 - 20 / ( 3 + 1 )"
* @return - 所生成的后缀表达式
*/
public static ArrayList<String> getPostfixExpression(String originalExpression) {
// 0. 校验参数:是否为null或者空
if (originalExpression == null || originalExpression.isEmpty()) {
throw new RuntimeException("expression wrong");
}
originalExpression = originalExpression.trim();
// 1. 创建一个堆栈,operatorStack<string> 用于保留运算符; 创建一个list,postfixList<string> 用于保留中间结果。
Stack<String> operatorStack = new Stack<>();
ArrayList<String> postfixList = new ArrayList<>();
// 2. 原始中缀表达式 -> 中缀表达式list<string>
ArrayList<String> originalExpressionList = getExpressionList(originalExpression);
// 3. 中缀表达式list<string> -> 后缀表达式list<string>:遍历list,临时变量为 item
for (String item : originalExpressionList){
// 3.1 item为数字:入栈 postfixList。
if (item.matches("\\d+")){
postfixList.add(item);
}
// 3.2 item为 ( :item 入栈 operatorStack。
else if (item.equals("(")) {
operatorStack.push(item);
}
// 3.3 item为 ):逐个从 operatorStack 出栈,并入栈 postfixList,直到碰到 (,且删除 (。
else if (item.equals(")")) {
while (!operatorStack.peek().equals("(")) {
postfixList.add(operatorStack.pop());
}
operatorStack.pop(); // "("出栈
}
// 3.4 item为*,/,+或-的运算符,循环查看operatorStack的top:
else if (item.equals("+")
|| item.equals("-")
|| item.equals("*")
|| item.equals("/")){
// (1) 循环从 operatorStack 中出栈 top,并将top加入postfixList。
// 当 a. operatorStack 为空 或
// b. top为( 或
// c. item 优先级大于 top
// 时停止
while (!operatorStack.isEmpty()
&& !operatorStack.peek().equals("(")
&& getPriority(item) <= getPriority(operatorStack.peek())) {
postfixList.add(operatorStack.pop());
}
// (2) item 入栈 operatorStack
operatorStack.push(item);
}
}
// 4. 将字符栈中剩余字符逐个出栈,并加入输出 postfixList,返回输出list
while (!operatorStack.isEmpty()) {
postfixList.add(operatorStack.pop());
}
return postfixList;
}
// for getPostfixExpression()
public static ArrayList<String> getExpressionList(String expression) {
ArrayList<String> expressionList = new ArrayList<>();
StringBuilder wholeNumber = new StringBuilder();
for (int i = 0; i < expression.length(); i++) {
String item = expression.substring(i, i + 1);
if (item.equals(" ")) {
continue;
} else if (isNumber(item)) {
wholeNumber.append(item);
if (i == expression.length() - 1 || !isNumber(expression.substring(i + 1, i + 2))) {
expressionList.add(wholeNumber.toString());
wholeNumber = new StringBuilder();
}
} else if (isOperatorOrBracket(item)) {
expressionList.add(item);
}
}
return expressionList;
}
// for getExpressionList()
private static boolean isNumber(String item) {
switch (item) {
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
return true;
default:
return false;
}
}
// for getExpressionList()
private static boolean isOperatorOrBracket(String item) {
return item.equals("+")
|| item.equals("-")
|| item.equals("*")
|| item.equals("/")
|| item.equals("(")
|| item.equals(")");
}
// for all two method
private static int getPriority(String operator) {
switch (operator) {
case "*":
case "/":
return 1;
case "+":
case "-":
return 0;
default:
return -1;
}
}
/**
* @author hoy
* 通过所给的后缀表达式,计算结果。
* @param postfixExpressionList - 后缀表达式的list。如"7,4,*,20,3,1,+,/,-"
* @return
*/
public static int calculateByPostfixExpression(ArrayList<String> postfixExpressionList) {
// 1. 设置数字栈栈,存放各个元素
Stack<Integer> digitStack = new Stack<>();
// 2. 遍历栈
for (String item : postfixExpressionList) {
// 2.1 若item为数字(用正则表达式判断):入栈
if (item.matches("\\d+")){
digitStack.push(Integer.parseInt(item));
}
// 2.2 若item为运算符:出栈两个数字,根据item计算结果,并将结果入栈
else {
// (1) 设置计算数字和结果的int变量
int number1 = digitStack.pop();
int number2 = digitStack.pop();
int result = 0;
// (2) 计算结果
switch (item) {
case "+":
result = number1 + number2;
break;
case "-":
result = number2 - number1;
break;
case "*":
result = number1 * number2;
break;
case "/":
result = number2 / number1;
break;
default:
throw new RuntimeException("wrong char");
}
// (3) 结果入栈
digitStack.push(result);
}
}
// 3. 返回栈顶数字
return digitStack.pop();
}
/**
* @author monash
* ** 生成并获取表达式的"后缀表达式"(所输入的表达式已用括号标明了优先级)**
* 思路:
* 1. 创建一个空堆栈,opstack用于保留运算符。创建一个空列表进行输出。
* 2. 使用string方法将输入的中缀字符串转换为列表 split。
* 3. 从左到右扫描令牌列表。
* 3.1 如果令牌是操作数,则将其附加到输出列表的末尾。
* 3.2 如果标记是左括号,请将其推到上opstack。
* 3.3 如果标记是右括号,请弹出opstack直到删除相应的左括号。将每个运算符追加到输出列表的末尾。
* 3.4 如果令牌是*,/,+或-运算符,则将其推入 opstack。但是,请先删除上opstack具有更高或相等优先级的所有运算符 ,然后将它们附加到输出列表中。
* 4. 将字符栈中剩余字符逐个出栈,并加入输出 list,返回输出list
*
* @param originalExpression - 原表达式,元素用空格隔开。如"( 7 * 4 ) - ( 20 / ( 3 + 1 ) )"
* @return - 所生成的后缀表达式
*/
public static ArrayList<String> getPostfixExpressionWithAllBracket(String originalExpression) {
// 0. 校验参数:是否为null或者空
originalExpression = originalExpression.trim();
if (originalExpression == null || originalExpression.isEmpty()) {
throw new RuntimeException("expression wrong");
}
// 1. 设置必要变量
// 1.1 设置字符栈(stack<string>)
Stack<String> operationStack = new Stack<>();
// 1.2 设置输出list(list<string>)
ArrayList<String> list = new ArrayList<>();
// 2. 将originalExpression转化为string数组,遍历数组
String[] originalArray = originalExpression.split(" ");
for (String item : originalArray){
// 2.1 若是数字,加入输出list
if (item.matches("\\d+")){
list.add(item);
}
// 2.2 若是字符,进行判断:
else {
switch (item) {
// (1) 若是"(":入字符栈
case "(":
operationStack.push(item);
break;
// (2) 若是")":字符栈逐个出栈,逐个添加入输出list,直到遇到"("后停止,并从字符栈中删除"("
case ")":
while(true){
String topOperator = operationStack.pop();
if (topOperator.equals("(")) {
break;
}
list.add(topOperator);
}
break;
// (3) 若是运算符:
case "+":
case "-":
case "*":
case "/":
// (3.1) 逐个将"栈内优先级大于当前运算符的运算符"出栈,放入输出list
while (!operationStack.isEmpty() && getPriority(operationStack.peek()) > getPriority(item)) {
list.add(operationStack.pop());
}
// (3.2) 处理完成后,当前运算符入字符栈
operationStack.push(item);
break;
// (4) 否则,抛出异常
default:
throw new RuntimeException("wrong character");
}
}
}
// 3. 将字符栈中剩余字符逐个出栈,并加入输出list,返回输出list
while (!operationStack.isEmpty()) {
list.add(operationStack.pop());
}
return list;
}
}
【数据结构与算法(Java)】逆波兰计算器(后缀表达式实现)
最新推荐文章于 2021-03-18 15:57:58 发布