用堆栈求算术表达式在数据结构中也是一个比较经典的问题,其主要原理就是利用两个堆栈,首先利用一个堆栈把算数表达式(中缀表达式,即我们常用的表达式)转换为后缀表达式,再利用另一个堆栈,把中缀表达式中的数字进行相关操作,最后栈里的值为所求结果,直接弹出即可。
private string MidExpression(string orgstr)
{
StringBuilder temp = new StringBuilder();
foreach (var item in orgstr)
{
switch (item)
{
case '(':
symbols.Push(item);
break;
case ')':
{
while (symbols.Count > 0)
{
if (symbols.Peek() != '(')
{
temp.Append(symbols.Pop());
}
else
{
symbols.Pop();
}
}
}
break;
case '+':
{
if (symbols.Count > 0)
{
char topchar = symbols.Peek();
if (topchar == '*' || topchar == '/' || topchar == '+' || topchar == '-')
{
temp.Append(symbols.Pop());
symbols.Push(item);
}
else
{
symbols.Push(item);
}
}
else
{
symbols.Push(item);
}
}
break;
case '-':
{
if (symbols.Count > 0)
{
char topchar = symbols.Peek();
if (topchar == '*' || topchar == '/' || topchar == '+' || topchar == '-')
{
temp.Append(symbols.Pop());
symbols.Push(item);
}
else
{
symbols.Push(item);
}
}
else
{
symbols.Push(item);
}
}
break;
case '*':
if (symbols.Count > 0)
{
char topchar = symbols.Peek();
if (topchar == '*' || topchar == '/')
{
temp.Append(symbols.Pop());
symbols.Push(item);
}
else
{
symbols.Push(item);
}
}
else
{
symbols.Push(item);
}
break;
case '/':
if (symbols.Count > 0)
{
char topchar = symbols.Peek();
if (topchar == '*' || topchar == '/')
{
temp.Append(symbols.Pop());
symbols.Push(item);
}
else
{
symbols.Push(item);
}
}
else
{
symbols.Push(item);
}
break;
default:
temp.Append(item);
break;
}
}
while (symbols.Count > 0)
{
temp.Append(symbols.Pop());
}
return temp.ToString();
}
先把字符串转为后缀表达式:原理就是从左往右依次读取表达式的每个字符,如果为“(”直接入栈,如果是“)”,则依次出栈,直到遇到“(” (注意,出栈时直接把出栈结果拼接到后缀表达式中,但不拼接括号),如果是数字,直接拼接到表达式中,如果为操作符(即+ - * /),用该操作符与栈顶的操作符比较,若优先级高于栈定操作符,则直接入栈,否则先出栈,再入栈。注意,此时只判断栈定操作符的优先级,如果为括号,则直接入栈。读取完之后直接如果栈中还有操作符,则直接拼接到表达式中。
根据后缀表达式求值。原理就是从左往右依次读后缀表达式,如果为数字,直接入栈,如果为操作符,则弹出需要的操作数,计算完结果后再入栈。读取完毕后栈中的值为表达式结果。
private int compute(string midstr)
{
foreach (var item in midstr)
{
switch (item)
{
case '+':
int fp = numbers.Pop();
int sp = numbers.Pop();
numbers.Push(fp + sp);
break;
case '-':
int fs = numbers.Pop();
int ss = numbers.Pop();
numbers.Push(ss - fs);
break;
case '*':
int fx = numbers.Pop();
int sx = numbers.Pop();
numbers.Push(fx * sx);
break;
case '/':
int fd = numbers.Pop();
int sd = numbers.Pop();
numbers.Push(sd / fd);
break;
default:
numbers.Push(Convert.ToInt32(item.ToString()));
break;
}
}
return numbers.Pop();
}
测试调用
static void Main(string[] args)
{
string exp = "(((1+1)*3/2+1)-1)*2";
StackClass myclsaa = new StackClass(exp);
int result = myclsaa.OutPut();
Console.WriteLine(result);
Console.ReadLine();
}