数据结构(java语言描述)链栈的使用——表达式求值

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种表示形式。

  中缀表达式是将运算符放在两个操作数的中间;

  后缀表达式将运算符放在两个操作数之后;

  前缀表达式是将操作符放在两个操作数之前。

  后缀表达式中既无操作符的优先级又无括号的约束问题,英雌可以按后缀表达式中运算符出现的顺序进行计算求值。

原文地址:https://www.cnblogs.com/xleer/p/5302219.html