使用栈实现一个综合的计算器的功能,用户输入想要计算的表达式,然后进行计算,主要用到的技术是栈先进后出的特点。
package com.yu.datastructure.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PolandNotation3 {
public static void main(String[] args) {
String exepression = "(7+(4*7)-1) + 7 -9 + 12 *5";
List<String> list = toList(exepression);
System.out.println("转换的集合:" + list);
List<String> parseSuffixExpressionList = parseSuffixExpressionList(list);
System.out.println("后缀表达式" +parseSuffixExpressionList);
Double value = calculation(parseSuffixExpressionList);
System.out.println("计算的结果:" + value);
}
/**
* 去除表达式的空白符
* @param str
* @return
*/
public static String replaceAllBlank(String str){
// \\s+ 匹配任何空白字符,包括空格、制表符、换页符等等, 等价于[\f\n\r\t\v]
return str.replaceAll("\\s+","");
}
/**
* 判断是否是数字的正则表达式,把点,百分号也算成数字
* @param str
* @return
*/
public static boolean isNumber(String str) {
Pattern pattern = Pattern.compile("^?[.\\d]*?[%\\d]*$");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
return true;
}
/**
* 判断是否是运算符的的正则表达式
*/
public static boolean isSymbol(String str){
return str.matches("\\+|\\-|\\*|\\/|\\(|\\)");
}
/**
* 判断运算符的优先级
*/
public static Integer operatorPriority(String str){
if("*".equals(str) || "/".equals(str)) {
return 2;
}else if("+".equals(str) || "-".equals(str)) {
return 1;
}else{
return -1;
}
}
/**
* 计算的表达式
* @param s1 第一个值
* @param s2 第二个值
* @param symbol 计算的表达式
* @return
*/
public static Double calculation(String s1,String s2,String symbol){
Double result = 0.0;
switch (symbol) {
case "+":
result = Double.valueOf(s2) + Double.valueOf(s1);
break;
case "-":
result = Double.valueOf(s2) - Double.valueOf(s1);
break;
case "*":
result = Double.valueOf(s2) * Double.valueOf(s1);
break;
case "/":
result = Double.valueOf(s2) / Double.valueOf(s1);
break;
default:
throw new RuntimeException("计算出错");
}
return result;
}
/**
* 将表达式的值放入到集合中
*/
public static List<String> toList(String exepression){
exepression = replaceAllBlank(exepression);
if (exepression == null || exepression.trim().equals("")) {
throw new RuntimeException("出具为空");
}
if(!isNumber(exepression.charAt(0) + "") && !(exepression.charAt(0) + "").equals("(")){
throw new RuntimeException("表达式的第一个值不对,请检查");
}
List<String> list = new ArrayList<>();
int index = 0;
String data = "";
String temp = "";//用于拼接数据
while(true){
if(!isNumber(data = exepression.charAt(index) + "")){
list.add(data);
index++;
}else{
while(index < exepression.length() && isNumber(data = exepression.charAt(index) + "")){
temp += data;
if(index >= exepression.length()){
break;
}
index++;
}
list.add(temp);
temp = "";
}
if(index >= exepression.length()){
break;
}
}
return list;
}
/**
* 将集合中的表达式转换为一个后缀表达式
* @param list 传入的集合
*
*/
public static List<String> parseSuffixExpressionList(List<String> expressionList) {
if (expressionList.size() <= 0) {
throw new RuntimeException("传入的数组为空,请检查");
}
Stack<String> stack = new Stack<>();// 用来存放符号的栈
List<String> list = new ArrayList<>();// 用来存放数字和符号的集合
for (String str : expressionList) {
if (isNumber(str)) {
// 如果是数字,则直接加入到集合
list.add(str);
} else {
if (str.equals("(")) {
// 如果是左括号,直接入栈
stack.push(str);
} else if (str.equals(")")) {
// 如果是右括号,则取出左边符号栈里面的符号,加入到集合里面,直到遇到符号栈里面的左括号,这样就可以消除一对括号了
while (!stack.peek().equals("(")) {
list.add(stack.pop());
}
// 消除左括号
stack.pop();
} else {
// 如果当前取出的操作符的优先级小于等于栈顶的优先级,将栈顶的元素弹出加入到集合里面,持续到大于栈的数据,然后把当前取出的数据加入到栈
while (stack.size() != 0 && operatorPriority(str) <= operatorPriority(stack.peek())) {
list.add(stack.pop());
}
stack.push(str);
}
}
}
// 操作完成之后,然后把栈里面的数据依次加入到集合里面,集合遍历的数据就是后缀表达式
while (stack.size() != 0) {
list.add(stack.pop());
}
return list;
}
/**
* 计算后缀表达式的值
* 计算规则:如果遇到的是数字,依次入栈,如果符号,则取出栈里面的值来进行计算,
* 计算之后将结果入栈,再讲数入栈,依次进行计算,最后栈里面的数据就是计算的结果
* @param list
*/
public static Double calculation(List<String> list){
if(list.size() < 0){
throw new RuntimeException("集合为空");
}
Stack<String> stack = new Stack<>();
for (String str : list) {
if(isNumber(str)){
stack.push(str);
}else{
Double calculation = calculation(stack.pop(),stack.pop(),str);
stack.push(calculation + "");
}
}
return Double.parseDouble(stack.pop());
}
}
|