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.
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,后面是符号“+”,进栈。
3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+
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.将后缀表达式进行运算得出结果(栈用来进出运算的数字)。