表达式求值(中缀转后缀及后缀表达式求值)
。中缀表达式转后缀表达式:
中缀表达式转后缀表达式遵循以下原则:
1.遇到操作数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。
经过上面的步骤,得到的输出既是转换得到的后缀表达式。
举例:a+b*c+(d*e+f)g ———> abc+de*f+g*+
图示上述过程:
因为比较懒,而刚好在网上看到画的还不错的图,所以就直接贴过来了哦。希望作者不要怪罪哦。。。
遇到a,直接输出:
遇到+,此时栈为空,入栈:
遇到b,直接输出:
遇到*,优先级大于栈顶符号优先级,入栈:
遇到c,输出:
到+,目前站内的与+优先级都大于或等于它,因此将栈内的,+依次弹出并且输出,并且将遇到的这个+入栈:
遇到(,将其入栈:
遇到d,直接输出:
遇到*
,由于的优先级高于处在栈中的(,因此入栈:
遇到e,直接输出:
遇到+,栈顶的优先级高于+,但是栈内的(低于+,将出栈输出,+入栈:
遇到f,直接输出:
遇到),弹出栈顶元素并且输出,直到弹出(才结束,在这里也就是弹出+输出,弹出(不输出:
遇到*,
优先级高于栈顶+,将*入栈
遇到g,直接输出: :
此时已经没有新的字符了,依次出栈并输出操作直到栈为空:
因为后缀表达式求值过程较为简单:
所以在这里我只进行简单说明:
1.扫描后缀表达式:
①如果是数字,则让其进栈
②若为操作符,则从栈中取出两个操作数,先取出的作为右操作数,后取出的作为左操作数,然后进行该操作符的运算,并使其结果入栈。
③重复上述过程,直至表达式扫描完成。
2.最终栈中只留一个元素—–>即就是结果。
下面代码实现中缀转后缀以及后缀表达式求值:
使用的栈是自定义栈(自己实现的):
//stack.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<cassert>//------------使用类型萃取来拷贝栈内元素-------------
struct _TrueType
{bool Get(){return true;}
};struct _FalseType
{bool Get(){return false;}
};template<class _Tp>
struct TypeTraits
{typedef _FalseType _IsPODType;
};template<>
struct TypeTraits<bool>
{typedef _TrueType _IsPODType;
};template<>
struct TypeTraits<int>
{typedef _TrueType _IsPODType;
};template<>
struct TypeTraits<unsigned int>
{typedef _TrueType _IsPODType;
};template<>
struct TypeTraits<char>
{typedef _TrueType _IsPODType;
};template<>
struct TypeTraits< float >
{typedef _TrueType _IsPODType;
};template<>
struct TypeTraits< double >
{typedef _TrueType _IsPODType;
};template<>
struct TypeTraits<long>
{typedef _TrueType _IsPODType;
};template<>
struct TypeTraits< unsigned long>
{typedef _TrueType _IsPODType;
};template<class T>
void Copy(T* dst, T* src, size_t size)
{if (TypeTraits<T>::_IsPODType().Get()){memcpy(dst, src, size);}else{for (int i = 0; i < size; ++i){dst[i] = src[i];}}
}template<class T>
struct TypeTraits< T* >
{typedef _TrueType _IsPODype;
};//-------------------------栈的基本操作----------------
template<class T>
class Stack
{
public://构造函数Stack(int capacity = 10):_pData(NULL), _capacity(capacity), _size(0){_pData = new T[capacity];}//拷贝构造函数Stack(const Stack<T>& s):_pData(new T[s._capacity]), _size(s._size), _capacity(s._capacity){for (int i = 0; i < _size; ++i){_pData[i] = s._pData[i];}}//赋值运算符函数Stack& operator=(Stack<T> s){std::swap(_pData, s._pData);_size = s._size;_capacity = s._capacity;return *this;}//入栈void Push(const T& data){CheckCapacity();_pData[_size++] = data;}//出栈void Pop(){if (!Empty()){--_size;}}//获取栈顶元素T& Top(){if (!Empty()){return _pData[_size - 1];}}const T& Top()const{if (!Empty()){return _pData[_size - 1];}}size_t Size()const{return _size;}bool Empty()const{return 0 == _size;}//析构函数(释放资源)~Stack(){if (_pData){delete[] _pData;_pData = NULL;}}private://增容void CheckCapacity(){if (_size >= _capacity){_capacity = 2 * _capacity + 3;T* tmp = new T[_capacity];//拷贝原数据//释放旧空间//指向新空间//需要进行类型萃取Copy<T>(_pData, tmp, _size);delete[] _pData;_pData = tmp;}}T* _pData;int _capacity;int _size;
};//----------------------------------------------------------
//需要用到的函数的声明
int GetPriority(char ch, int flag);//获取优先级
bool IsOperator(char ch);//判断是否为操作符
void prefixionToSuffix(char* dst, char* src);//中缀表达式转后缀表达式
int SuffixToValue(char *suffix, char *prefixion);//后缀表达式求值
中缀表达式转后缀表达式:
//prefixionToSuffix.cpp
#include"Stack.h"//flag为1时表示栈内优先级 flag为0表示栈外优先级
int GetPriority(char ch, int flag)
{if (ch == '+' || ch == '-'){if (flag){return 3;}else{return 2;}}else if (ch == '*' || ch == '/' || ch == '%'){if (flag){return 5;}else{return 4;}}else if (ch == '('){if (flag){return 1;}return 6;}else if (ch == ')'){if (flag){return 6;}else{return 1;}}
}bool IsOperator(char ch)
{if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' || ch == '(' || ch == ')'){return true;}return false;
}//中缀表达式转后缀表达式
void prefixionToSuffix(char* dst, char* src)
{assert(dst);assert(src);Stack<char> s;char * cur = src;char* tmp = dst;while (*cur != '\0'){if (*cur >= '0' && *cur <= '9'){*tmp++ = *cur;cur++;continue;}else if (IsOperator(*cur)){if (s.Empty())//如果栈为空,直接入栈{s.Push(*cur);cur++;}else//如果栈不空,则需要判断栈顶元素和当前操作符的优先级{if (*cur == ')'){while (*cur == ')' && s.Top() != '('){*tmp++ = s.Top();s.Pop();}s.Pop();cur++;}if (GetPriority(*cur, 0) > GetPriority(s.Top(), 1)){s.Push(*cur);cur++;}else{while (!s.Empty() && GetPriority(*cur, 0) < GetPriority(s.Top(), 1)){*tmp++ = s.Top();s.Pop();}s.Push(*cur);cur++;}}}else{*tmp++ = *cur++;}}while(!s.Empty()){*tmp++ = s.Top();s.Pop();}
}
后缀表达式求值:
//SuffixToValue.cpp
#include"Stack.h"//12 3 4 + * 6 - 8 2 / +
int SuffixToValue(char *suffix, char *prefixion)
{prefixionToSuffix(suffix, prefixion);Stack<int> s;char* cur = suffix;int res = 0;int tmp = 0;while (*cur != '\0'){if (*cur == '+' || *cur == '-' || *cur == '*' || *cur == '/' || *cur == '%'){char ch = *cur;int right = s.Top();s.Pop();int left = s.Top();s.Pop();switch (ch){case '+':s.Push(left + right);break;case '-':s.Push(left - right);break;case '*':s.Push(left * right);break;case '%':s.Push(left % right);break;case '/':if (right){s.Push(left / right);}break;}cur++;}else if (*cur >= '0' && *cur <= '9'){res = 0;while (!isspace(*cur) && *cur >= '0' && *cur <= '9'){tmp = *cur - '0';res = res * 10 + tmp;cur++;}s.Push(res);//cur++;}else{cur++;}}if (!s.Empty()){res = s.Top();return res;}
}
main.cpp
#include"Stack.h"void Test()
{char prefixion[] = "12 * (3 + 4) - 6 + 8 / 2 ";//保存前缀表达式char suffix[25] = {};//保存后缀表达式int res = SuffixToValue(suffix, prefixion);cout << res << endl;
}int main()
{Test();return 0;
}
表达式求值(中缀转后缀及后缀表达式求值)相关推荐
- nyoj 1272 表达式求值(中缀式转后缀式)
表达式求值 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式. 2. 如果 X 和 Y 是 表达式,则 X+ ...
- 使用栈解决的一类经典问题:表达式转换及求值;中缀表达式;前缀表达式,后缀表达式,中缀转前缀;中缀转后缀;后缀表达式求值;波兰式,逆波兰式
文章目录 背景知识 表达式转换问题(考研经典) 一:手工转换 (1)中缀转前缀和中缀转后缀 (2)前缀转中缀和后缀转中缀 二:用栈实现表达式转换 (1)中缀转后缀 (2)中缀转前缀 表达式计算问题(使 ...
- 由中缀表达式求后缀、前缀表达式cpp代码
前缀中缀后缀定义 一个表达式树.前序遍历得到前缀,中序遍历得到中缀,后序遍历得到后缀.单纯的中缀表达式会引起计算歧义,所以为了计算一般要完全括号化:或者将中缀转换为前缀或者后缀.注意:前缀和后缀没有歧 ...
- 前缀表达式计算、中缀表达式计算、后缀表达式计算
首先要知道什么是前缀表达式,什么是中缀表达式,什么是后缀表达式 所谓的中缀表达式就是类似于这种的运算 1+((2+3)×4)-5 所谓的前缀表达式就是符号在两个操作数的前面 - + 1 × + 2 3 ...
- 表达式树前缀中缀后缀表达式
表达式树( expression tree ), 表达式树的树叶是操作数( operand ),比如常数或变量,而其他的节点为操作符( operator )如: 由于这里所有的操作都是二元的,因此这棵 ...
- 中缀、后缀、前缀表达式
一.简介 对于1+((2*3)-4)/2 的数学表达式怎么求值? 分析: 数学表达式求值有优先级,不能简单的从左往右依次计算, 需要从优先级高的开始计算 中缀表达式是一种通用的算术或逻辑公式表示方法, ...
- java 中缀转后缀并计算_Java实现表达式计算(中缀转后缀)
定义: 中缀表达式:我们平时写的数学表达式一般为中缀表达式,如"5+2*(3*(3-1*2+1))",直接拿中缀表达式直接让计算机计算表达式的结果并不能做到. 后缀表达式:把中缀表 ...
- 表达式计算:后缀表达式求解 以及 中缀表达式转换为后缀表达式
后缀表达式 后缀表达式格式: 不包含括号,运算符放在两个运算对象的后面. 后缀表达式运算规则: (从左向右) 所有计算均按运算符出现的顺序(不再考虑乘除优先于加减这种运算符的优先规则),严格从左向右进 ...
- C语言实现中缀转后缀并计算表达式结果
文章目录 一.问题描述 二.AC代码 三.注意点 四.实现思路/代码解析 一.问题描述 [问题描述] 从标准输入中读入一个整数算术运算表达式,如5 - 1 * 2 * 3 + 12 / 2 / 2 ...
最新文章
- Python抓取新浪新闻数据(三)
- pip install lxml 总是失败
- Windows Server查看和记录远程登录信息的方法
- 嵌入式开发板上常用术语
- 统计学习方法 第一章 学习笔记
- axios post body参数_09-axios
- SQL Server表分区
- 自动化测试学习之路--java String、StringBuilder
- 中相对路径与绝对路径的写法_相对路径和绝对路径?简洁易懂解释+实例
- 轻量级数据库中间件利器Sharding-JDBC深度解析(有彩蛋)
- 前端学习(799):根据位置返回字符
- Linux内核的Makefile和kconfig解读
- 服务端开发——云服务器的端口转发设置(SSH隧道)
- 程序员懂算法玩“淮安掼蛋”是否更有优势?
- xp访问服务器显示没有权限,xp无法访问2008R2共享
- C语言学习笔记---浮点函数modf()和fmod()
- Oracle PL/SQL中的循环处理(sql for循环)
- 传递集合对象_【Java学习笔记(九)】之集合的要点介绍
- 华为海思智能手机处理器及其参数对比
- Petalinux移除module或app的方法