。中缀表达式转后缀表达式:

中缀表达式转后缀表达式遵循以下原则:

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;
}

表达式求值(中缀转后缀及后缀表达式求值)相关推荐

  1. nyoj 1272 表达式求值(中缀式转后缀式)

    表达式求值 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式. 2. 如果 X 和 Y 是 表达式,则 X+ ...

  2. 使用栈解决的一类经典问题:表达式转换及求值;中缀表达式;前缀表达式,后缀表达式,中缀转前缀;中缀转后缀;后缀表达式求值;波兰式,逆波兰式

    文章目录 背景知识 表达式转换问题(考研经典) 一:手工转换 (1)中缀转前缀和中缀转后缀 (2)前缀转中缀和后缀转中缀 二:用栈实现表达式转换 (1)中缀转后缀 (2)中缀转前缀 表达式计算问题(使 ...

  3. 由中缀表达式求后缀、前缀表达式cpp代码

    前缀中缀后缀定义 一个表达式树.前序遍历得到前缀,中序遍历得到中缀,后序遍历得到后缀.单纯的中缀表达式会引起计算歧义,所以为了计算一般要完全括号化:或者将中缀转换为前缀或者后缀.注意:前缀和后缀没有歧 ...

  4. 前缀表达式计算、中缀表达式计算、后缀表达式计算

    首先要知道什么是前缀表达式,什么是中缀表达式,什么是后缀表达式 所谓的中缀表达式就是类似于这种的运算 1+((2+3)×4)-5 所谓的前缀表达式就是符号在两个操作数的前面 - + 1 × + 2 3 ...

  5. 表达式树前缀中缀后缀表达式

    表达式树( expression tree ), 表达式树的树叶是操作数( operand ),比如常数或变量,而其他的节点为操作符( operator )如: 由于这里所有的操作都是二元的,因此这棵 ...

  6. 中缀、后缀、前缀表达式

    一.简介 对于1+((2*3)-4)/2 的数学表达式怎么求值? 分析: 数学表达式求值有优先级,不能简单的从左往右依次计算, 需要从优先级高的开始计算 中缀表达式是一种通用的算术或逻辑公式表示方法, ...

  7. java 中缀转后缀并计算_Java实现表达式计算(中缀转后缀)

    定义: 中缀表达式:我们平时写的数学表达式一般为中缀表达式,如"5+2*(3*(3-1*2+1))",直接拿中缀表达式直接让计算机计算表达式的结果并不能做到. 后缀表达式:把中缀表 ...

  8. 表达式计算:后缀表达式求解 以及 中缀表达式转换为后缀表达式

    后缀表达式 后缀表达式格式: 不包含括号,运算符放在两个运算对象的后面. 后缀表达式运算规则: (从左向右) 所有计算均按运算符出现的顺序(不再考虑乘除优先于加减这种运算符的优先规则),严格从左向右进 ...

  9. C语言实现中缀转后缀并计算表达式结果

    文章目录 一.问题描述 二.AC代码 三.注意点 四.实现思路/代码解析 一.问题描述 [问题描述] 从标准输入中读入一个整数算术运算表达式,如5 - 1 * 2 * 3 + 12 / 2 / 2   ...

最新文章

  1. Python抓取新浪新闻数据(三)
  2. pip install lxml 总是失败
  3. Windows Server查看和记录远程登录信息的方法
  4. 嵌入式开发板上常用术语
  5. 统计学习方法 第一章 学习笔记
  6. axios post body参数_09-axios
  7. SQL Server表分区
  8. 自动化测试学习之路--java String、StringBuilder
  9. 中相对路径与绝对路径的写法_相对路径和绝对路径?简洁易懂解释+实例
  10. 轻量级数据库中间件利器Sharding-JDBC深度解析(有彩蛋)
  11. 前端学习(799):根据位置返回字符
  12. Linux内核的Makefile和kconfig解读
  13. 服务端开发——云服务器的端口转发设置(SSH隧道)
  14. 程序员懂算法玩“淮安掼蛋”是否更有优势?
  15. xp访问服务器显示没有权限,xp无法访问2008R2共享
  16. C语言学习笔记---浮点函数modf()和fmod()
  17. Oracle PL/SQL中的循环处理(sql for循环)
  18. 传递集合对象_【Java学习笔记(九)】之集合的要点介绍
  19. 华为海思智能手机处理器及其参数对比
  20. Petalinux移除module或app的方法

热门文章

  1. 常见的css换行样式
  2. Windows本地服务器搭建(微信公众号开发)
  3. 股票上涨的本质是什么
  4. PIM-DM的扩散-剪枝
  5. 数据库中的三级模式和二级映射
  6. 从月薪3500到700万 我在上海奋斗的五年
  7. 智慧城市”的兴起,3D动画对智慧交通系统可以助力多少?
  8. 圆周率for python
  9. 上市首日股价大跌,美国餐饮SaaS第一股Olo不够“香”吗?
  10. RDD -- flatmap