1.操作思想
- 首先将表达式转换为后缀表达式的形式;
- 然后利用链栈存储后缀表达式,利用栈的入栈、出栈计算表达式。
2.把中缀表达式转换为后缀表达式
- 初始化一个运算符栈;
- 从左到右读取字符串;
- 左括号(入栈;1
- 字符串为运算符时:2
- 运算符栈为空则入栈;
- 该运算符优先级高于栈顶运算符时,入栈;否则弹出栈顶运算符写入后缀表达式然后该运算符入栈(栈顶运算优先级小于入栈的运算符);
- 字符是右括号)时,反复抛出栈顶元素入后缀表达式,直到栈顶为左括号,然后扔掉左括号和右括号。3
- 若读取完毕则将栈中的运算符送往后缀表达式。4
表达式中的优先级为:
_______________________________________
— () — +- — */% — ^ ——
—————————————————————————
— 0 — 1 — 2 — 3 —
_______________________________________
代码:
public String TransAf(String x)throws Exception{
Linkstack st=new Linkstack();//初始化运算符栈
String postString=new String();//初始化String类用于存放转换后的后缀表达式
for(int i=0;x!=null&&i<x.length();i++){//遍历整个中缀表达式
char c=x.charAt(i);//获取中缀表达式中当前的字符
/*********分四种情况将操作符入栈**********/
if(' '!=c)
{//判断该操作符不是结尾
if(isopenOperator(c))
{//该操作符是左括号则入栈1
st.push(c);
}//open
else if(iscloseOperator(c))
{//此时操作符为右括号2
Character ac=(Character) st.pop();//运算符栈做出栈操作
while(!isopenOperator(c))
{//不为左括号时则加到后缀表达式中
postString=postString.concat(String.valueOf(ac));
ac=(Character)st.pop();
}
}else if(isOperator(c))
{//此时为运算符3
if(!st.isEmpty())
{//若运算符栈不为空,弹出栈顶元素做优先级比较
Character ac=(Character)st.pop();
while(ac != null&&priority(ac.charValue())>=priority(c)){//栈顶元素优先级高,则出栈操作
postString=postString.concat(String.valueOf(ac));//把栈抛出的元素加到后缀表达式中
ac=(Character)st.pop();//继续做出栈操作
}
if(ac!=null)
{//如果不满足while,即抛出的运算符优先级低于此时的运算符,
st.push(ac);//先把最后一次抛出的运算符入栈
}
}//if(!st.isEmpty()){
st.push(c);//然后把遍历的该运算符入栈
}
else{//遍历的符号为操作数,则直接加到后缀表达式中4
postString=postString.concat(String.valueOf(c));
}//4中情况分析完毕
}//if(' '!=c)
}//for
while(!st.isEmpty())//若中缀表达式以遍历完,此时操作符栈依然不为空
postString=postString.concat(String.valueOf(st.pop()));//直接把栈中的元素一次出栈加到后缀表达式中
return postString;//返回后缀表达式
}
/****************************对后缀表达式进行计算**********************************/
public double numCalculate(String postString)throws Exception{
Linkstack st=new Linkstack();
for(int i=0;postString!=null&&i<postString.length();i++)//遍历整个postString后缀表达式
{
char c=postString.charAt(i);
if(isOperator(c))//判断每个字符是否是运算符
{
double d2=Double.valueOf(st.pop().toString());
double d1=Double.valueOf(st.pop().toString());
double d3=0;
if('+'==c)//判断是哪种运算符并进行计算
{
d3=d1+d2;
}else if('-'==c)
{
d3=d1-d2;
}else if('*'==c)
{
d3=d1*d2;
}else if('/'==c)
{
d3=d1/d2;
}else if('^'==c)
{
d3=Math.pow(d1, d2);
}else if('%'==c)
{
d3=d1%d2;
}
st.push(d3);//将计算后的结果入栈
}else//如果postString中的字符不是运算符,则执行入栈操作
{
st.push(c);
}
}
return (Double) st.pop();//最终,遍历完后缀表达式,在栈中取出最终的计算结果
}
/*********************判断字符是否是运算符*************************/
public boolean isOperator(char c){
if('+'==c||'-'==c||'*'==c||'/'==c||'^'==c||'%'==c)
return true;
else
return false;
}
/*********************判断字符是否是左括号*************************/
public boolean isopenOperator(char c){
return '('==c;
}
/*********************判断字符是否是右括号*************************/
public boolean iscloseOperator(char c){
return ')'==c;
}
/*********************判断字符的优先级*************************/
public int priority(char c){
if(c=='^')
return 3;
else if(c=='*'||c=='/'||c=='%')
return 2;
else if(c=='+'||c=='-')
return 1;
else
return 0;
}
主函数:
public static void main(String[] args)throws Exception{
CountB con=new CountB();
String postString=con.TransAf("(1+2)*(5-2)/2^2+5%3");
System.out.println("表达式的结果为:"+con.numCalculate(postString));
}
注:表达式一般有中缀表达式、后缀表达式和前缀表达式3种表示形式。
中缀表达式是将运算符放在两个操作数的中间;
后缀表达式将运算符放在两个操作数之后;
前缀表达式是将操作符放在两个操作数之前。
后缀表达式中既无操作符的优先级又无括号的约束问题,英雌可以按后缀表达式中运算符出现的顺序进行计算求值。