您的位置:首页 > 其它

算法:逆波兰表达式求值

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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: