C++:前缀、中缀、后缀表达式互相转换详解

2023-11-13


表达式 定义 示例
前缀表达式 运算符位于操作数之前 - × + 3 4 5 6
中缀表达式 操作符以中缀形式处于操作数的中间 (3 + 4) × 5 - 6
后缀表达式 运算符位于操作数之后 3 4 + 5 × 6 -

前缀式,后缀式是不需要用括号来进行优先级的确定的。

中缀表达式 转为 前缀表达式(波兰式)

遵循以下步骤:

  1. 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
  2. 从右至左扫描中缀表达式;
  3. 遇到操作数时,将其压入S2;
  4. 遇到运算符时,比较其与S1栈顶运算符的优先级:
    4.1 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
    4.2 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
    4.3 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较
  5. 遇到括号时:
    5.1 如果是右括号“)”,则直接压入S1;
    5.2 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃
  6. 重复步骤(2)至(5),直到表达式的最左边;
  7. 将S1中剩余的运算符依次弹出并压入S2;
  8. 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
前缀表达式 逆向求解 中缀表达式

-+1*+2345

思路: 递归,碰到操作符就进入递归。

  • 从右往左扫描先碰到+号,取+号后面两个操作数:2,3 得到:2+3.
  • 继续往左扫碰到*号,取2+3和 4 得到:(2+3)*4
  • 继续往左扫碰到+号,取1和(2+3)*4得到:1+(2+3)*4
  • 继续往左扫碰到-号,取1+(2+3)*4和5得到:1+(2+3)*4-5

中缀表达式 转为 后缀表达式(逆波兰式)

