算法题-字符串3.24-3.29

wric

基本计算器

image.png

image.png

image.png

解析

主要分为两个步骤

一为中缀表达式转化为后缀表达式

二为后缀表达式的求值得到结果

三种表达式

一般来说,表达式分为三种类型,前缀记法、中缀记法和后缀记法。

我们日常使用的表达式为中缀表达式,也就是运算符在运算数的中间。这种种表达式人类很容易识别,并根据其进行计算,但计算机识别这种表达式非常困难。
例如:

a + b * (c - d) + e/f

1920年,波兰科学家扬·武卡谢维奇(Jan ukasiewicz)发明了一种不需要括号的计算表达式的表示法将操作符号写在操作数之前,也就是前缀表达式,即波兰式(Polish Notation, PN)。上述中缀表达式转换为波兰表达式的格式如下:

+a+*b-cd/ef

为了便于理解,我们给出一个具体的实例,这个实例将上面的字母换成具体的数字(1 + 2 (4 - 3) + 6/2),这个结果很容易看出来,也就是1 + 21 + 3 = 6。然后我们看一下波兰表达式的表示形式及运算过程。

+1+*2-4 3/ 6 2 // 从右向左扫描,当遇到运算符时计算其最近的右侧2个运算数
+1+*2-4 3 3   //先计算最右侧的数据,也就是 6/2=3
+1+*2 1 3     // 同理,4-3 = 1
+1+2 3         // 同理, 2*1= 1
+1+5  
6

波兰表达式也成为前缀表达式,而逆波兰表达式则成为后缀表达式,对比可以猜出来运算符在运算数后面的表达式就是逆波兰表达式。上述表达式如果采用逆波兰表达式则如下:

1 2  4 3 -*+ 6 2 / + //计算方式正好相反,也就是从左向右扫描
1 2 1 *+ 6 2 / +
1 2 + 6 2 / +
3 6 2 / +
3 3 +
6

为什么要使用逆波兰表达式

逆波兰表达式严格遵循「从左到右」的运算。计算逆波兰表达式的值时,使用一个栈存储操作数,从左到右遍历逆波兰表达式,进行如下操作:

如果遇到操作数,则将操作数入栈;

如果遇到运算符,则将两个操作数出栈,其中先出栈的是右操作数,后出栈的是左操作数,使用运算符对两个操作数进行运算,将运算得到的新操作数入栈。

整个逆波兰表达式遍历完毕之后,栈内只有一个元素,该元素即为逆波兰表达式的值。

由此可见,逆波兰表示式是天生适合于基于栈的语言。遇到数字就将数字压栈,遇到操作符,就将栈顶的两个元素取出计算,将计算结果再压入栈。

从中缀表达式到后缀表达式

从中缀表达式转换为后缀表达式的流程如下描述。需要注意的是,经过处理之后,中缀表达式中的括弧将被消除,也就是只剩下+-*/数学运算符。

  1. 从左至右扫描一中缀表达式。
  2. 若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
  3. 若读取的是运算符
  4. 该运算符为左括号"(",则直接存入运算符堆栈。
  • 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。
  • 该运算符为非括号运算符:
  • 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
  • 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈。
  • 若比运算符堆栈栈顶的运算符优先级低或者相等,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。
  • 当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。

将中缀表达式转换成逆波兰表达式过程中,特别要注意对于中缀标到式中括号的处理。 1. 要注意的,如果算符是"(",无论入栈中栈顶级别(只看栈顶)为何直接入栈,所以,“(”的等级 只用于对其后入栈的算符进行优先级比较,在“(”入栈时是无视优先级的。 2. 在遇到")"时候找到最后进入的"(",并把"("前面所有的符号都压入出栈。不能仅凭运算符的级别来判断。

注: 逆波兰用的优先级有以下几种, 等级从高到低分别是: 1.* \ 2.+ - 3.( 4.)

阅读 371
10 声望
3 粉丝
0 条评论
10 声望
3 粉丝
文章目录
宣传栏