算法:逆波兰表达式求值

背景

运算符求值的一种常见做法是:先将中缀表达式转换为后缀表达式(逆波兰表达式),然后再对后缀表达式求值,之所以这么做的原因是后缀表达式的求值非常简单。

代码实现

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 
  7 namespace DataStuctureStudy.Stacks
  8 {
  9     public static class Calculator
 10     {
 11         private static readonly Dictionary<string, int> _operators = new Dictionary<string, int>
 12         {
 13             { "+", 1 },
 14             { "-", 1 },
 15             { "*", 2 },
 16             { "/", 2 },
 17             { "%", 2 }
 18         };
 19 
 20         public static void Test(string expression)
 21         {
 22             var postfixTokens = GetPostfixTokens(GetTokens(expression));
 23             Console.WriteLine(expression + " = " + Calculate(postfixTokens));
 24         }
 25 
 26         private static int Calculate(IEnumerable<string> postfixTokens)
 27         {
 28             var stack = new Stack<int>();
 29 
 30             foreach (var item in postfixTokens)
 31             {
 32                 if (IsOperator(item))
 33                 {
 34                     switch (item)
 35                     {
 36                         case "+":
 37                             stack.Push(stack.Pop() + stack.Pop());
 38                             break;
 39                         case "-":
 40                             stack.Push(stack.Pop() - stack.Pop());
 41                             break;
 42                         case "*":
 43                             stack.Push(stack.Pop() * stack.Pop());
 44                             break;
 45                         case "/":
 46                             stack.Push(stack.Pop() / stack.Pop());
 47                             break;
 48                         case "%":
 49                             stack.Push(stack.Pop() % stack.Pop());
 50                             break;
 51                     }
 52                 }
 53                 else
 54                 {
 55                     stack.Push(int.Parse(item));
 56                 }
 57             }
 58 
 59             return stack.Pop();
 60         }
 61 
 62         private static IEnumerable<string> GetPostfixTokens(IEnumerable<string> infixTokens)
 63         {
 64             var postfixTokens = new List<string>();
 65             var stack = new Stack<string>();
 66 
 67             foreach (var token in infixTokens)
 68             {
 69                 if (IsOperator(token))
 70                 {
 71                     var curOperator = token;
 72 
 73                     if (stack.Count == 0)
 74                     {
 75                         stack.Push(curOperator);
 76                     }
 77                     else
 78                     {
 79                         while (stack.Count != 0)
 80                         {
 81                             var popOperator = stack.Pop();
 82                             if (popOperator == "(")
 83                             {
 84                                 stack.Push(popOperator);
 85                                 break;
 86                             }
 87 
 88                             if (_operators[curOperator] <= _operators[popOperator])
 89                             {
 90                                 postfixTokens.Add(popOperator);
 91                             }
 92                             else
 93                             {
 94                                 stack.Push(popOperator);
 95                                 break;
 96                             }
 97                         }
 98 
 99                         stack.Push(curOperator);
100                     }
101                 }
102                 else if (token == "(")
103                 {
104                     stack.Push(token);
105                 }
106                 else if (token == ")")
107                 {
108                     var popOperator = stack.Pop();
109                     while (popOperator != "(")
110                     {
111                         postfixTokens.Add(popOperator);
112                         popOperator = stack.Pop();
113                     }
114                 }
115                 else
116                 {
117                     postfixTokens.Add(token);
118                 }
119             }
120 
121             while (stack.Count != 0)
122             {
123                 postfixTokens.Add(stack.Pop());
124             }
125 
126             return postfixTokens;
127         }
128 
129         private static IEnumerable<string> GetTokens(string expression)
130         {
131             var tokens = new List<string>();
132             var sb = new StringBuilder();
133 
134             foreach (var item in expression)
135             {
136                 if (IsOperator(item.ToString()) || item == '(' || item == ')')
137                 {
138                     if (sb.Length > 0)
139                     {
140                         tokens.Add(sb.ToString());
141                         sb.Clear();
142                     }
143 
144                     tokens.Add(item.ToString());
145                 }
146                 else
147                 {
148                     sb.Append(item);
149                 }
150             }
151 
152             return tokens;
153         }
154 
155         private static bool IsOperator(string token)
156         {
157             return _operators.ContainsKey(token);
158         }
159     }
160 }
原文地址:https://www.cnblogs.com/happyframework/p/3485451.html