逆波兰表达式(后缀表达式)C++实现

article/2025/9/19 10:32:28

1 何谓逆波兰表达式

逆波兰表达式又称为后缀表达式,是波兰逻辑学家J・卢卡西维兹(J・ Lukasewicz)于1929年首先提出的一种表达式的表示方法。

例如:
1 + 2 + 3,转换为逆波兰表达式:1 2 3 + +。
1 + 2 * 3,转换为逆波兰表达式:1 2 3 * +。

对于我们而言,中缀表达式是最熟悉也是最直观的一种求值方式,但是计算机处理中缀表达式并不方便。

对于计算机而言,逆波兰表达式是最优、最简洁、最方便检索的一种表达式形式。因为逆波兰表达式没有括号,并且严格遵循从左到右运算。只需要利用栈的特点,就可以一次性求出逆波兰表达式的值。

2 算法实现

首先需要一个队列用来存储后缀表达式,一个临时存储操作符

  1. 构造一个运算符优先表(算符优先矩阵)。
  2. 读入一个中缀表达式并进行预处理,将运算符与操作数分隔开。
  3. 从左到右扫描中缀表达式。
  • 如果是操作数,直接入队列
  • 如果是操作符,栈为空的情况下直接入栈
  • 不为空则需要比较栈顶运算符与当前运算符优先级,当前运算符优先级高则入栈
  • 否则将栈顶运算符出栈直到栈为空或者栈顶运算符优先级小于当前运算符。
  1. 计算逆波兰表达式结果。

3 C++实现代码

