逆波兰式

逆波兰式一.前言: 逆波兰表示法 ( Reverse Polish notation , RPN ,或 逆波兰记法 ),是一种是由 波兰 数学家 扬·武卡谢维奇 1920年引入的数学表达式形式,在逆波兰记法中,所有 操作符 置于 操作数 的后面,因此也被称为 后缀表示法 (也称后缀表达式)。而我们

逆波兰式"

一.前言:

  逆波兰表示法 ( Reverse Polish notation , RPN ,或 逆波兰记法 ),是一种是由 波兰 数学家 扬·武卡谢维奇 1920年引入的数学表达式形式,在逆波兰记法中,所有 操作符 置于 操作数 的后面,因此也被称为 后缀表示法 (也称后缀表达式)。而我们平常用的a+b叫做中缀表达式,转换成后缀表达式为ab+(其实还有一个波兰式,也就作前缀表达式+ab),为什么要这么转换呢?虽然我们人脑非常喜欢这种显而易见的中缀表达式计算,但是计算机算觉得这非常的难计算(主要是堆栈的实现会变的比中缀表达式更简单),因此就有了波兰表达式和逆波兰表达式。

二.问题分析:

  那我们如和将中缀表达式转成后缀表达式呢?总所周知,在中缀表达式中我们的操作符+-优先级最低,*/优先级第二,而()优先级最高。但是在逆波兰式的转换过程中这个优先级有一些变化,乘除的优先级会看成比加减的优先级更低,括号优先级依旧是最高,因此我们可以有定义+-优先级为2,()优先级为1,*/优先级为3。因此我们就解决掉了优先级的问题。

  其他规则

  1.如果碰到左括号,则直接入栈。

  2.如果碰到优先级高于栈顶的,则依次出栈,直到栈顶为空或者栈顶的优先级高于碰到的操作符,然后再把操作符加入栈区即可

  3.如果中缀表达式遍历完成后,栈区还剩余操作符,则直接把剩余操作符从栈顶依次加入逆波兰式

  4.如果碰到右括号,则把括号和右括号之间的操作符加入逆波兰式,左括号和右括号出栈

  接下来我们看看具体怎么转换吧!

 

  

  首先,我们给出一个计算样例来解释计算过程,中缀表达式如下:1+2*(3+4)/5

  我们给出一个栈区用来存操作符,用一个字符串来存储逆波兰式

  碰到1,直接加入逆波兰式

  stack(代表栈区):NULL

  bolan(代表逆波兰式):1

  

  碰到‘+’,因为栈区此时为空,故直接加入栈区

  stack(代表栈区):+

  bolan(代表逆波兰式):1

 

  碰到2,直接加入逆波兰式

  stack(代表栈区):NULL

  bolan(代表逆波兰式):1,2

 

  碰到‘*’,因为*的优先级为2,最低,故不需要弹出+号,因此直接入栈\

  stack(代表栈区):+,*

  bolan(代表逆波兰式):1,2

 

  

  碰到‘(’,因为左括号需要续’)’相匹配,故直接入栈

  stack(代表栈区):+,*,(

  bolan(代表逆波兰式):1,2

  

  

  碰到数字3,直接加入逆波兰式

  stack(代表栈区):+,*,(

  bolan(代表逆波兰式):1,2,3

 

   

  碰到‘+’,因为+优先级低于括号,因此直接入栈

  stack(代表栈区):+,*,(,+

  bolan(代表逆波兰式):1,2,3

 

  碰到数字4,直接加入逆波兰式

  stack(代表栈区):+,*,(,+

  bolan(代表逆波兰式):1,2,3,4

 

  碰到‘(‘,把左括号之前的全部加入逆波兰式

  stack(代表栈区):+,*

  bolan(代表逆波兰式):1,2,3,4,+

 

  碰到’/’,把栈顶优先级不高于’/’的全部加入逆波兰式,再把自己加入栈区

  stack(代表栈区):+,/

  bolan(代表逆波兰式):1,2,3,4,+,*

 

  碰到数字5,直接加入波兰式

  stack(代表栈区):+,/

  bolan(代表逆波兰式):1,2,3,4,+,*,5

 

  字符串遍历结束,把栈区剩下的全部加入逆波兰式

  

  stack(代表栈区):NULL

  bolan(代表逆波兰式):1,2,3,4,+,*,5,/,+

三.代码实现:

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 int jdgCode(char flag)//定于操作符运算
 4 {
 5     if(flag == '+')
 6         return 1;
 7     if(flag == '-')
 8         return 2;
 9     if(flag == '*')
10         return 3;
11     if(flag == '/')
12         return 4;
13 }
14 double Compute(string cpu)
15 {
16     stack <double> ans;
17     for(auto iter = cpu.begin();iter != cpu.end();iter++){
18         if(*iter >= '0' && *iter <= '9')
19             ans.push(*iter - '0');
20         else {
21             double r1,r2;
22             r1 = ans.top();
23             ans.pop();
24             r2 = ans.top();
25             ans.pop();
26             switch(jdgCode(*iter)){
27                 case 1: ans.push(r2 + r1);break;
28                 case 2: ans.push(r2 - r1);break;
29                 case 3: ans.push(r2 * r1);break;
30                 case 4: ans.push(r2 / r1);break;
31             }
32         }
33     }
34     return ans.top();
35 }
36 int prio(char a)
37 {
38     if(a == '*' || a == '/')
39         return 2;
40     else if(a == '+' || a == '-')
41         return 1;
42     else 
43         return 0;//左括号优先级
44 }
45 void Dispose(string& ms,string& as)//处理成后缀表达式
46 {
47     stack <char> ct;//定义一个ct容器存储运算符
48     for(auto iter = ms.begin();iter != ms.end();iter++){
49         if(*iter >= '0' && *iter <= '9')//如果是数字,直接入栈
50             as += *iter;
51         else{
52             if(ct.empty() || *iter == '(')//如果是空栈,或者是左括号,直接入栈
53                 ct.push(*iter);
54             else if(*iter == ')'){
55                 while(ct.top() != '('){//把左括号和右括号里面的操作符出栈
56                     as += ct.top();
57                     ct.pop();
58                 }
59                 ct.pop();//弹出左括号
60             }
61             else{
62                 while(!ct.empty() && prio(*iter) <= prio(ct.top())){//把优先级低于当前操作符的操作符出栈
63                     as += ct.top();
64                     ct.pop();
65                 }
66                 ct.push(*iter);//把当前操作符入栈
67             }
68         }
69     }
70     while(!ct.empty()){//如果栈区还有操作符
71         as += ct.top();
72         ct.pop();
73     }
74 }
75 int main()
76 {
77     string ms;//中缀表达式
78     string as;//后缀表达式
79     cin >> ms;
80     Dispose(ms,as);//将中缀表达式处理为后缀表达式
81     cout << as << endl;//输出处理后的后缀表达式
82     cout << "Result:" << Compute(as) << endl;//输出后缀表达式计算结果
83     return 0;
84 }

今天的文章逆波兰式分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/56900.html

(0)
编程小号编程小号
上一篇 2023-08-26
下一篇 2023-08-26

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注