与转换为前缀表达式相似,遵循以下步骤:

  1. 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
  2. 从左至右扫描中缀表达式;
  3. 遇到操作数时,将其压入S2;
  4. 遇到运算符时,比较其与S1栈顶运算符的优先级:
    4.1 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
    4.2 比栈顶高,也将运算符压入S1 (注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
    4.3 比栈顶低或相同,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
  5. 遇到括号时:
    5.1 如果是左括号“(”,则直接压入S1;
    5.2 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
    可以想象成“(”比任何运算符都高,“)”比任何运算符都低。
  6. 重复步骤(2)至(5),直到表达式的最右边;
  7. 将S1中剩余的运算符依次弹出并压入S2;
  8. 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。
后缀表达式 逆向求解 中缀表达式

1 2 3 + 4* 5 - +

基本思路和上面的一样: 递归,碰到操作符就进入递归

  • 从左往右扫描先碰到+号,取+号前面两个操作数:2,3 得到:2+3.
  • 继续往右扫碰到*号,取2+3 和 4 得到:(2+3)*4
  • 继续往右扫碰到-号,取(2+3)*4和5得到:(2+3)*4-5
  • 继续往右扫碰到+号:取(2+3)*4-5和1得到:1+(2+3)*4-5
图解示例:

在这里插入图片描述

代码实现:
// 判断是否为括号
bool isPra(char c) {
    return (c == '(' || c == ')') ? true : false;
}

// 获得符号的优先性
int getPri(char c)
{
    switch (c) {
    case '+':
    case '-':
        return 0;   // 如果是加减,返回0
        break;
    case '*':
    case '/':
        return 1;   // 如果是乘除,返回1
        break;
    case '(':
    case ')':
        return -1;  // 这里将括号设为最低优先级,因此括号不会被弹出,除非遇到右括号
        break;
    default:
        cout << "输入其他运算符\n" << endl;
    }
}

//判断符号的优先性
void check(char c, stack<char>& operator_s, string& suffix) {
    if (operator_s.empty()) {
        operator_s.push(c);
        return;
    }
    
    if (isPra(c)) {
        if (c == '(') {
            operator_s.push(c);
        }
        else {
            // 弹出所有元素直到遇到左括号
            while (operator_s.top() != '(') {
                suffix += operator_s.top();
                operator_s.pop();
            }

            // 遇到左括号,弹出且不加入后缀表达式
            operator_s.pop();
        }
    }
    else {
        // 如果不是括号,比较当前元素,与栈顶元素的优先级
        if (getPri(c) > getPri(operator_s.top())) {
            operator_s.push(c);
        }
        else {
            suffix += operator_s.top();
            operator_s.pop();

            // 递归调用,比较当前符号c与下一个栈顶符号的优先性
            check(c, operator_s, suffix);
        }
    }
}

// 中缀表达式转后缀表达式
string infixToSuffix(string& infix) {
    stack<char> operator_s; // 运算符栈
    string suffix;          // 后缀表达式

    //int num = 0;
    for (int i = 0; i < infix.size(); ++i) {
        if (infix[i] >= '0' && infix[i] <= '9') {
            suffix += infix[i];
        }
        else {
            check(infix[i], operator_s, suffix);
        }
    }

    // 对中缀表达式的遍历结束,将栈中元素加入后缀表达式
    while (!operator_s.empty()) {
        suffix += operator_s.top();
        operator_s.pop();
    }

    return suffix;
}

一个中缀式到其他式子的转换方法(超级简易)~~

这里给出中缀表达式:a+b*c-(d+e)

  1. 按照运算符的优先级对所有的运算单位加括号~

    式子变成:((a+(b* c))-(d+e))

  2. 转换成前缀表达式与后缀表达式

    • 前缀:把运算符号移动到对应的括号前面
      则变成:-( +(a* (bc))+(de))
      把括号去掉:-+a* bc+de 前缀式子出现
    • 后缀:把运算符号移动到对应的括号后面
      则变成:((a(bc)* )+(de)+)-
      把括号去掉:abc* +de+ - 后缀式子出现

相关习题:

  1. 假定有中缀表达式A:1 + (( 2 + 3)* 4 ) – 5,请将它转化为前缀,后缀表达式。
  • 中缀转前缀:(直接转换法)

首先确定表达式表达式A的运算顺序,然后加括号:((1 + (( 2 + 3)* 4 )) – 5 )
从最里面的一层括号开始运算,转换成前缀表达式的方法为:(忽略括号)符号在前,数字在后。

演示过程如下:

  1. ( 2 + 3) => +23
  2. (( 2 + 3)* 4 ) => *+234
  3. (1 + (( 2 + 3) * 4 ))=> +1*+234
  4. ((1 + (( 2 + 3)* 4 )) – 5 )=> -+1*+2345

前缀表达式为:-+1*+2345

  • 中缀转后缀:(直接转换法)

首先确定表达式表达式A的运算顺序,然后加括号:((1 + (( 2 + 3)* 4 )) – 5 )
从最里面的一层括号开始运算,转换成后缀表达式的方法为:(忽略括号)数字在前,符号在后。

演示过程如下:

  1. ( 2 + 3) => 23+
  2. (( 2 + 3)* 4 ) => 23+4*
  3. (1 + (( 2 + 3)* 4 ))=> 123+4*+ [按照运算次序,从左到右排列]
  4. ((1 + (( 2 + 3)* 4 )) – 5 )=> 123+4*+ 5-

后缀表达式为:123 + 4*+ 5 –

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++:前缀、中缀、后缀表达式互相转换详解 的相关文章

随机推荐

  • eclipse里打开图片文件乱码解决方案

    从eclipse中打开工程文件下的图片文件显示乱码 原因是你电脑系统上没有设置图片的默认打开方式 或者是图片的默认打开方式与eclipse不兼容
  • 原始值和引用值

    ECMAScript 变量可以包含两种不同类型的数据 原始值和引用值 原始值就是简单数据类型 引用值则是由多个值构成的对象 原始值 引用值 原始值包括 Undefined Null Boolean Number String Symbol和
  • 【GAN 04】可解释性GAN

    本文是对http www seeprettyface com research notes html的学习笔记 不想让GANs随机生成图片 希望通过控制输入的参数去生成特定的图片 例如 在手写数字图片的生成中 希望通过输入 控制数字 高度以
  • Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Interop.E

    前段时间做了个将Txt中数据导出到Excel中的C 小应用程序 一直都运行很好的 今天突然有同事安装时 报如下错 Exception Text System InvalidCastException Unable to cast COM o
  • android横竖屏切换、键盘推出状态改变的处理

    背景介绍 在编写android小应用的时候 碰到了这样的一个问题 当推开手机的实体键盘时 屏幕由竖屏转换为横屏 此时应用程序的显示界面 Activity 就会被销毁了 这个让人比较郁闷 如何才能让这个activity不被销毁呢 背景分割线
  • 【VUE3】ElementUI--el-date-picker下拉控件样式修改(高亮显示设置)

    ElementUI el date picker下拉控件样式修改 一些废话 事发背景 实现效果 实现思路 总结和完整代码 参考资料 一些废话 默默做前端 分享一些自己在项目需求实现中遇到的奇妙问题 主要是网上搜索不到解决办法自己解决后的总结
  • cell基础概念

    1 spare cell 备用cell 共流片时进行function eco和metal eco使用 使用方法 add spare cells add spare cells cell name spare1 lib cell AND2 O
  • Unity 按键输入系统(一)

    这段时间制作了游戏内的操作系统 主要制作的原因是 在游戏内很多按键是公用的 但是不同位置的处理逻辑不同 比如在最外层界面上 可以使用ESC打开菜单 但是在二级界面里 使用ESC是返回上个界面 如果要使用判断制作的话 会产生很强的耦合性 要在
  • (环境四)python安装pymssql

    1 利用pip安装 用pip安装whl文件 在cmd中输入 pip install pymssql 2 1 3 cp36 cp36m win32 whl 2 安装失败可手动下载 网址 https www lfd uci edu gohlke
  • 如何挑选自媒体平台进行创作?这3个关键需要把握

    应该如何挑选平台进行创作 在这里 介绍两个值得长期坚持的平台 及主要变现方式 1 头条号 阅读量变现 发布文章时 可根据阅读量获取对应广告分成 付费专栏 当账号获取图文原创收益后就能开启付费专栏 用户购买后即可获得收入 签约作者 成为平台签
  • aptitude versus apt-get

    Important UpdateApparently the new version of apt get in Edgy Eft Ubuntu 6 10 has a function that allows you to remove u
  • python作业记录1_字典运用的实例

    帮朋友做了几个作业题目 记录一下 一 某人到超市购买了以下物品 先需要对货物金额进行统计 清单如下图所示 牛奶 65 面包 15 可乐 39 饼干 45 糖果 24 水果 35 8 要求 1 使用字典保存以上数据 2 可乐的金额统计出错 请
  • GNU make 基礎知識點梳理 with tangible examples(01-st 記)

    1 作爲基礎項目的一個示例
  • Linux常见的工具有哪些?

    在Linux系统中 有很多实用的工具和软件可拿来即用 即方便又可以释放双手 节省时间 更是每个运维工程师必须掌握的技能之一 那么Linux常见的工具有哪些 具体请看下文 1 文本编辑器 Vim 一款功能强大的文本编辑器 Emacs 另一款广
  • Python工程师必看的面试问题与解答(中)

    16 在Python中什么是迭代器 在Python中 迭代器用于迭代一组元素 如列表之类的容器 17 什么是Python中的单元测试 Python中的单元测试框架称为unittest 它支持共享设置 自动化测试 测试关闭代码 将测试聚合到集
  • https单向认证和双向认证区别

    关于证书 1 每个人都可以使用一些证书生成工具为自己的https站点生成证书 比如jdk的keytool 大家称它为 自签名证书 但是自己生成的证书是不被互联网承认的 所以浏览器会报安全提示 要求你手动安装证书 只有通过权威的CA机构付费获
  • 网络协议学习笔记 二 tcpdump windump (BY 冷家锋)

    网络协议学习笔记二 作者 冷家锋 刘婷婷 时间 2008 4 3 说明 欢迎转载 无须注明出处 水平有限 译者不保证译文的正确和准确 如因看了本译文而对看官的学习有误导 与译者无关 学习网络和操作系统也有段时间了 总感觉无所进步 打算认真从
  • 请基于matlab,利用BP算法和sigmoid函数,研究反比例函数f(x)=1/x的逼近问题

    好的 我可以用中文回答你的问题 利用BP算法和sigmoid函数来逼近反比例函数f x 1 x 可以按照以下步骤进行 1 准备数据 选择一组反比例函数的数据作为训练集 比如x取1到10 y为对应的1 x值 2 创建神经网络 在Matlab中
  • Python爬虫从入门到精通:(35)CrawlSpider基础_Python涛哥

    CrawlSpider 概念 其实是Spider的一个子类 Spider是爬虫文件中爬虫类的父类 子类的功能一定是多余父类 作用 被用作于专业实现全站数据爬取 将一个页面下所有页面对应的数据进行爬取 基本使用 创建一个工程 cd 工程 创建
  • C++:前缀、中缀、后缀表达式互相转换详解

    文章目录 中缀表达式 转为 前缀表达式 波兰式 前缀表达式 逆向求解 中缀表达式 中缀表达式 转为 后缀表达式 逆波兰式 后缀表达式 逆向求解 中缀表达式 图解示例 代码实现 一个中缀式到其他式子的转换方法 超级简易 相关习题 表达式 定义