import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* @version v 1.0
* @Author kami
* @Date 2020/5/5
*/
public class rua006 {
public static void main(String[] args) {
//说明:
//1. 1. 1+((2+3)*4)-5 => 转成 1 2 3 = 4 * + 5 -
//2. 因为直接对str进行操作 , 不方便。因此 先将 "1+((2+3)*4)-5" => 中缀表达式对应的List
// 级 "1+((2+3)*4)-5" => ArrayList[1,+,(,(,2,+,3,),*,4,),-,5]
// 方法:将中缀表达式的List转换为 => 后缀表达式的List
String expression ="1+((2+3)*4)-5";
List infixExpressionList = toInfixExpressionList(expression);
System.out.println("中缀表达式对应的是"+infixExpressionList);
List parseSuffixExperssionList = parseSuffixExperssionList(infixExpressionList);
System.out.println("后缀表达式对应的是"+parseSuffixExperssionList);
System.out.printf("expression=%d",calculate(parseSuffixExperssionList));
//1.先定义逆波兰表达式
//(3+4)*5-6 => 3 4 + 5 *6
// 4 * 5 - 8 + 60 + 8 / 2 => 4 5 * 8 - 60 + 8 2 / +
//说明为了方便 , 逆波兰表达式 的数字和符号使用空格隔开
// String suffixExpression = "3 4 + 5 * 6 - ";
// String suffixExpression = "4 5 * 8 - 60 + 8 2 / +";
//思路
//1. 先将 " 3 4 + 5 * 6 -" =>放到arraylist中
//2. 将arrayList 传递一个方法 ,遍历arrayList 配合栈完成计算
// ListrpnList = getListString(suffixExpression);
// System.out.println("rpnList="+rpnList);
// int res =calculate(rpnList);
// System.out.println("计算的结果是="+res);
}
//即ArrayList[1,+,(,(,2,+,3,),*,4,),-,5] => ArrayList[1,2,3,+,4,*,+,5,-]
// 方法:将中缀表达式的List转换为 => 后缀表达式的List
public static ListparseSuffixExperssionList(Listls){
//定义两个栈
Stack s1 = new Stack<>();//符号栈
//说明:因为s2 这个栈,在整个转换过程中,没有pop操作,而且后面我们还需要逆序输出
//因此比较麻烦,因此我们就不用Stack 直接使用 Lists2
// Stack s2 = new Stack<>();//储存中间结果的栈s2
ArrayList s2 = new ArrayList<>();//储存中间结果的Lists2
//遍历ls
for (String item : ls) {
//如果是一个数,加入s2
if (item.matches("\\d+")){
s2.add(item);
}else if (item.equals("(")){
s1.push(item);
}else if (item.equals(")")){
//如果是右括号“)”,则弹出s1栈顶的运算符,并压入s2,知道遇到左括号为止,此刻这一对括号丢弃
while (!s1.peek().equals("(")){
s2.add(s1.pop());
}
s1.pop();//!!! ( 弹出s1栈,清除小括号
}else {
//当item 的优先级小于等于栈顶运算符,将s1栈顶的运算符弹出并加入到s2中 ,再次转到(4,1)与s1中的栈顶运算符相对比较
//问题 : 我们缺少一个比较优先级高低的方法
while (s1.size() != 0 && Operation.getValue(s1.peek())>=Operation.getValue(item)){
s2.add(s1.pop());
}
//还需要将item压入栈
s1.push(item);
}
}
//将s1中剩余的运算符依次弹出并加入s2
while (s1.size() != 0){
s2.add(s1.pop());
}
return s2;//注意因为是存放到List,因此按顺序输出就是后缀表达式
}
//方法:将中缀表达式转换成对应的list
// s =""1+((2+3)*4)-5;
public static ListtoInfixExpressionList(String s){
//定义一个List,存放中缀表达式 对应的内容
ArrayList ls = new ArrayList<>();
int i = 0;//这是一个指针。,用于遍历中缀表达式字符串
String str;//对多位数的拼接
char c ;//每遍历到一个字符,就放入到C
do {
//如果是一个非数字,我需要加入到ls
if ((c=s.charAt(i))<48 || (c=s.charAt(i))>57){
ls.add("" + c);
i++;//i需要后移
}else { //如果是一个数,需要考虑多位数
str ="";//先将str 至成多位数
while (i <s.length() && (c=s.charAt(i))>=48 && (c=s.charAt(i))<=57){
str += c;//拼接
i++;
}
ls.add(str);
}
}while (i < s.length());
return ls;
}
private static List getListString(String suffixExpression) {
//将suffixExpression 分割
String [] split =suffixExpression.split(" ");
ArrayList list = new ArrayList<>();
for (String ele : split) {
list.add(ele);
}
return list;
}
//完成对逆波兰表达式的运算
/**
* 1. 从左到右扫描,将3和4 压入栈
* 2. 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素)
* 计算出3+4的值,得7,再将7入栈
* 将5入栈
* 接下来是 * 运算符,因此弹出5和7 计算出7*5 =35,将35入栈
* 将6入栈
* 最后是 -运算符,计算出 35 -6的值,即29。由此得出最终结果
*
*/
public static int calculate(List ls) {
//创建个栈,只需要一个栈即可
Stack stack = new Stack<>();
//遍历ls
for (String item : ls) {
//这里使用正则表达式来取值
if (item.matches("\\d+")) {//匹配的是多位数
//入栈
stack.push(item);
} else {
//pop两个数数并运算再入栈
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
if (item.equals("+")) {
res = num1 + num2;
} else if (item.equals("-")) {
res = num1 - num2;
} else if (item.equals("*")) {
res = num1 * num2;
} else if (item.equals("/")) {
res = num1 / num2;
} else {
throw new RuntimeException("运算符有误");
}
//把res 入栈
stack.push("" + res);
}
}
//最后留在stack中的数据是运算结果
return Integer.parseInt(stack.pop());
}
}
//编写一个类Operation 可以返回一个运算符 对应的优先级
class Operation{
private static int ADD =1;
private static int SUB =1;
private static int MUL =1;
private static int DIV =1;
//写一个方法,返回对应的优先级数字
public static int getValue(String operation){
int result = 0;
switch (operation){
case "+":
result =ADD;
break;
case "-":
result =SUB;
break;
case "*":
result =MUL;
break;
case "/":
result =DIV;
break;
default:
System.out.println("不存在该运算符");
break;
}
return result;
}
}
文章评论