• 数据结构(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种表示形式。

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

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

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

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

  • 相关阅读:
    IE6实现PNG图片透明
    xp精简版 安装IIS
    CSS 多浏览器兼容又一方案
    mysql忘记root帐号和密码,修改root用户名和密码解决方案
    jQuery函数学习
    建立标准化的声明DOCTYPE和head
    关于Microsoft.XMLDOM 与Microsoft.XMLHTTP
    伪静态技术(较完整篇)
    关于document.cookie的使用
    鼠标滚动缩放图片效果
  • 原文地址:https://www.cnblogs.com/xleer/p/5302219.html
Copyright © 2020-2023  润新知