我在上一篇中简单概述了逆波兰表达式的用途,中缀表达式转换逆波兰表达式的标准算法,还有逆波兰表达式的计算方法。这一篇,我将给出中缀表达式转换逆波兰表达式时各运算符的运算级别。
运算符的运算级别即方程式运算的先后级别,如下:
运算符 | 级别 |
空格 | 0 |
) | 1 |
( | 2 |
+,- | 3 |
*,/ | 4 |
运算对象 | -1 |
我现在给出中缀表达式转换逆波兰表达式的C#源代码,该代码在.net2005运行通过。由于时间原因部分代码未作优化,希望有兴趣的朋友能请给我提出更好的建议。
[Serializable]
/// <summary>
/// 操作符结构
/// </summary>
private struct Operator
{
public string OperatorStack;
public int Level;
public Operator(string OperatorStack, int Level)
{
this.OperatorStack = OperatorStack;
this.Level = Level;
}
}
/// <summary>
/// 操作符运算级别
/// </summary>
/// <param name="strOperator">操作符</param>
/// <returns>操作运算符,空格返回0,出错返回-1</returns>
private int OperatorLevel(string strOperator)
{
switch (strOperator)
{
case "+":
return 3;
case "-":
goto case "+";
case "*":
return 4;
case "/":
goto case "*";
case "(":
return 2;
case ")":
return 1;
case " ":
return 0;
default:
return -1;
}
}
/// <summary>
/// 将中缀表达式转换为逆波兰表达式
/// </summary>
/// <param name="Expression">标准中缀表达式</param>
/// <returns>标准逆波兰表达式</returns>
public string RpnExpression(string Expression)
{
try
{
//加入结束标记
string strExpression = Expression + "#";
//定义出栈和入栈堆栈
string[] strNum = Expression.Split(new char[] { '+', '-', '*', '/', '(', ')' });
int intNum = strNum.GetLength(0);
//操作运算符堆栈
Stack oper = new Stack();
//定义输出堆栈
Stack output = new Stack();
//定义前缀表达式字符读取指针
int i = 0;
//定义当前读取数字数组指针
int n = 0;
//定义操作运算符级别函数
Operator op=new Operator();
//输出堆栈的大小
int intStackCount=0;
//从左到右读取前缀表达式
while (i < strExpression.Length)
{
//读取一个字符
string strChar = strExpression.Substring(i, 1);
if (strChar != "#")
{
//取字符的运算级别
int intLevel = this.OperatorLevel(strChar);
if (intLevel == 0)
//遇空格读取下一字符
{
i++;
}
else if (intLevel == -1)
//数字直接推入输出堆栈
{
for (int m = n; m < strNum.GetLength(0); m++)
{
if (strNum[m] != "")
{
//移动数组指针
n = m + 1;
//将数字直接推入堆栈
output.Push(strNum[m]);
//移动字符串读取指针
i = i + strNum[m].Length;
break;
}
}
}
else //操作字符根据运算字符级别推入运算符堆栈
{
if (oper.Count == 0)
{
//运算符堆栈为空,直接推入堆栈
oper.Push(new Operator(strChar, intLevel));
//移动字符读取指针
i++;
}
else
{
op = (Operator)oper.Peek();
if (intLevel > op.Level || intLevel == 2)
{
//运算字符比运算符堆栈最后的级别高或者运算符为'('直接推入运算符堆栈
oper.Push(new Operator(strChar, intLevel));
//移动字符读取指针
i++;
}
else
{
//运算字符不高于运算符堆栈最后的级别,则将运算符堆栈出栈,直到比其高为止
intStackCount = oper.Count;
for (int m = 0; m < intStackCount; m++)
{
op = (Operator)oper.Peek();
if (op.Level >= intLevel)
{
//将操作符出栈并压入输入堆栈
output.Push(op.OperatorStack);
int l = op.Level;
oper.Pop();
if (l == 2)
{
//如果操作符堆栈中最后的操作符为'('则停止出栈
i++;
break;
}
}
else
{
//直到运算符已经高出运算符栈中最后的级别,则入栈
oper.Push(new Operator(strChar, intLevel));
i++;
break;
}
}
}
}
}
}
else
{
//读取前缀表达式结尾将运算符堆栈直接压入输出堆栈
intStackCount = oper.Count;
for(int m=0;m<intStackCount;m++)
{
op = (Operator)oper.Peek();
output.Push(op.OperatorStack);
oper.Pop();
}
i++;
}
}
//形成逆波兰表达式输出字符串
object[] strOutput = output.ToArray();
string str = Convert.ToString(strOutput[strOutput.GetLength(0) - 1]);
for (int m = strOutput.GetLength(0)-2; m >= 0;m-- )
{
if (Convert.ToString(strOutput[m]) != "(" && Convert.ToString(strOutput[m]) != ")")
{
str = str + "," + Convert.ToString(strOutput[m]);
}
}
return str;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
return "";
}
}