逆波兰表达器的实现
逆波兰表达式(后缀表达式)
逆波兰表达式(后缀表达式)
后缀表达式:平时使用的是中缀表达式
举例说明:
(1 + 4) * 4 - 6
完成任务如下:
任务一:将一个中缀表达式转换为一个后缀表达式
举例说明:1+((2+3)4)-5转换为 集合ArrayList[1,2,3,+,4,,+,5,-]
计算结果为:16
实现思路:
第一步:
将字符串1+((2+3)4)-5转换为一个ArrayList[1,+,(, (,2,+,3,),,4,),-,5]
第二步:将集合中的中缀表达式转换为后缀表达式
1、建立一个栈用来存储临时的运算符和括号;
建立一个List集合用来存储后缀表达式;
建立一个整数型的top表示栈顶
2、遍历中缀表达式的集合
①:如果取出的是一个数字,直接加入到后缀表达式集合中
②:如果是左括号,直接进入临时栈
③:如果是右括号,则while循环,结束条件为遇到左括号,
执行体为弹出临时栈的运算符,并且加入到后缀表达式的集合中
④:如果遇到的是运算符:
如果临时栈为空,直接入栈,
如果不为空,判断运算符的优先级
while(当栈顶的运算符等级大于等于新的运算符的时候 && 临时栈不为空){
弹临时栈到结果栈
}新的运算符加入临时栈
3、遍历结束后将临时栈的运算符加入到结果集
第三步:得到对应的后缀表达式
任务二:完成一个后缀表达式的计算
实现思路:1、将得到的字符串转换为一个字符数组(里面只含有数字和运算符)
2、建立一个栈用来储存数据以便用来计算结果
3、如果输入的为数字则入栈,如果为运算符,则弹栈,用后弹出的数字加减乘除前面的数字
4、最后一个数据直接弹栈为最终结果
代码实现
package com.atguigu.polandNotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
*
* 逆波兰表达式(后缀表达式)
* 后缀表达式:平时使用的是中缀表达式
* 举例说明:(1 + 4) * 4 - 6
* 对应的后缀表达式式为 1 4 + 4 * 6 -
* 1 + 10 / 2 - 3 * ( 6 / 2)
* 后缀表达式为:1 10 2 / + 3 6 2 / * - 结果:-3
*
*
* 完成任务如下:
* 任务一:将一个中缀表达式转换为一个后缀表达式
* 举例说明:1+((2+3)*4)-5转换为 集合ArrayList[1,2,3,+,4,*,+,5,-]
* 计算结果为:16
* 实现思路:
* 第一步:将字符串1+((2+3)*4)-5转换为一个ArrayList[1,+,(,(,2,+,3,),*,4,),-,5]
* 第二步:将集合中的中缀表达式转换为后缀表达式
* 1、建立一个栈用来存储临时的运算符和括号;
* 建立一个List集合用来存储后缀表达式;
* 建立一个整数型的top表示栈顶
* 2、遍历中缀表达式的集合
* ①:如果取出的是一个数字,直接加入到后缀表达式集合中
* ②:如果是左括号,直接进入临时栈
* ③:如果是右括号,则while循环,结束条件为遇到左括号,
* 执行体为弹出临时栈的运算符,并且加入到后缀表达式的集合中
* ④:如果遇到的是运算符:
* 如果临时栈为空,直接入栈,
* 如果不为空,判断运算符的优先级
* while(当栈顶的运算符等级大于等于新的运算符的时候 && 临时栈不为空){
* 弹临时栈到结果栈
* }新的运算符加入临时栈
* 3、遍历结束后将临时栈的运算符加入到结果集
*
*
* 第三步:得到对应的后缀表达式
*
*
* 任务二:完成一个后缀表达式的计算
*实现思路:1、将得到的字符串转换为一个字符数组(里面只含有数字和运算符)
* 2、建立一个栈用来储存数据以便用来计算结果
* 3、如果输入的为数字则入栈,如果为运算符,则弹栈,用后弹出的数字加减乘除前面的数字
* 4、最后一个数据直接弹栈为最终结果
*/
public class PolandNotation {
public static void main(String[] args) {
//完成任务,将一个中缀表达式转换为一个后缀表达式
//第一步:将字符串1+((2+3)*4)-5转换为一个ArrayList[1,+,(,(,2,+,3,),*,4,),-,5]
String infixExpression = "1+((2+3)*4)-5";
List<String> infixExpressionList = toinfixExpression(infixExpression);
//第二步:将集合中的中缀表达式转换为后缀表达式
List<String> suffList = transfromSuffExpression(infixExpressionList);
//第三步:得到对应的后缀表达式
System.out.println("中缀表达式" + infixExpression + "\t的后缀表达式为" + suffList);
//第四步,计算
int results = count(suffList);
System.out.println("中缀表达式" + infixExpression + "\t的最终的计算结果为" + results);
System.out.println("<-------------------------分割线-------------------------->");
//输入带有空格的后缀表达式
// String suffixExpression = "1 4 + 4 * 6 -";//14
String suffixExpression = "1 10 2 / + 3 6 2 / * -";//-3
List se = processingData(suffixExpression);
System.out.println("后缀表达式" + suffixExpression + "的每个元素为" +se);
//运算的方法
int result = count(se);
System.out.println("后缀表达式" + suffixExpression + "的最终的计算结果为" + result);
}
//将集合中的中缀表达式转换为后缀表达式
private static List<String> transfromSuffExpression(List<String> infixExpressionList) {
// 1、建立一个栈用来存储临时的运算符和括号;
// 建立一个List集合用来存储后缀表达式;
List<String> suffList = new ArrayList<String> ();
//建立一个栈,存储临时变量
Stack<String> st = new Stack<String>();
// 建立一个整数型的top表示栈顶
int top = 0;
// 2、遍历中缀表达式的集合
for (String item:infixExpressionList) {
if (item.matches("\\d*")){// ①:如果取出的是一个数字,直接加入到后缀表达式集合中
suffList.add(item);
}else if ("(".equals(item)){//②:如果是左括号,直接进入临时栈
st.push(item);
}else if (")".equals(item)){
// ③:如果是右括号,则while循环,结束条件为遇到左括号,
// 执行体为弹出临时栈的运算符,并且加入到后缀表达式的集合中
while(!("(".equals(st.peek()))){
suffList.add(st.pop());
}
//弹出左括号
st.pop();
}else if ("+".equals(item) ||"-".equals(item) ||"*".equals(item) ||"/".equals(item)){
// ④:如果遇到的是运算符:
// * 如果临时栈为空,直接入栈,
if (st.size() == 0){
st.push(item);
}else {
// * 如果不为空,判断运算符的优先级
while(st.size() != 0 && operatorLevel(st.peek()) >= operatorLevel(item)
){
suffList.add(st.pop());
}
// 新的运算符加入临时栈
st.push(item);
// while(当栈顶的运算符等级大于等于新的运算符的时候 && 临时栈不为空){
// * 弹临时栈到结果栈
// }
}
}
}
// 3、遍历结束后将临时栈的运算符加入到结果集
while(st.size() != 0){
suffList.add(st.pop());
}
return suffList;
}
//将字符串1+((2+3)*4)-5转换为一个ArrayList[1,+,(,(,2,+,3,),*,4,),-,5]
private static List<String> toinfixExpression(String infixExpression) {
List<String> suffList = new ArrayList<String>();
String str;//用于字符串拼接
int i = 0;
char c;//用来存储每次取到的字符串
while(i < infixExpression.length()){
//如果不是数字的话,直接进入集合
if ((c = infixExpression.charAt(i)) < 48 || (c = infixExpression.charAt(i)) > 57){
suffList.add("" +c);
i++;
}else{
//如果是数字需要考虑多位数的问题
str = "";
while(i < infixExpression.length() &&(c = infixExpression.charAt(i)) >= 48 && (c = infixExpression.charAt(i)) <= 57){
str += c;
i++;
}
suffList.add(str);
}
}
return suffList;
}
//为波兰计算器的计算部分,输入的se为一个集合
private static int count(List<String> se) {
Stack<String> stacks = new Stack<String>();
int num1;
int num2;
int TemporaryValue;
for (int i = 0; i < se.size(); i++) {
if (se.get(i).matches("\\d+")){//为数字则入栈
stacks.push(se.get(i));
}else if("+".equals(se.get(i))){
num2 = Integer.parseInt(stacks.pop());
num1 = Integer.parseInt(stacks.pop());
TemporaryValue = num1 + num2;
stacks.push(String.valueOf(TemporaryValue));
}else if("-".equals(se.get(i))){
num2 = Integer.parseInt(stacks.pop());
num1 = Integer.parseInt(stacks.pop());
TemporaryValue = num1 - num2;
stacks.push(String.valueOf(TemporaryValue));
}else if("*".equals(se.get(i))){
num2 = Integer.parseInt(stacks.pop());
num1 = Integer.parseInt(stacks.pop());
TemporaryValue = num1 * num2;
stacks.push(String.valueOf(TemporaryValue));
}else if("/".equals(se.get(i))){
num2 = Integer.parseInt(stacks.pop());
if (0 == num2){
throw new RuntimeException("除数不可以为零");
}
num1 = Integer.parseInt(stacks.pop());
TemporaryValue = num1 / num2;
stacks.push(String.valueOf(TemporaryValue));
}
}
return Integer.parseInt(stacks.pop());
}
//将后缀表达式处理为一个字符转数组(去掉空格)
private static List<String> processingData(String suffixExpression) {
String[] se = suffixExpression.split(" ");
List<String> valuse = new ArrayList<String>();
for (String ses:se) {
valuse.add(ses);
}
return valuse;
}
//判断运算符等级的方法
public static int operatorLevel(String operator){
int grade = 0;
switch (operator){
case "+":
grade = 1;
break;
case "-":
grade = 1;
break;
case "*":
grade = 2;
break;
case "/":
grade = 2;
break;
case "(":
break;
case ")":
break;
default:
System.out.println("输入有误");
break;
}
return grade;
}
}