#include<bits/stdc++.h>
using namespace std;// 从操作符到索引的映射
map<char, int>operator_to_index;
// 算符优先矩阵
int priority_matrix[6][6] = {1, 1, -1, -1, -1, 1,1, 1, -1, -1, -1, 1,1, 1, 1, 1, -1, 1,1, 1, 1, 1, -1, 1,-1, -1, -1, -1, -1, 0,1, 1, 1, 1, 100, 1
};
// 输入的中缀表达式
string expression;
// 存储操作数
queue<string>Operand;
// 存储操作符
stack<char>Operator;
// 存储后缀表达式计算结果
stack<int>result;// 判断是否为操作符
bool isOperator(char ch) {if (ch == '(' || ch == ')' || ch == '+' || ch == '-' || ch == '*' || ch == '/')return true;return false;
}// 判断优先级
bool priority(char left, char right) {//左边操作符(栈顶)优先级低if (priority_matrix[operator_to_index[left]][operator_to_index[right]] == -1)return true;//左边操作符(栈顶)优先级与右边(当前操作符)相等if (priority_matrix[operator_to_index[left]][operator_to_index[right]] == 0)return true;return false;
}// 初始化
void init() {// 将操作符映射为对应的索引operator_to_index['+'] = 0;operator_to_index['-'] = 1;operator_to_index['*'] = 2;operator_to_index['/'] = 3;operator_to_index['('] = 4;operator_to_index[')'] = 5;
}// 打印后缀表达式
void print_postfix() {queue<string>temp = Operand;cout << "逆波兰表达式为:" << endl;while (!Operand.empty()) {cout << Operand.front() << ' ';Operand.pop();}cout << endl;Operand = temp;
}void print_Infix() {cout << "中缀表达式为:" << endl;cout << expression << endl;
}// 输入函数
bool readin() {cin >> expression;if (expression == "end")return false;return true;
}// 处理函数
void treat() {// 预处理表达式,将数字与操作符用空格分开for (int i = 0; i < expression.length(); i++) {if (isOperator(expression[i])) {expression.insert(i, " ");i++;expression.insert(i + 1, " ");}}stringstream sin(expression);string word;// 遍历表达式while (sin >> word) {// 如果是操作符if (isOperator(word[0])) {// 如果存储操作符的栈为空,直接入栈if (Operator.empty()) {Operator.push(word[0]);}// 如果栈顶运算符优先级小于当前运算符优先级,直接入栈else if (priority(Operator.top(), word[0])) {Operator.push(word[0]);}// 如果栈顶运算符优先级大于等于当前运算符优先级,则将栈顶出栈,直到栈为空或者栈顶运算符优先级小于当前运算符优先级else {while (!Operator.empty() && !priority(Operator.top(), word[0])) {string temp = "";temp += Operator.top();Operator.pop();Operand.push(temp);}// 右括号不入栈if (word[0] != ')')Operator.push(word[0]);else {// 将栈中左括号去除if (Operator.top() == '(')Operator.pop();}}}// 如果是操作数,直接进入Operand队列else {Operand.push(word);}}// 当操作符栈不为空时,需要将栈中操作符压入操作数队列中while (!Operator.empty()) {string temp = "";temp += Operator.top();Operator.pop();Operand.push(temp);}
}// 计算逆波兰表达式结果
void calculat() {queue<string>temp = Operand;// 依次遍历逆波兰表达式while (!Operand.empty()) {string s = Operand.front();Operand.pop();// 如果是操作符,则取出result栈中两个操作数,进行相应计算if (isOperator(s[0])) {int b = result.top();result.pop();int a = result.top();result.pop();int c = 0;if (s[0] == '+') {c = a + b;}else if (s[0] == '-') {c = a - b;}else if (s[0] == '*') {c = a * b;}else if (s[0] == '/') {c = a / b;}result.push(c);}// 如果是操作数,直接压入result栈else {result.push(stoi(s));}//cout << result.top() << ' ';}//cout << endl;Operand = temp;
}void print_result() {cout << "逆波兰表达式计算结果:" << endl;cout << result.top() << endl;cout << endl;
}int main() {init();cout << "请输入中缀表达式(end表示退出程序):" << endl;while (readin()) {treat();//print_Infix();print_postfix();calculat();print_result();}return 0;
}

4 运算结果

在这里插入图片描述
附上输入样例:

1+(2+(3+4))
(1+2)6-(5+3)+(3+5)/4
(12+24+36)/12+100
(12+16/2-2
8+(20+7)/3)-10*2

注意:输入的中缀表达式不能有空格,因为是用cin读取的,cin不能读取空格。


http://chatgpt.dhexx.cn/article/Y687fVkn.shtml

相关文章

将一般算术表达式转化为逆波兰表达式,并求逆波兰表达式的值。

要求&#xff1a;设计一个算法&#xff0c;将一般算术表达式转化为逆波兰表达式&#xff0c;并求逆波兰表达式的值。 实现思路 获取一个中缀表达式将表达式转换为后缀表达式计算后缀表达式的结果 中缀表达式转换为后缀表达式的几个关键部分 假如不是运算符&#xff0c;则输…

波兰表达式与逆波兰表达式

文章目录 波兰表达式逆波兰表达式波兰表达式计算逆波兰表达式计算总结 常见的算术表达式&#xff0c;称为中缀表达式&#xff0c;例如&#xff1a; 5 ( 6 – 4 / 2 ) * 3波兰表达式 波兰表达式也称为前缀表达式&#xff0c;以上面的例子为例&#xff0c;其波兰表达式为&…

逆波兰表达式

逆波兰表达式在维基百科上的解释&#xff1a;逆波兰表示法&#xff08;Reverse Polish notation&#xff0c;RPN&#xff0c;或逆波兰记法&#xff09;&#xff0c;是一种是由波兰数学家扬武卡谢维奇1920年引入的数学表达式方式&#xff0c;在逆波兰记法中&#xff0c;所有操作…

【数据结构】-------逆波兰表达式(C++)

文章目录 逆波兰表达式讲解正常表达式转换到逆波兰表达式栈操作逆波兰表达式的原理多位数压入栈操作代码例题 逆波兰表达式讲解 逆波兰表达式-----是数据结构的应用&#xff0c;你要单独说讨论它的话没有多大意义&#xff0c;如果我们结合数据结构中的栈来讲解的话&#xff0c…

什么是逆波兰表达式?

文章目录 1. 题目描述2. 解题思路3. 动图演示4. 代码实现 1. 题目描述 2. 解题思路 逆波兰表达式由波兰的逻辑学家卢卡西维兹提出&#xff0c;它的特点是&#xff1a;没有括号&#xff0c;运算符总是放在和它相关的操作数之后。因此&#xff0c;逆波兰表达式也称后缀表达式&am…

微信网页开发中授权headimgurl有的为空

微信网页开发授权&#xff0c;有的用户头像链接为空。 微信开发文档&#xff1a;https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html headimgurl用户头像&#xff0c;最后一个数值代表正方形头像大小&#xff08;有0、46、64、…

微信开发——网页授权

微信开发——网页授权 前期准备前端后端 前期准备 ①微信客户端中访问第三方页面&#xff0c;公众号可以通过网页登陆授权&#xff0c;获取微信用户的基本信息&#xff08;头像、昵称等&#xff09;&#xff0c;实现业务逻辑。一切按照官方文档说明开发。 ②安装微信开发者工具…

微信公众号微信网页开发网页授权/回调自定义参数问题处理方法。

微信公众号页面授权回调自定义参数问题 我们知道微信页面回调接口&#xff0c;获得用户信息后&#xff0c;回调地址&#xff1a; redirect_uri&#xff1a;授权后重定向的回调链接地址&#xff0c; 请使用 urlEncode 对链接进行处理。 授权后跳转回页面&#xff1a; redirec…

微信网页开发--分享接口

流程 关于流程&#xff0c;在上一篇中已经有图介绍: 微信文档 微信JS-SDK说明文档 JSSDK使用步骤 首先确保已经获取了相关权限 步骤一&#xff1a;绑定域名 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。 备注&#xff1a;登录后…

微信网页开发样式库的使用

一、WeUI 是什么 WeUI 是一套同微信原生视觉体验一致的基础样式库&#xff0c;由微信官方设计团队为微信内网页和微信小程序量身设计&#xff0c;令用户的使用感知更加统一。在微信网页或小程序中使用 WeUI&#xff0c;有如下优势&#xff1a; 1. 同微信客户端一致的视觉效果…

微信网页开发(10)--扫一扫功能接口

点此查看 微信公众号/微信网页/微信支付/企业微信/小程序开发合集及源代码下载 本文目录 1. 背景2. 代码3. 测试 1. 背景 我们可以在微信网页调起扫一扫功能&#xff0c;可以识别一维码、二维码的内容&#xff0c;然后根据扫码结果实现我们的业务逻辑。 2. 代码 代码如下&am…

微信公众号开发—通过网页授权实现业务系统登录及用户绑定(微信网页授权自动登录业务系统)

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; 微信公众号开发—通过网页授权实现业务系统登录及用户绑定(微信网页授权…

微信网页开发,禁止右上角微信复制分享链接JS

禁止微信右上角分享链接 开发网页时&#xff0c;为了提高网页链接的安全&#xff0c;不想让别人分享链接给别人 一般微信打开网页后&#xff0c;点击右上角是这样的 想要网页不能被复制&#xff0c;不能分享给其他人 效果图&#xff1a; 资源文件下载地址 下载地址 直接贴…

开发微信网页及调试方法

参考资料 Mac中怎么使用Nginx实现80端口转发8080端口 - 大数据 - 亿速云 使用代理映射解决微信页面调试难题 | 梦翼坊 微信开发工具里的域名必须是在微信公众号白名单里的域名,而npm run dev大多是localhost,所以为了方便调试,需要如下步骤 在Charles勾选Proxy-macOS Proxy…

微信网页开发之JS-SDK初使用

最近需要做一个页面&#xff0c;该页面使用微信浏览器打开&#xff0c;功能如下&#xff1a; 1、用户打开链接之后获取到用户的openId&#xff0c;用于支付、获取后台数据等场景 2、自定义分享链接、标题、图标、描述等 3、隐藏微信页面中的某些菜单项列表 阅读本文前需掌握…

微信网页开发--获取微信用户信息

流程 用户扫码或者直接点击链接进入我们的入口页面&#xff1b;进入授权登录页面&#xff0c;用户点击授权登录按钮&#xff1b;微信会自动将我么的网页授权域名后增加参数&#xff1b;根据微信给的code去获取当前登录的微信用户的用户信息。 具体操作过程 1.配置网页授权域名…

微信网页开发(4)--使用JSSDK基础接口

点此查看 微信公众号/微信网页/微信支付/企业微信/小程序开发合集及源代码下载 本文目录 1. JSSDK接口2. 基础接口3. 开发流程3.1 绑定域名3.2 引入JS文件3.3 通过config接口注入权限验证配置3.5 调用基础接口 4. 小结 1. JSSDK接口 微信提供了很多JSSDK接口&#xff0c;包括基…

微信网页开发(8)--地理位置接口

点此查看 微信公众号/微信网页/微信支付/企业微信/小程序开发合集及源代码下载 本文目录 1. 背景2. 代码3. 测试 1. 背景 微信网页提供了获取当前地理位置经纬度&#xff0c;以及通过内置地图查看当前位置的接口。 官方接口说明如下&#xff1a; // 获取位置 wx.getLocation…

微信公众号开发——2、微信网页开发

第一部分、为公众号菜单嵌入网页 一、关键参考文档 微信JS-SDK说明文档 。 二、编辑模式嵌入网页 在公众号平台下&#xff0c;自定义菜单&#xff0c;添加菜单&#xff0c;并选择菜单内容跳转到指定页面地址即可&#xff08;需认证后方可添加页面地址&#xff0c;个人账号暂不…

微信网页开发配置整理

真是人越大记忆越差&#xff0c;断断续续做了几个微信小程序和微信h5项目&#xff0c;然鹅小程序的开发流程有些都忘了&#xff0c;最近刚做完一个微信h5网页开发的项目&#xff0c;所以赶紧记录下开发中需要注意的点&#xff0c;给自己往后回顾&#xff0c;同时也给第一次接入…