算术表达式的前缀,中缀,后缀相互转换

中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。

前缀表达式(前缀记法、波兰式)
前缀表达式的运算符位于操作数之前。

前缀表达式的计算机求值:
从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。
例如前缀表达式“- × + 3 4 5 6”:
(1) 从右至左扫描,将6、5、4、3压入堆栈;
(2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈;
(3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈;
(4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
可以看出,用计算机计算前缀表达式的值是很容易的。
详细解释:http://blog.youkuaiyun.com/antineutrino/article/details/6763722/

给出一个中缀表达式如下:
a+b*c-(d+e) 
第一步:按照运算符的优先级对所有的运算单位加括号,
         式子变成了:((a+(b*c))-(d+e)) 
第二步:转换前缀与后缀表达式 
         前缀:把运算符号移动到对应的括号前面 
               则变成了:-( +(a *(bc)) +(de)) 
               把括号去掉:-+a*bc+de   前缀式子出现 
         后缀:把运算符号移动到对应的括号后面 
               则变成了:((a(bc)* )+ (de)+ )- 
               把括号去掉:abc*+de+-   后缀式子出现

<1> 将中缀表达式“1+((2+3)*4)-5”转换为前缀表达式。

(1)构建两个栈,一个存运算符一个存操作数。运算符(以括号分界点)在栈内遵循越往栈顶优先级不降低的原则排序。

(2)从右往左扫描中缀式表达式,从右边第一个字符开始判断。

  如果当前字符是数字,则分配到数字串的结尾并将数字串直接输出。

  如果是运算符,则比较优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将运算符直接入栈;否则将栈顶运  算符出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶元素是括号直接入栈),再将当前运算符入栈。如果是括号,则根据括号的  方向进行处理。如果是括号直接入栈;否则,遇右括号前将所有的运算符全部出栈并输出,遇右括号后将左右的两括号一起删除。

(3)重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再将缀输出字符串。中缀表达式就变成了前缀表达式了。

 

中缀表达式

前缀表达式

(栈顶)运算符栈(栈尾)

说明

5

5

5,是数字串直接输出

-

5

-

-,栈内无运算符,直接入栈

5

-)

),直接入栈

4

5 4

-)

4,是数字串直接输出

*

5 4

-)*

*,栈顶是括号,直接入栈

)

5 4

- ) * )

),直接入栈

3

5 4 3

- ) * )

3,是数字串直接输出

+

5 4 3

- ) * ) +

+,栈顶是括号,直接入栈

2

5 4 3 2

- ) * )+

2,是数字串直接输出

(

5 4 3 2+

- ) *

