Reverse Polish Notation
It is worth noting that only four arithmetic operations of single digits are implemented in the demo, and the division only retains integers. If you want to implement multi-digit operations, you can split the numbers by adding spaces when using Reverse Polish Notation.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static void Change(char[] tokens)
{
Stack<int> s = new Stack<int>();
string operators = "+-*/";
foreach (char token in tokens)
{
if (!operators.Contains(token))
{
s.Push(Convert.ToInt32(token));
continue;
}
int x = s.Pop();
int y = s.Pop();
if (token.Equals("+"))
{
s.Push(y + x);
}
else if (token.Equals("-"))
{
s.Push(y - x);
}
else if (token.Equals("*"))
{
s.Push(y * x);
}
else
{
s.Push(y / x);
}
}
s.Pop().ToString(); ;
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Control || e.KeyCode == Keys.Enter)
{
string tempstr = "";
Stack<char> arrStark = new Stack<char>();
char[] arrChar = textBox1.Text.ToCharArray();
int a = 4; // default status
for (int i = 0; i < arrChar.Length; i++)
{
if (arrChar[i] <= '9' && arrChar[i] >= '0')
{
tempstr += arrChar[i];
}
switch (a)
{
case 1: // +-
if (arrChar[i] == '+' || arrChar[i] == '-')
{
a = 1;
tempstr += arrStark.Pop();
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == '*' || arrChar[i] == '/')
{
a = 2;
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == '(')
{
a = 3;
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == ')')
{
a = 4;
for (int j = 0; j < arrStark.Count; j++)
{
// output the opreator in "()"
if (arrStark.Peek() == '(')
{
// pop "("
arrStark.Pop();
break;
}
else
{
tempstr += arrStark.Pop();
}
}
}
break;
case 2: // */
if (arrChar[i] == '+' || arrChar[i] == '-')
{
a = 1;
for (int j = 0; j <= arrStark.Count; j++)
{
tempstr += arrStark.Pop();
}
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == '*' || arrChar[i] == '/')
{
a = 2;
tempstr += arrStark.Pop();
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == '(')
{
a = 3;
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == ')')
{
a = 4;
for (int j = 0; j < arrStark.Count; j++)
{
if (arrStark.Peek() == '(')
{
//pop "("
arrStark.Pop();
break;
}
else
{
//output the opreator in "()"
tempstr += arrStark.Pop();
}
}
}
break;
case 3: // (
if (arrChar[i] == '+' || arrChar[i] == '-')
{
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == '*' || arrChar[i] == '/')
{
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == '(')
{
a = 3;
arrStark.Push(arrChar[i]);
}
else
if (arrChar[i] == ')')
{
a = 4;
for (int j = 0; j < arrStark.Count; j++)
{
if (arrStark.Peek() == '(')
{
//pop "("
arrStark.Pop();
break;
}
else
{
//output the opreator in "()"
tempstr += arrStark.Pop();
}
}
}
break;
case 4: // )
if (arrChar[i] == '+' || arrChar[i] == '-')
{
if (arrStark.Count == 0)
{
a = 1;
arrStark.Push(arrChar[i]);
}
else
{
if (arrStark.Peek() == '+' || arrStark.Peek() == '-')
{
a = 1;
arrStark.Push(arrChar[i]);
}
else
if (arrStark.Peek() == '*' || arrStark.Peek() == '/')
{
a = 1;
for (int j = 0; j < arrStark.Count; j++)
{
tempstr += arrStark.Pop();
}
arrStark.Push(arrChar[i]);
}
}
}
else
if (arrChar[i] == '*' || arrChar[i] == '/')
{
if (arrStark.Count == 0)
{
a = 2;
arrStark.Push(arrChar[i]);
}
else
{
if (arrStark.Peek() == '+' || arrStark.Peek() == '-')
{
a = 2;
arrStark.Push(arrChar[i]);
}
else if (arrStark.Peek() == '*' || arrStark.Peek() == '/')
{
a = 2;
arrStark.Push(arrChar[i]);
}
}
}
else
if (arrChar[i] == '(')
{
a = 3;
arrStark.Push(arrChar[i]);
}
if (arrChar[i] == ')')
{
a = 4;
for (int j = 0; j < arrStark.Count; j++)
{
if (arrStark.Peek() == '(')
{
//pop "("
arrStark.Pop();
break;
}
else
{
//output the opreator in "()"
tempstr += arrStark.Pop();
}
}
}
break;
default:
break;
}
}
//output the remaining item in stack and clear
foreach (char item in arrStark)
{
tempstr += item;
}
arrStark.Clear();
char[] strarray = tempstr.ToCharArray();
Stack<int> s = new Stack<int>();
string operators = "+-*/";
foreach (char token in strarray)
{
if (!operators.Contains(token.ToString()))
{
s.Push(Convert.ToInt32(token.ToString()));
continue;
}
int x = s.Pop();
int y = s.Pop();
if (token.Equals('+'))
{
s.Push(y + x);
}
else if (token.Equals('-'))
{
s.Push(y - x);
}
else if (token.Equals('*'))
{
s.Push(y * x);
}
else
{
s.Push(y / x);
}
}
textBox2.Text = s.Pop().ToString();
}
}
}
}
我们把平时所用的标准四则运算表达式,即“9+(3-1)*3+10/2"叫做中缀表达式。因为所有的运算符号都在两数字的中间,现在我们的问题就是中缀到后缀的转化。
中缀表达式“9+(3-1)*3+10/2”转化为后缀表达式“9 3 1-3*+ 10 2/+”
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
下面我们来具体看看这个过程。
1. 初始化一空栈,用来对符号进出栈使用。
2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。
![](http://www.nowamagic.net/librarys/images/201210/2012_10_22_08.jpg)
3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
![](http://www.nowamagic.net/librarys/images/201210/2012_10_22_09.jpg)
5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。
![](http://www.nowamagic.net/librarys/images/201210/2012_10_22_10.jpg)
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
![](http://www.nowamagic.net/librarys/images/201210/2012_10_22_11.jpg)
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+
![](http://www.nowamagic.net/librarys/images/201210/2012_10_22_12.jpg)
dList {a,b,+,c,d,e,+,*,-}
rStack
{ }
{a} //a入栈
{a,b} //b入栈
{a+b} //遇到+号,取出两个操作数进行运算,运算结果入栈
{a+b,c}
{a+b,c,d}
{a+b,c,d,e}
{a+b,c,d+e}
{a+b,c*(d+e)}
{a+b-c*(d+e)}
1.将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
2.将后缀表达式进行运算得出结果(栈用来进出运算的数字)。