表达式求值
中缀表达式到后缀表达式的转换
要把表达式从中缀表达式的形式转换成用后缀表示法表示的等价表达式,必须了解操作符的优先级和结合性。优先级或者说操作符的强度决定求值顺序;优先级高的操作符比优先级低的操作符先求值。 如果所有操作符优先级一样,那么求值顺序就取决于它们的结合性。操作符的结合性定义了相同优先级操作符组合的顺序(从右至左或从左至右)。
转换过程包括用下面的算法读入中缀表达式的操作数、操作符和括号:
1. 初始化一个空堆栈,将结果字符串变量置空。
2. 从左到右读入中缀表达式,每次一个字符。
3. 如果字符是操作数,将它添加到结果字符串。
4. 如果字符是个操作符,弹出(pop)操作符,直至遇见开括号(opening parenthesis)、优先级较低的操作符或者同一优先级的右结合符号。把这个操作符压 入(push)堆栈。
5. 如果字符是个开括号,把它压入堆栈。
6. 如果字符是个闭括号(closing parenthesis),在遇见开括号前,弹出所有操作符(弹出开括号),然后把它们添加到结果字符串。
7. 如果到达输入字符串的末尾,弹出所有操作符并添加到结果字符串。
后缀表达式求值
对后缀表达式求值比直接对中缀表达式求值简单。在后缀表达式中,不需要括号,而且操作符的优先级也不再起作用了。您可以用如下算法对后缀表达式求值:
1. 初始化一个空堆栈
2. 从左到右读入后缀表达式
3. 如果字符是一个操作数,把它压入堆栈。
4. 如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
5. 到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ExpressionValue { class Program { public static Boolean IsNumber(String n) { Int32 temp; return Int32.TryParse(n, out temp); } // Get the priority of the operator, just for + - * / public static Int32 GetPriority(Char op) { switch (op) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } // Convert to Suffix Format public static List<String> ConvertToRearFormat(String str) { str = str.Replace(" ", ""); List<String> list = new List<String>(); Int32 start = 0; for (Int32 i = 0; i < str.Length; i++) { if (!Char.IsDigit(str[i])) { if (!(i - 1 < 0 || i == start)) { list.Add(str.Substring(start, i - start)); } list.Add(str[i].ToString()); start = i + 1; continue; } if (Char.IsDigit(str[i]) && i == str.Length - 1) { list.Add(str.Substring(start)); } } Stack<Char> stack = new Stack<Char>(); List<String> res = new List<String>(); foreach (String s in list) { if (IsNumber(s)) { res.Add(s); } else if (s == "(") { stack.Push(s[0]); } else if (s == ")") { while (stack.Count != 0) { if (stack.Peek() == '(') { stack.Pop(); break; } res.Add(stack.Pop().ToString()); } } else { while(stack.Count != 0 && stack.Peek() != '(' && GetPriority(stack.Peek()) > GetPriority(Convert.ToChar(s))) { res.Add(stack.Pop().ToString()); } stack.Push(s[0]); } } while (stack.Count != 0) { res.Add(stack.Pop().ToString()); } return res; } //Get the value of a expression which is expressed in suffix format public static Int32 GetValue(List<String> list) { Stack<String> temp = new Stack<String>(); foreach (String s in list) { temp.Push(s); if (!IsNumber(s)) { temp.Pop(); String p1 = temp.Pop(); String p2 = temp.Pop(); temp.Push(Calculate(p1, s[0], p2).ToString()); } } return Convert.ToInt32(temp.Pop()); } //Calculate the value of p1 op p2. public static Int32 Calculate(String s1, Char op, String s2) { Int32 p1 = Convert.ToInt32(s1); Int32 p2 = Convert.ToInt32(s2); switch (op) { case '+': return p1 + p2; case '-': return p1 - p2; case '*': return p1 * p2; case '/': return p1 / p2; default: return 0; } } public static void ValueofExpression(String str) { str = str.Trim().Replace(" ", ""); if (str.IndexOf(@"/0") > -1) { Console.WriteLine("the divisor cannot be zero"); return; } Char[] cs = str.ToCharArray(); Int32 openN = (from c in cs where c == '(' select c).Count<Char>(); Int32 closeN = (from c in cs where c == ')' select c).Count<Char>(); if (openN != closeN) { Console.WriteLine("Format is wrong!(because parentheses)"); return; } List<String> list = new List<String>(); list = ConvertToRearFormat(str); Int32 numofParas = list.FindAll((string s) => { if (IsNumber(s)) return true; else return false; }).Count; Int32 numofOps = list.FindAll((String s) => { if (s[0] == '+' || s[0] == '-' || s[0] == '*' || s[0] == '/') return true; else return false; }).Count; if (numofParas == numofOps + 1) { Console.WriteLine(GetValue(list)); } else { Console.WriteLine("Error"); } } static void Main(string[] args) { ValueofExpression("1 + (2 * 3 +5 / 0)"); //the divisor cannot be zero ValueofExpression("1 + (2 * 3 + 5 )"); //12 ValueofExpression("(2 * 2 + 4) * 2"); //16 ValueofExpression("(2 * 2 + 4 * 2"); //Format is wrong!(because parentheses) } } }
作者:Peter
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.