• 表达式求值


    因工作需要对表达式求值,借机巩固下基础知识,使用两个栈,一个存放操作数,一个存放算符。

    在表达式的开始和结尾分别放一个#,表示开始和结束。

    算符栈初始的时候有一个#算符,如果是计算1+2,这里会有一个疑问,1入栈后,读到算符+,
    (当前的算符)其优先级比 栈顶算符# 大,也就是栈顶算符优先级低,则需要把该算符入栈。
    下一个算符是#,其优先级比栈顶算符+的小,栈顶算符优先级大,则将两个操作数出栈和栈顶算符出栈,进行运算。

    如果计算表达式1+2+3*4。

    1入栈后,读到算符+,
    (当前的算符)其优先级比 栈顶算符# 大,也就是栈顶算符优先级低,则需要把该算符入栈。
    下一个算符是+,其优先级和栈顶算符优先级相等,这里会有一个疑问,根据则将栈顶算符出栈,并去取下一个字符。(错误)

    这里把栈顶的+出栈,当前算符+也没有入栈,栈顶算符变成了#。 +算符都没有了,可怎么办?

    读取下一个字符是3,操作数里面有1 2 3

    读取到*,比栈顶算符优先高,栈顶算符优先级低,则入栈。
    读取最后一个算符#,栈顶算符优先级高,则进行计算:3*4 。

    正确的运算过程是:

    1入栈后,读到算符+,
    (当前的算符)其优先级比 栈顶算符# 大,也就是栈顶算符优先级低,则需要把该算符入栈。
    下一个算符是+,其优先级和栈顶算符优先级相等,根据运算法则,同级别时,先左后右。应该将栈顶算符和两个操作数取出,进行计算,然后将当前字符和运算结果入栈。
    支持+-*/运算的代码:

    public class ExpCaculate
        {
            Stack<int> optd = new Stack<int>();
            Stack<char> optr = new Stack<char>();
           
            public void run(string exp)
            {
                optr.Push('#');
                Console.WriteLine("计算表达式:" + exp);
                for (int i = 0; i < exp.Length; i++)
                {
                    char ch = exp[i];
    
                    // 识别0-9数字
                    if (IsNumer(ch))
                    {
                        // 从表达式里面提取数字
                        StringBuilder d = new StringBuilder();
                        d.Append(ch);
                        for (int j = i+1; j < exp.Length; j++)
                        {
                            if (IsNumer(exp[j]))
                            {
                                d.Append(exp[j]);
                                i = j;
                            }
                            else
                            {
                                break;
                            }
                        }
    
                        int t = int.Parse(d.ToString());
                        optd.Push(t);
    
                    }
                    else if (IsOptr(ch))
                    {
                        switch (Percede(ch))
                        {
                            case ">": //当前算符优先级高, 栈顶算符优先级低
                                optr.Push(ch);
                                break;
                            case "<":
                            case "=":
                                int a = optd.Pop();
                                int b = optd.Pop();
                                char theta = optr.Pop();
                                int r = Caclulae(a, b, theta);
                                optd.Push(r);
                                optr.Push(ch);
                                break;
                            default:
                                break;
                        }
                    }
    
                }// end for
    
                optr.Pop();
    
                while (optr.Count > 1&&optd.Count>1)
                {
                    int a = optd.Pop();
                    int b = optd.Pop();
                    char theta = optr.Pop();
                    int r = Caclulae(a, b, theta);
                    optd.Push(r);
                }
                if (optd.Count == 1)
                {
                    Console.WriteLine("计算结果是:" + optd.Pop());
                    optr.Clear();
                    optd.Clear();
                }
                else
                {
                    Console.WriteLine("error :");
                }
    
            }
    
            private int Caclulae(int a, int b, char theta)
            {
                switch (theta){
                    case '+':
                        return a + b;
                    case '-':
                        return a - b;
                    case '*':
                        return a * b;
                    case '/':
                        return a / b;
                }
    
                return 0;
            }
    
            private string Percede(char ch)
            {
                if (optr.Count == 0)
                {
                    return "";
                }
                char top = optr.Peek();
                switch (top)
                {
                    case '+':
                    case '-':
                        if (ch == '*' || ch == '/')
                        {
                            return ">";
                        }
                        else if (ch == '+' || ch == '-')
                        {
                            return "=";
                        }
                        else
                        {
                            return "<";
                        }
                    case '*':
                    case '/':
                        if (ch == '*' || ch == '/')
                        {
                            return "=";
                        }
                        else if (ch == '+' || ch == '-')
                        {
                            return "<";
                        }
                        else
                        {
                            return "<";
                        }
                    case '#':
                        if (ch == '#')
                        {
                            return "=";
                        }
                        else
                        {
                            return ">";
                        }
                }
                return "=";
            }
    
            private bool IsOptr(char ch)
            {
                return ch == '+' || ch == '-' || ch == '*' || ch == '/'|| ch == '#';
            }
    
            public bool IsNumer(char ch)
            {
                return ch > 47 && ch < 58;
            }
    
        }
    

      

  • 相关阅读:
    Spring Boot (五): Redis缓存使用姿势盘点
    跟我学SpringCloud | 第二十章:Spring Cloud 之 okhttp
    Spring Boot (四): Druid 连接池密码加密与监控
    跟我学SpringCloud | 第十九章:Spring Cloud 组件 Docker 化
    跟我学SpringCloud | 第十八篇:微服务 Docker 化之基础环境
    Spring Boot (三): ORM 框架 JPA 与连接池 Hikari
    Spring Cloud Alibaba | Dubbo Spring Cloud 之 HTTP 实战
    Spring Cloud Alibaba | Dubbo 与 Spring Cloud 完美结合
    Spring Boot (二):模版引擎 Thymeleaf 渲染 Web 页面
    可以穿梭时空的实时计算框架——Flink对时间的处理
  • 原文地址:https://www.cnblogs.com/363546828/p/8757222.html
Copyright © 2020-2023  润新知