public class NiBoLan {
private static final int MAX_NODE = 100;
// 二叉樹的結點類
private static class MyTreeNode {
public double value;// 若結點是數字,則儲存為該結點的值;若是符號,則此欄位無意義
public char symbol;// '+','-','*','/','d'
public int left;// 左孩子
public int right;// 右孩子
public int father;// 爹地
public void init() {
value = 0;
symbol = '\0';
left = -1;
right = -1;
father = -1;
}
}
private static boolean isOperator(char c) {
if (c == '+' || c == '-' || c == '*' || c == '/') {
return true;
}
return false;
}
private static boolean isDigit(char c) {
if ((c <= '9' && c >= '0') || c == '.') {
return true;
}
return false;
}
// 用遞迴計算樹的值
private static double getNodeValue(MyTreeNode[] tree, int nodeNum)
throws Exception {
// 如果結點是數字,直接傳回值
if (tree[nodeNum].symbol == 'd') {
return tree[nodeNum].value;
}
// 如果結點是符號,則遞迴計算
if (tree[nodeNum].symbol == '+') {
return getNodeValue(tree, tree[nodeNum].left)
+ getNodeValue(tree, tree[nodeNum].right);
}
if (tree[nodeNum].symbol == '-') {
return getNodeValue(tree, tree[nodeNum].left)
- getNodeValue(tree, tree[nodeNum].right);
}
if (tree[nodeNum].symbol == '*') {
return getNodeValue(tree, tree[nodeNum].left)
* getNodeValue(tree, tree[nodeNum].right);
}
if (tree[nodeNum].symbol == '/') {
return getNodeValue(tree, tree[nodeNum].left)
/ getNodeValue(tree, tree[nodeNum].right);
}
throw new Exception("tree error");
}
// 計算逆波蘭運算式
public static double calculate(String str) {
double result = 0;
MyTreeNode tree[] = new MyTreeNode[MAX_NODE];
for (int i = 0; i < MAX_NODE; i++) {
tree[i] = new MyTreeNode();
tree[i].init();
}
int nowCount = 0;
int pointerTmp = -1;
try {
// 建立整棵二叉樹
// 注意,逆波蘭式解析起來應該是從右向左
for (int i = str.length() - 1; i >= 0; i--) {
if (isOperator(str.charAt(i)) || isDigit(str.charAt(i))) {
// 若是符號
if (isOperator(str.charAt(i))) {
tree[nowCount].symbol = str.charAt(i);
}
// 若是數字
else if (isDigit(str.charAt(i))) {
int numEnd = i;
while (isDigit(str.charAt(i))) {
i--;
if (i < 0) {
break;
}
}
i++;
tree[nowCount].value = Double.valueOf(str.substring(i,
numEnd + 1));
tree[nowCount].symbol = 'd';
}
// 現在開始的代碼為核心+關鍵
// 向上找到父結點,掛載當前結點,構建二叉樹
pointerTmp = nowCount - 1;
while (pointerTmp >= 0) {
// 因為數字一定在葉子結點上,因此忽略數字結點
// 優先查看找到的非葉子的右孩子,如果為空白,就認其為父
if (tree[pointerTmp].right < 0
&& tree[pointerTmp].symbol != 'd') {
tree[pointerTmp].right = nowCount;
tree[nowCount].father = pointerTmp;
break;
}
// 如果右孩子非空,就看左孩子,如果為空白,就認賊作父
if (tree[pointerTmp].left < 0
&& tree[pointerTmp].symbol != 'd') {
tree[pointerTmp].left = nowCount;
tree[nowCount].father = pointerTmp;
break;
}
// 如果都不為空白,繼續向上尋找。"我要我要找我爸爸,去到哪裡也要找我爸爸~~~"
pointerTmp = tree[pointerTmp].father;
}
// 如果找不到爹地,哼哼,那怎麼可能!難道是無性繁殖?
if (nowCount != 0 && pointerTmp < 0) {
throw new Exception("我靠,你就不能寫個正確的運算式阿");
}
nowCount++;
}
}
// 計算結果
result = getNodeValue(tree, 0);
} catch (Exception e) {
// 如果運算式錯誤,輸出提示
System.out.println("The next expression error!");
result = 0;
}
return result;
}
public static void main(String[] args) {
String str = "1 2 3 4 5*-6 + -*";
String str2 = "1.23 252.6 3 4.8 5* - * 6 + *";
String str3 = "1.23 252.6 3 4.8 5* - * 6 ++ *";// 這個運算式是錯的,輸出錯誤提示
String str4 = "1.23 252.6 3 4.8 5";// 這個運算式還是錯的,輸出錯誤提示
System.out.println(str + " = " + calculate(str));
System.out.println(str2 + " = " + calculate(str2));
System.out.println(str3 + " = " + calculate(str3));
System.out.println(str4 + " = " + calculate(str4));
}
}