栈的特点:先进后出
中缀表达式转后缀表达式
申请一个栈对象:用于存放符号(运算符和括号)
创建一个StringBuffer对象:用于保存数字
实现过程:输入的计算表达式为一个字符串,获取字符串中每一个下标的字符,若获取到的字符为数字则存放在StringBuffer对象中,若为运算符或括号则进行入栈。当入栈的符号为右括号时,则停止入栈,把左括号之前的运算进行出栈操作并保存在StringBuffer对象中,然后把左括号进行出栈操作。
计算后缀表达式
申请一个栈对象:用于存放数字
实现过程:把后缀表达式进行入栈操作,入栈过程中若遇到运算符,则获取栈中的栈顶元素和下一个元素,进行相关运算操作,再把运算所得的结果进行入栈,依次进行直到后缀表达式入栈结束,此时栈中就剩余一个元素,该元素就是计算表达式的结果。
主要解决问题
运算符优先级的判断
处理大于两个连续的数字的拼接
代码实现
//初始化字符串
public static List InitData(String str) {
//把字符串存放在集合中,主要解决数字为两位数字以上时的运算
List<String> list=new ArrayList<>();
//存放遇到运算符之前的数字
StringBuffer stringBuffer=new StringBuffer();
for (int i = 0; i < str.length(); i++) {
//当前字符为运算符
if(str.charAt(i)=='+'||str.charAt(i)=='-'||str.charAt(i)=='*'||str.charAt(i)=='/'||str.charAt(i)==')'||str.charAt(i)=='('){
if (stringBuffer.length()>0){
//把运算符之前的数字添加到集合中
list.add(stringBuffer+"");
//清空stringBuffer的数据,为了存放下一个数字
stringBuffer.setLength(0);
}
//把当前运算符添加到集合中
list.add(str.charAt(i)+"");
}else{
//数字直接添加到 stringBuffer
stringBuffer.append(str.charAt(i));
}
}
//把最后一个数字添加到集合中
if (stringBuffer.length()>0){
list.add(stringBuffer+"");
}
return list;
}
//中缀转后缀
public static List<String> DealData(String str){
//接收初始化后的数据list
List<String> list=InitData(str);
//存放后缀表达式
List<String>list1=new ArrayList();
//判断运算符的优先级
Map<String,Integer> map =new HashMap<>();
map.put("+",1);
map.put("-",1);
map.put("*",2);
map.put("/",2);
map.put("(",3);
map.put(")",3);
//存放运算符
Stack<String> stack=new Stack<>();
for (int i = 0; i < list.size(); i++) {
//遇到左括号直接入栈
if (list.get(i).equals("(")){
stack.push(list.get(i));
} else if (list.get(i).equals(")")){//遇到右括号时把栈里面左括号之前的运算符添加到集合中
while(!stack.peek().equals("(")){
list1.add(stack.pop());
}
//删除左括号
stack.pop();
//遇到运算符
}else if (list.get(i).equals("+")||list.get(i).equals("-")||list.get(i).equals("/")||list.get(i).equals("*")){
if (stack.isEmpty()){
//栈空直接进栈
stack.push(list.get(i));
}else {
int temp1=map.get(list.get(i));
int temp2=map.get(stack.peek());
//当前运算符的优先级比栈顶运算符的优先级低,并且栈顶元素不能等于左括号
if (temp1<temp2 &&(!stack.peek().equals("("))) {
while(!stack.isEmpty()){
//栈顶元素出栈
list1.add(stack.peek());stack.pop();
}
//把当前字符入栈
stack.push(list.get(i));
} else {
//当前运算符的优先级比栈顶运算符的优先级高
stack.push(list.get(i));
}
}
}else {
//数字直接添加到集合中
list1.add(list.get(i));
}
}
//添加集合中剩余的数据
while(!stack.isEmpty()){
list1.add(stack.pop());
}
return list1;
}
//后缀计算结果
public static BigDecimal Calculator(String str){
//接收中缀转成的后缀
List<String> list=DealData(str);
//存数字
Stack<BigDecimal> stack=new Stack<>();
for (int i = 0; i < list.size(); i++) {
//遇到运算符
if (list.get(i).equals("+")||list.get(i).equals("-")||list.get(i).equals("/")||list.get(i).equals("*")){
//把运算符之前的两个数字取出
BigDecimal i1=stack.peek();stack.pop();
BigDecimal i2=stack.peek();stack.pop();
//接收i1、i2计算的结果
BigDecimal sum;
if (list.get(i).equals("-")){
sum=i2.subtract(i1);
}else if (list.get(i).equals("+")){
sum=i2.add(i1);
}else if (list.get(i).equals("*")){
sum=i2.multiply(i1);
}else {
//处理无限循环的结果
sum= BigDecimal.valueOf(i2.divide(i1,3, BigDecimal.ROUND_DOWN).doubleValue());
}
stack.push(sum);
}else {//数字直接进栈
stack.push(new BigDecimal(list.get(i)));
}
}
//获取栈中的最后一个数字,即就是运算结果
BigDecimal result =stack.peek();
return result;
}