算法:逆波兰表达式求值
2013-12-20 20:35
525 查看
背景
运算符求值的一种常见做法是:先将中缀表达式转换为后缀表达式(逆波兰表达式),然后再对后缀表达式求值,之所以这么做的原因是后缀表达式的求值非常简单。代码实现
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DataStuctureStudy.Stacks { public static class Calculator { private static readonly Dictionary<string, int> _operators = new Dictionary<string, int> { { "+", 1 }, { "-", 1 }, { "*", 2 }, { "/", 2 }, { "%", 2 } }; public static void Test(string expression) { var postfixTokens = GetPostfixTokens(GetTokens(expression)); Console.WriteLine(expression + " = " + Calculate(postfixTokens)); } private static int Calculate(IEnumerable<string> postfixTokens) { var stack = new Stack<int>(); foreach (var item in postfixTokens) { if (IsOperator(item)) { switch (item) { case "+": stack.Push(stack.Pop() + stack.Pop()); break; case "-": stack.Push(stack.Pop() - stack.Pop()); break; case "*": stack.Push(stack.Pop() * stack.Pop()); break; case "/": stack.Push(stack.Pop() / stack.Pop()); break; case "%": stack.Push(stack.Pop() % stack.Pop()); break; } } else { stack.Push(int.Parse(item)); } } return stack.Pop(); } private static IEnumerable<string> GetPostfixTokens(IEnumerable<string> infixTokens) { var postfixTokens = new List<string>(); var stack = new Stack<string>(); foreach (var token in infixTokens) { if (IsOperator(token)) { var curOperator = token; if (stack.Count == 0) { stack.Push(curOperator); } else { while (stack.Count != 0) { var popOperator = stack.Pop(); if (popOperator == "(") { stack.Push(popOperator); break; } if (_operators[curOperator] <= _operators[popOperator]) { postfixTokens.Add(popOperator); } else { stack.Push(popOperator); break; } } stack.Push(curOperator); } } else if (token == "(") { stack.Push(token); } else if (token == ")") { var popOperator = stack.Pop(); while (popOperator != "(") { postfixTokens.Add(popOperator); popOperator = stack.Pop(); } } else { postfixTokens.Add(token); } } while (stack.Count != 0) { postfixTokens.Add(stack.Pop()); } return postfixTokens; } private static IEnumerable<string> GetTokens(string expression) { var tokens = new List<string>(); var sb = new StringBuilder(); foreach (var item in expression) { if (IsOperator(item.ToString()) || item == '(' || item == ')') { if (sb.Length > 0) { tokens.Add(sb.ToString()); sb.Clear(); } tokens.Add(item.ToString()); } else { sb.Append(item); } } return tokens; } private static bool IsOperator(string token) { return _operators.ContainsKey(token); } } }
相关文章推荐
- 【算法】表达式求值--逆波兰算法介绍
- 算法-波兰表达式求值(递归)
- 逆波兰式与表达式求值
- Dijkstra的双栈算数表达式求值算法
- 从键盘上输入一个后缀表达式,试编写算法计算表达式的值。规定:逆波兰表达式的长度不超过一行,以$符作为输入结束,操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。例如:234 34+2*$。
- 调度场算法与逆波兰表达式
- 逆波兰表达式求值
- 424. 逆波兰表达式求值 --栈
- 经典算法-算术表达式求值
- 基于逆波兰表达式的公式解析器-算法和思路(一)
- 逆波兰表达式算法
- 算法学习-逆波兰表达式RPN
- 逆波兰表达式求值
- 逆波兰(Reverse Polish Notation)四则运算表达式求值 《大话数据结构》
- 逆波兰表达式求值
- 我就给一个PHP逆波兰表达式的算法吧---工资计算专用
- 基于逆波兰表达式的公式解析器-算法和思路(二)
- 经典算法-算术表达式求值
- 后缀表达式(逆波兰表达式),并求值(可求浮点、负数与大于10的数),C++实现
- 【Algorithm】算术表达式求值------逆波兰RPN