棧應用1:算術表示式求值
阿新 • • 發佈:2019-01-06
主要要理解字尾表示式是怎麼由中綴表示式得來的
多寫寫算術表示式實際是怎麼運算的(順序)
字尾表示式是怎麼運算的
使用(來提升運算子的優先順序
運算子總是跟在第二個操作元的後面
package Evaluation;
import java.util.Scanner;
class Stack
{
final int MaxSize = 10;
char[] data = new char[MaxSize];
int top;
public Stack()
{
top = -1;
}
}
// 運算子優先順序
class Priority
{
final int MaxOp = 7;
final char[] ch = { '=', '(', '+', '-', '*', '/', ')' }; // 運算子
final int[] lpri = { 0, 1, 3, 3, 5, 5, 6 }; // 左運算子優先順序
final int[] rpri = { 0, 6, 2, 2, 4, 4, 1 }; // 右運算子優先順序
}
public class Main
{
public static void main(String args[])
{
Scanner cin = new Scanner(System.in);
String exp = cin.nextLine();
exp = exp + "\0" ;
char postexp[] = new char[30];
trans(exp, postexp);
System.out.println("中綴表示式:" + exp);
int i = 0;
char ch = postexp[i];
while (ch != '\0')
{
System.out.print(ch);
ch = postexp[++i];
}
System.out.println();
System.out.println("表示式的值:" + compvalue(postexp));
}
// 判斷是否為運算子
public static boolean IsOp(char ch)
{
Priority pri = new Priority();
for (int i = 0; i < pri.MaxOp; i++)
if (ch == pri.ch[i])
return true;
return false;
}
// 求左運算子op的優先順序
public static int leftpri(char op)
{
Priority pri = new Priority();
for (int i = 0; i < pri.MaxOp; i++)
if (op == pri.ch[i])
return pri.lpri[i];
return 0;
}
// 求右運算子op的優先順序
public static int rightpri(char op)
{
Priority pri = new Priority();
for (int i = 0; i < pri.MaxOp; i++)
if (op == pri.ch[i])
return pri.rpri[i];
return 0;
}
// 返回op1與op2運算子優先順序的比較結果
public static int Precede(char op1, char op2)
{
if (leftpri(op1) == rightpri(op2))
return 0;
else if (leftpri(op1) < rightpri(op2))
return -1;
else
return 1;
}
// 將算術表示式exp轉換成字尾表示式postexp
public static void trans(String exp, char[] postexp)
{
int i = 0;
Stack Sop = new Stack();
Sop.top++;
Sop.data[Sop.top] = '='; // 將'='入棧
int n = 0;
char ch = exp.charAt(n);
while (ch != '\0')
{
if (!IsOp(ch))
{
while (ch >= '0' && ch <= '9')
{
postexp[i++] = ch;
ch = exp.charAt(++n);
}
postexp[i++] = '#';
}
else
{
switch (Precede(Sop.data[Sop.top], ch))
{
case -1: // 棧頂運算子優先順序低
Sop.data[++Sop.top] = ch;
ch = exp.charAt(++n); // 繼續掃描其他字元
break;
case 0: // 只有括號滿足這種情況
Sop.top--; // 退棧
ch = exp.charAt(++n); // 繼續掃描其他字元
break;
case 1:
postexp[i++] = Sop.data[Sop.top--]; // 退棧並輸出到postexp中
break;
}
}
}
while (Sop.data[Sop.top] != '=')
{
postexp[i++] = Sop.data[Sop.top--];
}
postexp[i] = '\0';
}
// 計算字尾算數表示式
public static float compvalue(char[] postexp)
{
Stack st = new Stack();
float d, a, b, c;
int i = 0;
char ch = postexp[i];
while (ch != '\0')
{
switch (ch)
{
case '+':
a = st.data[st.top--];
b = st.data[st.top--];
c = b + a;
st.data[++st.top] = (char) c;
break;
case '-':
a = st.data[st.top--];
b = st.data[st.top--];
c = b - a;
st.data[++st.top] = (char) c;
break;
case '*':
a = st.data[st.top--];
b = st.data[st.top--];
c = b * a;
st.data[++st.top] = (char) c;
break;
case '/':
a = st.data[st.top--];
b = st.data[st.top--];
if (a != 0)
{
c = b / a;
st.data[++st.top] = (char) c;
} else
{
System.out.println("除0錯誤");
}
break;
default:
d = 0;
while (ch >= '0' && ch <= '9')
{
d = 10 * d + (ch - '0');
ch = postexp[++i];
}
st.data[++st.top] = (char) d;
break;
}
ch = postexp[++i];
}
return st.data[st.top];
}
}
輸入:
1+3*2-1
輸出:
中綴表示式:1+3*2-1
1#3#2#*+1#-
表示式的值:6.0
輸入:
(56-20)/(4+2)
輸出:
中綴表示式:(56-20)/(4+2)
56#20#-4#2#+/
表示式的值:6.0