C++后缀表达式

C++后缀表达式1基本概念后缀表示法也叫逆波兰表示法(前缀就是波兰表示法),由于所有的操作符都在操作数的后面,所以被称为后缀表示法。中缀表示法的操作符在操作数之间,也是最符合人的逻辑。前缀表示法的操作符在操作数之前,它和后缀表示法一样,都是为了方便计算机计算,因为在后缀或前缀中没有括号,也不存在优先级处理的问题,直接利用栈进行计算。示例:中缀表达式:5+(1+2)*4-3后缀表达式:512+4*+3-2中缀…

大家好,又见面了,我是你们的朋友全栈君。

1 基本概念

后缀表示法也叫逆波兰表示法(前缀就是波兰表示法),由于所有的操作符都在操作数的后面,所以被称为后缀表示法。

中缀表示法的操作符在操作数之间,也是最符合人的逻辑。前缀表示法的操作符在操作数之前,它和后缀表示法一样,都是为了方便计算机计算,因为在后缀或前缀中没有括号,也不存在优先级处理的问题,直接利用栈进行计算。

示例:

中缀表达式:

5+(1+2)*4-3

后缀表达式:

512+4*+3-

2 中缀表示转后缀表示

中缀转后缀可以从左向右扫描表达式,然后按照规则进行处理,对于中缀表达式a+(b+c)*d-e的转换步骤:

1. 首先初始化两个栈:输出栈rpn_和操作符栈rpn_stack

2. 从左至右扫描表达式,遇到操作数则直接压入输出栈,在遇到a时,由于是操作数,将“a”压入rpn_

