栈(2)
前缀、中缀、后缀表达式(逆波兰表达式)
前缀表达式
(1)前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前
(2)举例:(3+4)*5-6对应的前缀表达式就是 - * + 3 4 5 6
从右往左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对他们做相应的计算(栈顶元素和次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式结果。
例如:(3+4)*5-6对应的前缀表达式就是- * + 3 4 5 6,针对前缀表达式求值步骤如下:
- 从左往右扫描,将6、5、4、3压入堆栈
- 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素),计算出3+4的值,得7,再将7入栈
- 接下来时*运算符,因此弹出7和5,计算出7 * 5 = 35,将35入栈
- 最后时 - 运算符,计算出35 - 6的值,即29,由此得出最终结果
中缀表达式
(1)中缀表达式就是常见的运算表达式,如(3+4)* 5 - 6
(2)中缀表达式的求值是我们人最熟悉的,但是对计算机来水哦却不好操作(前面我们讲的案例就能看到这个问题),因此,在计算结果时,往往会将中缀表达式转换成其他表达式来操作(一般转为后缀表达式)
因为中缀表达式,需要判断遇到的操作符的优先级和后面遇到的优先级谁高谁低。
后缀表达式
(1)后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后
(2)举例:(3+4)* 5 - 6对应的后缀表达式就是3 4 + 5 * 6 -
(3)再举例:
后缀表达式计算机求值,从左往右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对他们做相应的计算(次顶元素和栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
例如:(3+4)* 5 - 6 对应的前缀表达式就是3 4 + 5 * 6 -,针对后缀表达式求值步骤如下:
(1)从左往右扫描,将3和4压入堆栈;
(2)遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
(3)将5入栈;
(4)接下来是*运算符,因此弹出5和7,计算出7 * 5 = 35,将35入栈;
(5)将6入栈;
(6)最后是 - 运算符,计算出35 - 6的值,即29,由此得出最终结果
接下来我们按照这个理论通过代码实现逆波兰计算器。
逆波兰计算器
需求如下:
(1)输入一个逆波兰表达式,使用(Stack)计算结果
(2)支持小括号和多位数整数,因为这里我们主要讲的是数据结构,因此计算器进行简化,只支持对整数的计算。
(3)思路分析
(4)完成代码
internal class MyPolandNotaion
{
//先定义一个逆波兰表达式
//(3+4)* 5 - 6对应3 4 + 5 * 6 -
//为了方便,逆波兰表达式的数字和符号使用空格隔开
public static string suffixExpression = "30 4 + 5 * 6 -";
//思路
//1.先将"3 4 + 5 * 6 -"存入一个List中
//2.将AarryList传递一个方法,遍历List配合栈完成计算
//将一个逆波兰表达式,一次将数据和运算符放入到List中
public static List<string> GetListString(string suffixExpression)
{
//将suffixExpression分割
string [] split = suffixExpression.Split(' ');
List<string> list = new List<string>();
foreach (var item in split)
{
list.Add(item);
}
return list;
}
//完成逆波兰表达式的运算
public static int Calculate(List<string> lst)
{
//创建栈,只需要一个栈即可
Stack<string> stack = new Stack<string>();
//遍历list
foreach (var item in lst)
{
//判断是否是数字
if (IsNumber(item))
{
stack.Push(item);
}
else
{
//POP出两个数并运算,再入栈
int num2 = Convert.ToInt32(stack.Pop());
int num1 = Convert.ToInt32(stack.Pop());
int result = 0;
if (item.Equals("+"))
{
result = num1 + num2;
}
else if (item.Equals("-"))
{
result = num1 - num2;
}
else if (item.Equals("*"))
{
result = num1 * num2;
}
else if (item.Equals("/"))
{
result = num1 / num2;
}
else
{
throw new Exception("nothing to do !");
}
stack.Push(result.ToString());
}
}
//最后留在stack中的数据就是计算结果
return Convert.ToInt32(stack.Pop());
}
/// <summary>
/// 判断字符串是否是数字
/// </summary>
public static bool IsNumber(string s)
{
if (string.IsNullOrWhiteSpace(s)) return false;
const string pattern = "^[0-9]*$";
Regex rx = new Regex(pattern);
return rx.IsMatch(s);
}
}