• C#数据结构与算法系列(十一):中缀表达式转后缀表达式


    1.具体步骤

    1)初始化两个栈:运算符栈s1和储存中间结果的栈s2;
    2)从左至右扫描中缀表达式;
    3)遇到操作数时,将其压s2;
    4)遇到运算符时,比较其与s1栈顶运算符的优先级:
         (1)如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
         (2)否则,若优先级比栈顶运算符的高,也将运算符压入s1;
         (3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;
    5)遇到括号时:
         (1)如果是左括号“(”,则直接压入s1
         (2)如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
    6)重复步骤2至5,直到表达式的最右边
    7)将s1中剩余的运算符依次弹出并压入s2
    8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

    2.思路分析

     3.代码实现

     /// <summary>
            /// 字符串转中缀表达式的List
            /// </summary>
            /// <param name="expression"></param>
            /// <returns></returns>
            public static List<string> ToInfixExpression(string expression)
            {
                List<string> list = new List<string>();
    
                int index = 0;
    
                string str = "";
    
                do
                {
    
                    //48-57ASCII码代表的是0-9 如果不是0-9直接入链表
                    if (expression[index] < 48 || expression[index] > 57)//ascii编码
                    {
                        list.Add("" + expression[index]);
    
                        index++;
                    }
                    else
                    {
                        str = "";
    
                        //多位数判断
                        while (index < expression.Length && expression[index] >= 48 && expression[index] <= 57)
                        {
    
                            str += expression[index];
    
                            index++;
                        }
    
                        list.Add(str);
                    }
    
                } while (index < expression.Length);
    
                return list;
            }
        /// <summary>
            /// 中缀转后缀
            /// </summary>
            /// <param name="expression"></param>
            /// <returns></returns>
            public static List<string> ParseSuffixExpression(List<string> expression)
            {
                //存储中间结果
                List<string> list = new List<string>();
                //符号栈
                Stack<string> stack = new Stack<string>();
    
                foreach (var item in expression)
                {
                    //多位数判断 如果是数字直接加入list
                    if (Regex.IsMatch(item, "\d+"))
                    {
                        list.Add(item);
                    }
                    //如果是左括号,直接入符号栈
                    else if (item.Equals("("))
                    {
                        stack.Push(item);
                    }
                    //如果是右括号
                    else if (item.Equals(")"))
                    {
                        //依次弹出stack栈顶的运算符,并存入list,直到遇到左括号为止
                        while (!stack.Peek().Equals("("))
                        {                        
                            list.Add(stack.Pop());
                        }
                        //将(也出栈
                        stack.Pop();
                    }
                    //如果是*/+-
                    else
                    {
                        //循环判断item的优先级小于或者等于stack栈顶运算符,将stack栈顶的运算符出栈并加入到list中
                        while (stack.Count != 0 && Operation.GetValue(stack.Peek()) >= Operation.GetValue(item))
                        {
                            list.Add(stack.Pop());
                        }
                        //将item入栈
                        stack.Push(item);
                    }
                }
    
                //将stack剩余的运算符依次入list
                while (stack.Count!=0)
                {
                    list.Add(stack.Pop());
                }
    
                return list;
            }
        public class Operation
        {
            private static int ADD = 1;
            private static int SUB = 1;
            private static int MUL = 2;
            private static int DIV = 2;
    
            public static int GetValue(string operation)
            {
                int result = 0;
    
                switch (operation)
                {
                    case "+":
                        result = ADD;
                        break;
                    case "-":
                        result = SUB;
                        break;
                    case "*":
                        result = MUL;
                        break;
                    case "/":
                        result = DIV;
                        break;
                    default:
                       // Console.WriteLine("不存在该运算符");
                        break;
                }
    
                return result;
            }
        }
            /// <summary>
            /// 计算
            /// </summary>
            /// <param name="list"></param>
            /// <returns></returns>
            public static int Calculate(List<string> list)
            {
                //创建栈
                Stack<string> stack = new Stack<string>();
    
                //循环遍历
                list.ForEach(item =>
                {
                    //正则表达式判断是否是数字,匹配的是多位数
                    if (Regex.IsMatch(item,"\d+"))
                    {
                        //如果是数字直接入栈
                        stack.Push(item);
                    }
                    //如果是操作符
                    else
                    {
                        //出栈两个数字,并运算,再入栈
                        int num1 =int.Parse(stack.Pop());
    
                        int num2 = int.Parse(stack.Pop());
    
                        int result = 0;
    
                        if(item.Equals("+"))
                        {
                            result = num2 + num1;
                        }
                        else if(item.Equals("*"))
                        {
                            result = num2 * num1;
                        }
                        else if(item.Equals("/"))
                        {
                            result = num2 / num1;
                        }
                        else if (item.Equals("-"))
                        {
                            result = num2 - num1;
                        }
                        else
                        {
                            throw new Exception("无法识别符号");
                        }
    
                        stack.Push(""+result);
                    }
                });
    
                //最后把stack中数据返回
                return int.Parse(stack.Pop());
            }
        public class ReversePolandTransformation
        {
    
            public static void Test()
            {
                string expression = "1+((2+3)*4)-5";
    
                //将字符串转换成List
                List<string> infixExpression = ToInfixExpression(expression);
    
                string str = "";
    
                infixExpression.ForEach(item =>
                {
                    str = str + item + ",";
                });
    
                Console.WriteLine("中缀表达式对应的List:"+str);
    
                str = "";
    
                //将中缀表达式转换成后缀表达式
                List<string> suffixExpression = ParseSuffixExpression(infixExpression);
    
                suffixExpression.ForEach(item =>
                {
                    str = str + item + ",";
                });
    
                Console.WriteLine("
    后缀表达式对应的List:"+str);
    
                //结果计算
                int result =PolandNotation.Calculate(suffixExpression);
    
                Console.WriteLine($"
    {expression}={result}");
            }
       }

  • 相关阅读:
    Leetcode 233 Number of Digit One
    获取各种常见形状的位图
    关于编程
    LintCode-第k大元素
    基于IBM Bluemix的数据缓存应用实例
    LeakCanary:简单粗暴的内存泄漏检測工具
    MFC,C++,VC++,VS2010 之间究竟是什么关系
    我对高考考场制度(比方是否同意迟到、忘带考证、上厕所)优化的点滴思考,不一定非常有道理
    ural 1989(树状数组+多项式hash)
    TI C66x DSP 系统events及其应用
  • 原文地址:https://www.cnblogs.com/vic-tory/p/13176657.html
Copyright © 2020-2023  润新知