3. 继续扫描,遇到操作符时,如果该操作符优先级高于rpn_stack栈顶的操作符,则直接压入rpn_stack,如果同级或低于栈顶操作符,则将栈中操作符依次弹出(同时压入输出栈)直到遇到比当前操作符优先级低的(或者遇到了“(“),然后压入操作符。(注意,对于操作符“(“,只有“)”才能将其弹出,其他情况不弹出“(“)。现在我们扫描到了“+”,由于当前的操作符栈空,直接压入。

4. 然后读取到“(“,由于它的优先级是最高的,只要遇到就直接压入栈。

5. 然后读取到操作数“b”,压入输出栈 rpn_

6. 继续读取到 “+” ,当前操作符栈的栈顶是“(“,因为只有“)”才能将其弹出,所以“+”入栈。

7. 读取的“c”压入输出栈。

8. 读取到了“)”,此时开始将操作符栈的操作符依次弹出(同时压入输出栈),直到遇到第一个“(“,将“(“弹出。(“(““)”都不能进入输出栈)

9. 然后读取到” * “,当前操作符栈的栈顶是“+”,优先级低于” * “,所以直接压入栈。

10.     读取的“d”压入输出栈。

11.     读取到“-“,当前栈顶是” * “,比“-“的优先级高,所以” * “弹出(同时压入输出栈,下同),然后栈顶“+”的优先级和“-“相同,也要弹出。此时操作符栈空,“-“压入。

12.     读取到了“e”,压入输出栈,此时表达式读取完毕,将操作符栈依次弹出并压入输出栈,完成了转换,输出为abc+d*+e-

以下是将中缀表达式转化为后缀表达式的代码:

// 比较操作符A和操作符B的优先级
bool opAisBiggerThanOpB(string opA, string opB) {
	if (opA == "*" || opA == "/" && opB != "*" && opB != "/" && opB!= "(")
		return true;
	else
		return false;
}

// 中缀表达式转后缀表达式
bool parseFormula(string formula) {
	vector<string> rpn_; // 总输出
	vector<string> rpn_stack; // 符号堆栈
	string sign_; // 临时保存操作数
	for (int i = 0; i < formula.size(); ++i) {
		if (formula[i] != '+'&&formula[i] != '-'&&formula[i] != '*'&&formula[i] != '/' && formula[i] != '(' &&formula[i] != ')') { // 如果是操作数的话就保存起来等待输出
			sign_ += formula[i];
		} else {
			string t_formula;
			t_formula += formula[i];

			// 操作数输出
			if (!sign_.empty()) {
				rpn_.push_back(sign_);
				sign_.clear(); // 清空,保存下一个操作数
			}

			//操作符入栈
			if (t_formula == ")") {
				while (rpn_stack[rpn_stack.size() - 1] != "(") {
					if (rpn_stack.empty())
						return false;
					rpn_.push_back(rpn_stack[rpn_stack.size() - 1]);
					rpn_stack.pop_back();
				}
				rpn_stack.pop_back();
			} else if (rpn_stack.empty())
				rpn_stack.push_back(t_formula);
			else if (t_formula == "(" || rpn_stack[rpn_stack.size() - 1] == "(")
				rpn_stack.push_back(t_formula);
			else if (opAisBiggerThanOpB(t_formula, rpn_stack[rpn_stack.size() - 1]))
				rpn_stack.push_back(t_formula);
			else {
				while (!opAisBiggerThanOpB(t_formula, rpn_stack[rpn_stack.size() - 1]) && rpn_stack[rpn_stack.size() - 1]!="(") {
					rpn_.push_back(rpn_stack[rpn_stack.size() - 1]);
					rpn_stack.pop_back();
					if (rpn_stack.empty())
						break;
				}
				rpn_stack.push_back(t_formula);
			}
		} // end else
	} // end for

	// 处理最后的还留在暂存区的操作数和操作符
	if (!sign_.empty())
		rpn_.push_back(sign_);
	if(!rpn_stack.empty()) {
		for(int i = rpn_stack.size()-1; i>=0; --i)
			rpn_.push_back(rpn_stack[i]);
	}

	// 输出测试
	string rpn;
	for (int i = 0; i < rpn_.size(); ++i) {
		rpn += rpn_[i];
	}
	cout << rpn << endl;
	return true;
}

例如:parseFormula(“5+((1+2)*4)-3”);

输出为:512+4*+3-

3 后缀表达式的计算

对于后缀表达式:5 1 2 + 4 * + 3 –

1. 首先建立一个栈 res 用来保存中间值,从左到右读取后缀表达式,遇到操作数直接入栈,遇到操作符则将栈顶的两个操作数弹出,完成计算后将计算结果压入栈。

2. 首先读取了 512,将它们依次入栈,当前的栈:res: 栈底 5 1 2 栈顶

3. 然后读取到操作符“+”,弹出2,然后弹出1,将1+2的运算结果3压入栈:res: 栈底 5 3 栈顶

4. 然后读取到的操作数“4”入栈,接着读取到” * “,如同上面,将4弹出,将3弹出,计算3*4然后将12压入栈。

5. 后面的操作和前面一样。

6. 结果:14

转载自:https://www.cnblogs.com/whlook/p/7143327.html

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

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/150531.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 【数据分析报告】携程客户分析与流失预测

    【数据分析报告】携程客户分析与流失预测目录一、项目背景与目的二、探索性分析2.1数据指标预览2.2数据概况2.3数据分布2.3.1数据分布总览2.3.2预定日期和入住日期2.3.3访问时间段2.3.4客户价值2.3.5消费能力指数2.3.6价格敏感指数分布2.3.6入住酒店平均价格2.3.7酒店星级偏好2.3.8订单取消率2.3.9用户年订单数分布2.3.10新老客户流失率三、数据预处理3.1去除不需要的字段与重复字段3.2数据类型转换3.3异常值处理3.3.1负数处理3.3.2极值处理3.4缺失值处理3.

    2022年10月18日
  • LaTeX学习:Texlive 2019和TeX studio的安装及使用「建议收藏」

    LaTeX学习:Texlive 2019和TeX studio的安装及使用「建议收藏」文章目录1.LaTex介绍2.Texlive2019的下载和安装(1)下载(2)安装3.TeXstudio的安装以及简单使用(1)设置中文界面(2)添加行号(3)设置编译器与编码(4)第一个简单程序4.扩展1.LaTex介绍LaTeX基于TeX,主要目的是为了方便排版。在学术界的论文,尤其是数学、计算机等学科论文都是由LaTeX编写,因为用它写数学公式非常漂亮。…

  • pycharm连接mysql数据库代码_怎么把Python与pycharm连接

    pycharm连接mysql数据库代码_怎么把Python与pycharm连接PyCharm版本:2020.3使用PyCharm连接数据库(MySQL)前言步骤SQLite总结前言最好使用PyCharmProfessional版步骤前期需要安装包(比如:pymysql)1.在PyCharm右侧工具栏有Database,点击打开如果没有,则在view|ToolWindows|Database选择显示2.点击Database中的+,选择DataSource,选择MySQL3.填写远程连接MySQL数据库的参数Host:

  • 简述django请求生命周期_django请求的生命周期

    简述django请求生命周期_django请求的生命周期Django请求生命周期分析1.客户端发送请求在浏览器输入url地址,例如www.baidu.com,浏览器会自动补全协议(http),变为http://www.baidu.com,现在部分网站都

  • 进程调度与进程切换_模式切换和进程切换有什么区别

    进程调度与进程切换_模式切换和进程切换有什么区别从今天开始,我们将要开启一个新的系列【闪耀计划】,没错!这是今年上半年的一整个系列计划!本专题目的是通过百天刷题计划,通过题目和知识点串联的方式,完成对计算机操作系统的复习和巩固;同时还配有专门的笔记总结和文档教程哦!想要搞定,搞透计算机操作系统的同学,本专栏将会通过模块化的分类,刷够1000道题,为大家提供点对点的考点相关知识轰炸!值得注意的是,本专栏将会通过教程+课后习题的方式来进行巩固教学,课后习题的题量也是算入总题数的哦!

    2022年10月20日
  • C++ 中的getline()函数用法详解

    C++ 中的getline()函数用法详解    遇到了要输入一行字符串的操作,我想除了fgets()的方法(fgets()用法链接),getline()也是可以的,但是我对getline的操作不熟悉,便查阅了很多资料,发现都说的很模糊,借这个机会我想彻底理清楚getline的用法;  网上有说getline有两种用法的,我在这总结一下,一、getline()用的比较多的用法 1) istrea…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号