(,

(

5 4 3 2+*

-

(,

+

5 4 3 2+*

-+

+,优先级大于等于栈顶运算符,直接入栈

1

5 4 3 2+*1

-+

1,是数字串直接输出

5 4 3 2+*1+-

扫描结束,将栈内剩余运算符全部出栈并输出

- + 1 * + 2 3 4 5

逆缀输出字符串

【2】中缀表达式转换为后缀表达式

 

过程和【1】差不多,只不过是从左往右扫描,方向换了一个,其他一样。

还是这个式子:1+((2+3)*4)-5

 

中缀表达式

后缀表达式

(栈顶)运算符栈(栈尾)

说明

1

1

1,是数字串直接输出

+

1

+

+,栈内无运算符,直接入栈

1

+(

(,直接入栈

1

+((

(,直接入栈

2

1 2

+((

2 ,数字

+

1 2

+((+

+,直接入栈

3

1 2 3

+((+

3,是数字串直接输出

1 2 3 +

+(

碰到 )找到(之前所有符号弹出出

*

1 2 3 +

+(*

*

4

1 2 3 + 4

+(*

4

1 2 3 + 4 *

+

碰到 )找到(之前所有符号弹出出

-

1 2 3 + 4 *

+ -

-

5

1 2 3 + 4 *5

+ -

5

1 2 3 + 4 *5 - +

扫描结束

1 2 3 + 4 *5 - +

逆缀输出字符串

 

后缀表达式逆向求解中缀表达式

1 2 3 + 4 *5 - +

基本思路和上面的一样:递归,碰到操作符就进入递归。

从左往右扫描先碰到+号,取+号前面两个操作数:2,3 得到:2+3.

继续往下扫碰到*号,取4 和2+3 得到:(2+3)*4

-号,取(2+3)*4和5得到::(2+3)*4-5

+号:取(2+3)*4-5和1得到::1+(2+3)*4-5

转自:http://blog.youkuaiyun.com/linsheng9731/article/details/23125353

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.youkuaiyun.com/dreamzuora/article/details/53384174

### 前缀中缀后缀表达式的概念 #### 前缀表达式(波兰式) 前缀表达式是指运算符位于操作数之前的表达式形式。这种表示方式最早由波兰逻辑学家扬·卢卡西维茨提出,因此也被称为波兰式。例如,`* + 3 4 5` 表示 `(3 + 4) * 5`[^2]。 #### 中缀表达式 中缀表达式是最常见的一种算术表达式表示方法,其中运算符位于操作数之间。这是人类最习惯使用的表达方式,但在计算机处理时较为复杂,因为需要考虑运算符的优先级和括号的影响。例如,`(3 + 4) * 5` 是一个典型的中缀表达式[^1]。 #### 后缀表达式(逆波兰式) 后缀表达式是指运算符位于操作数之后的表达式形式。它是由前缀表达式演变而来,常用于计算机科学领域,尤其是在编译器设计中。由于其不需要括号来指定顺序,计算起来更加高效。例如,`3 4 + 5 *` 表示 `(3 + 4) * 5`[^2]。 --- ### 转换方法 #### 中缀表达式转后缀表达式 将中缀表达式转换后缀表达式的过程可以通过栈实现。以下是具体步骤: 1. 初始化两个栈:一个是操作符栈 `S1`,另一个是存储后缀表达式的栈 `S2`。 2. 遍历中缀表达式的每一个字符: - 如果当前字符是操作数,则直接压入 `S2` 栈。 - 如果当前字符是左括号 `(`,则直接压入 `S1` 栈。 - 如果当前字符是右括号 `)`,则依次弹出 `S1` 栈中的元素并压入 `S2`,直到遇到左括号为止。 - 如果当前字符是运算符,则比较其与 `S1` 栈顶运算符的优先级: - 若当前运算符优先级高于栈顶运算符,则将当前运算符压入 `S1`。 - 否则,弹出 `S1` 的栈顶元素并压入 `S2`,直至满足条件或将 `S1` 清空后再压入当前运算符。 3. 当遍历完成后,如果 `S1` 不为空,则依次弹出所有元素并压入 `S2`。 4. 最终,`S2` 即为对应的后缀表达式[^3]。 #### 中缀表达式转前缀表达式 将中缀表达式转换前缀表达式的方法类似于转换后缀表达式,但需要注意以下几点: 1. 将输入的中缀表达式反转。 2. 使用相同的规则将反转后的中缀表达式转换后缀表达式。 3. 反转得到的结果即为前缀表达式[^2]。 #### 后缀表达式转中缀表达式 通过栈可以轻松完成这一转换过程: 1. 初始化一个栈。 2. 遍历后缀表达式的每个字符: - 如果是操作数,则将其压入栈。 - 如果是运算符,则从栈中弹出两个操作数,并按 “(操作数1 运算符 操作数2)” 的格式组合成新的字符串再压回栈。 3. 遍历结束后,栈顶元素即为中缀表达式。 #### 前缀表达式转中缀表达式 同样利用栈来进行转换: 1. 初始化一个栈。 2. 从右至左遍历前缀表达式的每个字符: - 如果是操作数,则将其压入栈。 - 如果是运算符,则从栈中弹出两个操作数,并按 “(操作数1 运算符 操作数2)” 的格式组合成新的字符串再压回栈。 3. 遍历结束后,栈顶元素即为中缀表达式。 --- ### 示例代码 以下是一个简单的 C 实现,展示如何将后缀表达式转化为数值结果: ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MAX_SIZE 100 typedef struct { double data[MAX_SIZE]; int top; } Stack; void init(Stack *s) { s->top = -1; } int isEmpty(Stack *s) { return (s->top == -1); } void push(Stack *s, double val) { s->data[++(s->top)] = val; } double pop(Stack *s) { return s->data[(s->top)--]; } double evaluatePostfix(const char *expr) { Stack stack; init(&stack); for(int i = 0; expr[i] != '\0'; ++i){ if(isdigit(expr[i])){ double num = 0; while(isdigit(expr[i])){ // 处理多位数字 num = num * 10 + (expr[i]-'0'); i++; } i--; // 因为上面while会多加一次i++ push(&stack, num); } else if(expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/'){ double op2 = pop(&stack); double op1 = pop(&stack); switch(expr[i]){ case '+': push(&stack, op1 + op2); break; case '-': push(&stack, op1 - op2); break; case '*': push(&stack, op1 * op2); break; case '/': push(&stack, op1 / op2); break; } } } return pop(&stack); } int main() { const char postfixExpr[] = "34+5*"; printf("Result of '%s' is %.2f\n", postfixExpr, evaluatePostfix(postfixExpr)); return 0; } ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值