package com.zpl.suanfa;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 用於界面簡單的四則運算字符串類型的表達式
*
* @author zhangpengliang
*
* 算法知識:後綴表達式 a+b*c+(d*e+f)*g
* <p>
* 是正常的表達式,我們要將這個轉換成後綴表達式:abc*+de*f+g*+ <br>
* 1、當讀到一個操作數的時候直接輸出,操作符不能立即輸出,要放到棧中,當遇到"("時也要推入到棧中<br>
* 2、當遇到")"時,就將棧元素依次彈出,並輸出,直到彈出的符號是一個"(",就直接彈出"(",右括號就不能再推入棧中了
* 3、當遇到其他符號如"+","*","("等時,我們從棧中彈出棧元素並輸出直到發現優先級更低的元素爲止<br>
* 如果是同級的,比如"+"與"-"和"+"都是同級。也要彈出輸出,雖然"("的優先級很高,但是只有在處理")"纔可以彈出但不輸出
* 4、第三步彈出輸出完後,需要將這個比較的元素壓到棧中 <br>
* 5、如何計算abc*+de*f+g*+<br>
* 先將a b 壓到棧中,然後遇到操作數就壓入棧中,遇到操作符就將棧中的最頂的兩位b c與操作符處理,b*c=v;然後再將v壓入 <br>
* 棧中,依次類推
*
*
*
*
*
*/
public class HouZhuiExpression {
private char[] chs = { '+', '-', '*', '/', '(', ')' };
/**
* 將字符串表達式轉換成一個list表,操作數與操作符分開
*
* @param exp
* @return
*/
private List<String> expressionToHouZhuiExpression(String exp) {
List<String> list = new ArrayList<String>();
char[] str = exp.toCharArray();
int j = 0;
for (int i = 0; i < str.length; i++) {
if (ishave(str[i])) {
String res = exp.substring(j, i);
j = i + 1;
if (!res.equals("") && res != null)
list.add(res);
list.add(String.valueOf(str[i]));
} else if (j < str.length && i == str.length - 1) {
String res = exp.substring(j, i + 1);
j = i;
list.add(res);
}
}
return list;
}
/**
* 後綴表達式
*
* @param list
* @return
*/
private List<String> List2HouZhuiExpr(List<String> list) {
String exp = "";
List<String> value = new ArrayList<String>();
Stack<String> stack = new Stack<String>();
for (String str : list) {
if (ishave(str)) {
if (stack.isEmpty())
stack.push(str);
else {
String a = cc(stack, str);
exp = exp + a;
if (!a.equals("")) {
value.addAll(expressionToHouZhuiExpression(a));
}
}
} else {
exp = exp + str;
value.add(str);
}
}
if (!stack.isEmpty()) {
for (int i = stack.size() - 1; i >= 0; i--) {
exp = exp + stack.get(i);
value.add(stack.get(i));
}
}
return value;
}
/**
* 遞歸邏輯
*
* @param stack
* @param str
* @return
*/
private String cc(Stack<String> stack, String str) {
String a = "";
if (stack.isEmpty()) {
stack.push(str);
return a;
}
String stck = stack.peek();
if (isPop(stck, str)) {
if (stck.equals("(")) {
stack.pop();
return a;
} else {
stack.pop();
a = stck;
a = a + cc(stack, str);
}
} else {
stack.push(str);
}
return a;
}
/**
* 判斷該操作符是否要彈出
*
* @param stck
* @param s
* @return
*/
private boolean isPop(String stck, String s) {
boolean flag = false;
if (s.equals("+") || s.equals("-")) {
if (stck.equals("+") || stck.equals("-") || stck.equals("*") || stck.equals("/")) {
flag = true;
}
} else if (s.equals("*") || s.equals("/")) {
flag = false;
} else if (s.equals("(")) {
flag = false;
} else if (s.equals(")")) {
flag = true;
}
return flag;
}
/**
* 判斷字符是否爲操作符
*
* @param ch
* @return
*/
private boolean ishave(char ch) {
boolean flag = false;
for (int i = 0; i < chs.length; i++) {
if (chs[i] == ch) {
flag = true;
break;
}
}
return flag;
}
/**
* 判斷字符串是否在這些符號中
*
* @param ch
* @return
*/
private boolean ishave(String ch) {
boolean flag = false;
for (int i = 0; i < chs.length; i++) {
if (String.valueOf(chs[i]).equals(ch)) {
flag = true;
break;
}
}
return flag;
}
/**
* 開始計算
*
* @param value
* @return
*/
private String caculate(List<String> value) {
Stack<String> s = new Stack<String>();
s.push(value.get(0));
s.push(value.get(1));
for (int i = 2; i < value.size(); i++) {
String key = value.get(i);
if (ishave(key)) {
int a = Integer.valueOf(s.pop());
int b = Integer.valueOf(s.pop());
int res = sum(b, a, key);
s.push(String.valueOf(res));
} else {
s.push(key);
}
}
if (s.isEmpty()) {
return "0";
} else {
String res = s.pop();
return res;
}
}
private int sum(int a, int b, String key) {
if (key.equals("*")) {
return a * b;
} else if (key.equals("/")) {
return a / b;
} else if (key.equals("+")) {
return a + b;
} else if (key.equals("-")) {
return a - b;
} else
return 0;
}
public static void main(String[] args) {
HouZhuiExpression hze = new HouZhuiExpression();
// String exp = "a+b*c+(d*e+f)*g";
String exp = "(6/3+6*2)+9";
List<String> list = hze.expressionToHouZhuiExpression(exp);
List<String> b = hze.List2HouZhuiExpr(list);
String ee = hze.caculate(b);
System.out.println(ee);
}
}
該方式使用了棧的數據結構具體實現看代碼,有錯誤歡迎指出。。。