C++:后缀表达式
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). 首先读取了 5、1、2,将它们依次入栈,当前的栈:
res:
栈底5 1 2栈顶
(3). 然后读取到操作符"+",弹出2,然后弹出1,将
1+2的运算结果3压入栈:
res:
栈底5 3栈顶
(4). 然后读取到的操作数"4"入栈,接着读取到" * ",如同上面,将4弹出,将3弹出,计算
3*4然后将12压入栈。
(5). 后面的操作和前面一样。
(6). 结果:14
C++:后缀表达式的更多相关文章
- sicily 中缀表达式转后缀表达式
		题目描述 将中缀表达式(infix expression)转换为后缀表达式(postfix expression).假设中缀表达式中的操作数均以单个英文字母表示,且其中只包含左括号'(',右括号‘)’ ... 
- 利用stack结构,将中缀表达式转换为后缀表达式并求值的算法实现
		#!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving with Algorithms and Da ... 
- RPN-逆波兰计算器-中缀表达式转后缀表达式-javascript
		1.利用栈(Stack)来存储操作数和操作符: 2.包含中缀表达式转后缀表达式的函数,这个是难点,也是关键点: 2.1.将输入字符串转为数组: 2.2.对转换来的字符进行遍历:创建一个数组,用来给存储 ... 
- 中缀表达式转后缀表达式(用于求字符串表达式值)(js栈和队列的实现是通过数组的push和unshift方法插值,pop方法取值)
		中缀表达式:就是我通常用的算术或逻辑公式: 后缀表达式:不包含括号,运算符放在两个运算对象后面,所有的计算按运算符出现的顺序,严格从左向右进行,不用考虑运算符优先级: 如,(2+1)*3 转换后,2 ... 
- 洛谷  P1449 后缀表达式 Label:表达式计算系列
		题目描述 所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级). 如:3*(5–2)+7对应 ... 
- Java堆栈的应用2----------中缀表达式转为后缀表达式的计算Java实现
		1.堆栈-Stack 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ... 
- 数据结构Java实现06----中缀表达式转换为后缀表达式
		本文主要内容: 表达式的三种形式 中缀表达式与后缀表达式转换算法 一.表达式的三种形式: 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3.我们从小做数学题时,一直使用的就是中缀表达式. 后 ... 
- javascript使用栈结构将中缀表达式转换为后缀表达式并计算值
		1.概念 你可能听说过表达式,a+b,a+b*c这些,但是前缀表达式,前缀记法,中缀表达式,波兰式,后缀表达式,后缀记法,逆波兰式这些都是也是表达式. a+b,a+b*c这些看上去比较正常的是中缀表达 ... 
- 《java数据结构与算法》笔记-CH4-8栈结构实现后缀表达式计算结果
		/** * 中缀表达式转换成后缀表达式: 从输入(中缀表达式)中读取的字符,规则: 操作数: 写至输出 左括号: 推其入栈 右括号: 栈非空时重复以下步骤--> * 若项不为(,则写至输出: 若 ... 
- 栈的应用1——超级计算器(中缀与后缀表达式)C语言
		这里要学的程序主要用来实现一个功能——输入表达式输出结果,也就是一个计算器.效果如下: 这个程序主要有两个步骤:1.把中缀表达式转换为后缀表达式:2.计算后缀表达式的结果. 首先先明白几个问题: 1. ... 
随机推荐
- hdu5716
			地址: 题目: 带可选字符的多字符串匹配 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ... 
- 【android】使用RecyclerView和CardView,实现知乎日报精致布局
			完整代码,请参考我的博客园客户端,git地址:http://git.oschina.net/yso/CNBlogs 在写博客园客户端的时候,突然想到,弄个知乎日报风格的简单清爽多好!不需要那么多繁杂的 ... 
- tomcat进程意外退出的问题分析(转)
			原文链接:http://hongjiang.info/why-kill-2-cannot-stop-tomcat/ 节前某个部门的测试环境反馈tomcat会意外退出,我们到实际环境排查后发现不是jvm ... 
- FFmpeg 入门(4):线程分治
			本文转自:FFmpeg 入门(4):线程分治 | www.samirchen.com 概览 上一节教程中,我们使用 SDL 的音频相关的函数来支持音频播放.SDL 起了一个线程来在需要音频数据的时候去 ... 
- 20145302张薇《Java程序设计》第七周学习总结
			20145302 <Java程序设计>第七周学习总结 教材学习内容总结 第十三章 时间的度量 Greenwich Mean Time,格林威治时间,简称GMT时间,由观察太阳而得来: Un ... 
- angularjs中的jqlite的认识理解及操作使用
			刚了解angularjs时,就知道它有个内嵌的轻量级的jquery:jqLite,那时候常于jQuery分不清,其实它们是不一样的.jqLite中,通过angular.element(param)获得 ... 
- MySQL—记录的增删改查操作
			1.插入记录: 方法一:INSERT [INTO] tbl_name [(col_name,···)] {VALUES|VALUE} ({expr |DEFAULT},···),(···),··· 例 ... 
- django的基本用法
			1.项目创建 # 新建一个文件夹DjangoProjects# 切换到需要的文件夹创建虚拟环境 C:\Projects\DjangoProjects>python -m venv test_ve ... 
- 爬虫框架Scrapy之详解
			Scrapy 框架 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页 ... 
- C++ 读取文件所有内容的方法
			方法一 #include <fstream> #include <string> #include <iostream> using namespace std; ... 
