資料結構——字尾表示式
阿新 • • 發佈:2019-01-11
一、需要自定義的優先順序
package com_1.constant; //運算子自定義的優先順序 public class Constant { public static final int PRI_ERROR = -1; //棧外左括號 public static final int PRI_LEFT_OUT = 1; //棧內乘 public static final int PRI_MULTY_IN = 2; //棧內除 public static final int PRI_DIV_IN = 2; //棧外乘 public static final int PRI_MULTY_OUT = 3; //棧外除 public static final int PRI_DIV_OUT = 3; //棧內加 public static final int PRI_PLUS_IN = 4; //棧內減 public static final int PRI_SUB_IN = 4; //棧外加 public static final int PRI_PLUS_OUT = 5; //棧外減 public static final int PRI_SUB_OUT = 5; //棧內左括號 public static final int PRI_LEFT_IN = 10; //棧外右括號 public static final int PRI_RIGHT_OUT = 10; }
//得到當前運算子的優先順序 public int getPri(char oper,boolean inStack){ int pri = Constant.PRI_ERROR; //在棧內 if(inStack){ switch (oper){ case '+': pri = Constant.PRI_PLUS_IN; break; case '-': pri = Constant.PRI_SUB_IN; break; case '*': pri = Constant.PRI_MULTY_IN; break; case '/': pri = Constant.PRI_DIV_IN; break; case '(': pri = Constant.PRI_LEFT_IN; break; default: pri = Constant.PRI_ERROR; break; } } //棧外 else{ switch (oper){ case '+': pri = Constant.PRI_PLUS_OUT; break; case '-': pri = Constant.PRI_SUB_OUT; break; case '*': pri = Constant.PRI_MULTY_OUT; break; case '/': pri = Constant.PRI_DIV_OUT; break; case '(': pri = Constant.PRI_LEFT_OUT; break; case ')': pri = Constant.PRI_RIGHT_OUT; break; default: pri = Constant.PRI_ERROR; break; } } return pri; }
二、中綴表示式到字尾表示式的轉化
*判斷數字字元
Character.isDigit(strMid.charAt(i))
//中綴表示式轉為字尾表示式 public void strMidToLast(String strMid,char[] strLast){ //棧 char[] stack = new char[strMid.length()];//棧的大小 int top = 0;//棧頂指標 //strMid下標 int i = 0; //strLast下標 int j = 0; //當前棧內運算子的優先順序 int pri_in = Constant.PRI_ERROR; //當前棧外運算子的優先順序 int pri_out = Constant.PRI_ERROR; //遍歷中綴表示式 while(i != strMid.length()){ //是數字——存入字尾表示式 if(Character.isDigit(strMid.charAt(i))){ strLast[j] = strMid.charAt(i); i ++; j ++; } //是運算子——進行棧的操作 else{ //棧空——直接進棧 if(top == 0){ stack[top ++] = strMid.charAt(i); i ++; } //棧不為空——比較優先順序 else{ //棧內 pri_in = getPri(stack[top - 1],true); //棧外 pri_out = getPri(strMid.charAt(i),false); //棧外優先順序高——入棧 if(pri_out < pri_in){ stack[top ++] = strMid.charAt(i); i ++; } //棧內優先順序高——出棧,並存入字尾表示式 else if(pri_in < pri_out){ strLast[j ++] = stack[top - 1]; top --; } //優先順序相等——括號匹配,出棧不存入,i往後走 else{ top --; i ++; } } } } //遍歷結束,跳出迴圈,如果棧不為空,將運算子依次出棧並存入字尾表示式 while(top != 0){ strLast[j ++] = stack[-- top]; } }
三、根據字尾表示式進行計算
//兩個數字運算
public int getResult(int a,int b,char oper){
int result = 0;
switch (oper){
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
}
return -1;
}
/*
根據字尾表示式計算結果
遍歷字尾表示式
將數字入棧。碰到運算子,出棧兩次,進行運算,並將運算結果再入棧
*/
public int arithmetic(char[] strLast){
//棧
int[] stack = new int[strLast.length];
int top = 0;
//字尾表示式下標
int i = 0;
//兩個運算元
int num1 = 0;
int num2 = 0;
//運算結果
int result = 0;
//字尾表示式遍歷
while(i != strLast.length){
//是數字——入棧
if(Character.isDigit(strLast[i])){
//先將當前字元轉化為int型別
String str1 = Character.toString(strLast[i]);
stack[top ++] = Integer.parseInt(str1);
}
//空格或預設值
else if(strLast[i] == ' ' || strLast[i] == '\u0000'){
}
//運算子——出棧兩次,進行運算並將結果入棧
else{
num1 = stack[-- top];//右運算元
num2 = stack[-- top];//左運算元
char oper = strLast[i];
//進行運算
result = getResult(num2,num1,oper);
//結果再次入棧
stack[top ++] = result;
}
i ++;
}
return result;
}