逆波兰问题
package p19;
import java.util.ArrayList;
import java.util.List;
/**
* 逆波兰表达式求值
* @author Guozhu Zhu
* @date 2018/8/5
* @version 1.0
*
*/
public class NBL {
private static MyStack ms1 = new MyStack();//生成逆波兰表达式的栈
private static MyStack ms2 = new MyStack();//运算栈
// 将字符串转换为中序表达式
public static List<String> zb(String s) {
List<String> ls = new ArrayList<String>();//存储中序表达式
int i = 0;
String str;
char c;
while (i < s.length()){
if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {
ls.add("" + c);
i++;
} else {
str = "";
while (i < s.length() && (c = s.charAt(i)) >= 48
&& (c = s.charAt(i)) <= 57) {
str += c;
i++;
}
ls.add(str);
}
}
return ls;
}
//将中序表达式转换为逆波兰表达式
/**
1、从左至右扫描中缀表达式。
2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
3、若读取的是运算符
(1) 该运算符为左括号"(",则直接存入运算符堆栈。
(2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。
(3) 该运算符为非括号运算符:
(a) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
(b) 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈。
(c) 若比运算符堆栈栈顶的运算符优先级低或相等,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。
4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
*/
public static List<String> parse(List<String> ls) {
List<String> lss = new ArrayList<String>();
for (String ss : ls) {
if (ss.matches("\\d+") || (ss.charAt(0) == '-' && ss.length() > 1)) { //数字
lss.add(ss);
} else if (ss.equals("(")) { //(
ms1.push(ss);
} else if (ss.equals(")")) { //)
while (!ms1.top.equals("(")) {
lss.add(ms1.pop());
}
ms1.pop();
} else {
while (ms1.size() != 0 && getValue(ms1.top) >= getValue(ss)) {
lss.add(ms1.pop());
}
ms1.push(ss);
}
}
while (ms1.size() != 0) {
lss.add(ms1.pop());
}
return lss;
}
//对逆波兰表达式进行求值
public static int jisuan(List<String> ls) {
for (String s : ls) {
//自然数和负数时
if (s.matches("\\d+") || (s.length() > 1 && s.charAt(0) == 0)) {
ms2.push(s);
} else {
int b = Integer.parseInt(ms2.pop());
int a = Integer.parseInt(ms2.pop());
if (s.equals("+")) {
a = a + b;
} else if (s.equals("-")) {
a = a - b;
} else if (s.equals("*")) {
a = a * b;
} else if (s.equals("\\")) {
a = a / b;
}
ms2.push("" + a);
}
}
return Integer.parseInt(ms2.pop());
}
//获取运算符优先级 +,-为1 *,/为2 ()为0
public static int getValue(String s) {
if (s.equals("+")) {
return 1;
} else if (s.equals("-")) {
return 1;
} else if (s.equals("*")) {
return 2;
} else if (s.equals("\\")) {
return 2;
}
return 0;
}
//========Test========
public static void main(String[] args) {
System.out.println(jisuan(parse(zb("1+((2+3)*4)-5"))));
}
}
package cn.zhuguozhu.zgzfinal;
import java.math.BigDecimal;
import java.util.ArrayDeque;
public class Calculator {
// 计算表达式的值
public String caculate(String string) throws Exception {
// 该部分用来验证中缀表达式是否合理
// 若右括号数量大于左括号,则说明表达式不合理,抛出异常
// 否则说明正常,继续进行运算
int x = 0;
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == '(') {
x++;
} else if (string.charAt(i) == ')') {
x--;
}
}
if (x < 0) {
throw new Exception("错误,右括号数量大于左括号");
}
// 该集合用来存储操作数
ArrayDeque<String> value = new ArrayDeque<>();
// 该集合用来存储运算符
ArrayDeque<String> operation = new ArrayDeque<>();
// 该字符串用来临时存储转化后的后缀表达式
StringBuilder stringBuilder = new StringBuilder();
// 将中缀表达式的操作数和运算符分离并存放到字符串数组中
String[] expression = formatInput(string);
// 遍历字符串数组
for (String s : expression) {
// 若该字符串为空则跳过
if (s.equals(" ") || s.length() == 0) {
continue;
} else if (s.charAt(0) == '-' && !s.equals("-")) { // 若为是负数,则添加至后缀表达式末尾,并补上空格,方便后面将后缀表达式分离
stringBuilder.append(s + " ");
} else if (isDigital(s.charAt(0))) { // 若为正数,添加至后缀表达式并补空格
stringBuilder.append(s + " ");
} else if (isOperater(s.charAt(0)) || s.charAt(0) == '(' || s.charAt(0) == ')') { // 若为运算符,继续判断
if (s.equals("(")) {// 若为左括号,则压入运算符栈中
operation.push(s);
continue;
}
// 若为右括号,则将运算符栈中第一个左括号以上全部弹出并添加至后缀表达式,左括号直接弹出,不用添加至后缀表达式
if (s.equals(")")) {
while (!operation.getFirst().equals("(")) {
if (!operation.getFirst().equals("(")) {
stringBuilder.append(operation.poll() + " ");
}
}
if (operation.getFirst().equals("(")) {
operation.pop();
continue;
}
}
// 若运算符栈为空,则将运算符压入栈中
if (operation.isEmpty()) {
operation.push(s);
continue;
} else if (priorityIsBiggerOrTheSame(s, operation.getFirst())) { // 若该运算符比栈顶运算符优先级高,则压入栈中
operation.push(s);
continue;
} else { // 否则弹出所有优先级不比它低的运算符并添加至后缀表达式
while (!operation.isEmpty() && !priorityIsBiggerOrTheSame(s, operation.getFirst())) {
stringBuilder.append(operation.poll() +" ");
}
operation.push(s);
continue;
}
}
}
// 弹出操作数栈中所有元素并添加至后缀表达式
while (!operation.isEmpty()) {
stringBuilder.append(operation.poll());
}
// 格式化后缀表达式(将操作数与运算符分离)
expression = formatInfixExpression(stringBuilder.toString());
// 清空后缀表达式
stringBuilder.delete(0, stringBuilder.length());
// 遍历字符串数组
for (String s : expression) {
// 若该字符串为空,则跳过
if (s.equals(" ") || s.length() == 0) {
continue;
} else if (isDigital(s.charAt(0))) { // 若为正数则压入操作数栈中
value.push(s);
} else if (s.charAt(0) == '-' && !s.equals("-")) { // 若为负数,则压入操作数栈中
value.push(s);
} else if (isOperater(s.charAt(0))) { // 若为运算符,则判断操作数个数大于2个,则进行弹出两个操作数进行操作,然后将结果压入操作数栈中
if (value.size() >= 2) {
BigDecimal last = new BigDecimal(value.poll());
BigDecimal last_p = new BigDecimal(value.poll());
if (s.equals("-")) {
value.push(last_p.subtract(last).toString());
} else if (s.equals("+")) {
value.push(last_p.add(last).toString());
} else if (s.equals("*")) {
value.push(last_p.multiply(last).toString());
} else if (s.equals("/")) {
value.push(last_p.divide(last, 15, BigDecimal.ROUND_HALF_DOWN).toString());
}
}
}
}
// 弹出最终运算结果并返回
return value.poll();
}
// 判断是否为运算符,若为运算符,则返回true,否则返回false
public static boolean isOperater(int a) {
if (a == '+' || a == '-' || a == '*' || a == '/')
return true;
return false;
}
// 判断是否为数字,若为数字,则返回true,否则返回false
public static boolean isDigital(int a) {
if (a >= '0' && a <= '9')
return true;
return false;
}
// 格式化中缀表达式输入,即在符号前后添加空格,便于后面的分隔操作
public static String[] formatInput(String s) {
String temp = "";
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (i == 0 && c == '-') {
temp += c;
} else if (isOperater(c) || c == '(' || c == ')') {
if ((i - 1) >= 0 && (i + 1) < s.length()
&& (isOperater(s.charAt(i - 1)) || s.charAt(i - 1) == '(' || s.charAt(i - 1) == ' ')
&& c == '-' && isDigital(s.charAt(i + 1))) {
temp += " " + c;
} else {
temp += " " + c + " ";
}
} else
temp += c; // 数字不用加空格
}
return temp.split(" "); // 分割
}
// 格式化后缀表达式
public static String[] formatInfixExpression(String s) {
String temp = "";
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (isOperater(c)) {
if (c == '-' && i + 1 < s.length() && isDigital(s.charAt(i + 1))) {
temp += " " + c;
} else {
temp += " " + c + " ";
}
} else {
temp += c; // 数字不用加空格
}
}
return temp.split(" "); // 分割
}
// 优先级判断,a是否大于b
public static boolean priorityIsBiggerOrTheSame(String a, String b) {
String s = " +- */";
return s.indexOf(a) - s.indexOf(b) >= 2;
}
}