小小算式(1 + 2) * (3 + 4)背后的大道理

目录

前缀表示法(波兰表达式)

中缀表达法

后缀表达法(逆波兰表达式)

三种表达法的相互转换

练习:逆波兰表达式求值


前缀表示法(波兰表达式)

波兰表示法(英语:Polish notation,或波兰记法)是一种逻辑、算术和代数表示方法,其特点是操作符置于操作数的前面,因此也称做前缀表示法。如果操作符的元数是固定的,则语法上不需要括号仍然能被无歧义地解析。波兰记法是波兰数学家扬·武卡谢维奇于1920年代引入的,用于简化命题逻辑。

表达“三加四”时,前缀记法写作“+ 3 4 ”,而不是“3 + 4”。在复杂的表达式中,操作符仍然在操作数的前面,但操作数可能是包含操作符的平凡表达式。 例如,中缀运算式(5 - 6) * 7 ,在前缀表达式中可以表示为:

*(− 5 6) 7

或省略括号:

* - 5 6 7

由于简单的算术运算符都是二元的,该前缀表达式无需括号,且表述是无歧义的。在前面的例子里,中缀形式的括号是必需的,如果将括号移动到:

5 - (6 * 7)

即:

5 - 6 * 7

则会改变整个表达式的值。而其正确的前缀形式是:

- 5 * 6 7

减法运算要等它的两个操作数(5;6和7的乘积)都完成时才会处理。在任何表示法中,最里面的表达式最先运算,而在波兰表达式中,决定“最里面”的是顺序而不是括号。

中缀表达法

中缀表示法(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4)。与前缀表达式(例:+ 3 4 )或后缀表达式(例:3 4 + )相比,中缀表达式不容易被电脑解析逻辑优先顺序,但仍被许多程序语言使用,因为它符合大多数自然语言的写法。

与前缀或后缀记法不同的是,中缀记法中括号是必需的。计算过程中必须用括号将操作符和对应的操作数括起来,用于指示运算的次序。

后缀表达法(逆波兰表达式)

逆波兰表示法(英语:Reverse Polish notation,缩写RPN,或逆波兰记法逆卢卡西维茨记法),是一种由波兰数学家扬·卢卡西维茨于1920年引入的数学表达式形式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法后序表示法[1]。逆波兰记法不需要括号来标识操作符的优先级。

逆波兰结构由弗里德里希·L·鲍尔和艾兹格·迪科斯彻在1960年代早期提议用于表达式求值,以利用堆栈结构减少计算机内存访问。逆波兰记法和相应的算法由澳大利亚哲学家、计算机学家查尔斯·伦纳德·汉布尔在1960年代中期扩充[2][3]。

在1960和1970年代,逆波兰记法广泛地被用于台式计算器,因此也在普通公众(如工程、商业和金融等领域)中使用。

下面大部分是关于二元运算,一个一元运算使用逆波兰记法的例子是阶乘的记法。

逆波兰记法中,操作符置于操作数的后面。例如表达“三加四”时,写作“3 4 + ”,而不是“3 + 4”。如果有多个操作符,操作符置于第二个操作数的后面,所以常规中缀记法的“3 - 4 + 5”在逆波兰记法中写作“3 4 - 5 + ”:先3减去4,再加上5。使用逆波兰记法的一个好处是不需要使用括号。例如中缀记法中“3 - 4 * 5”与“(3 - 4)*5”不相同,但后缀记法中前者写做“3 4 5 * - ”,无歧义地表示“3 (4 5 *) -”;后者写做“3 4 - 5 * ”。

逆波兰表达式的解释器一般是基于堆栈的。解释过程一般是:操作数入栈;遇到操作符时,操作数出栈,求值,将结果入栈;当一遍后,栈顶就是表达式的值。因此逆波兰表达式的求值使用堆栈结构很容易实现,并且能很快求值。

注意:逆波兰记法并不是简单的波兰表达式的反转。因为对于不满足交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法“/ 6 3”的逆波兰记法是“6 3 /”而不是“3 6 /”;数字的数位写法也是常规顺序

以上内容摘自维基百科:

前缀表达式

中缀表达式

后缀表达式

三种表达法的相互转换

前缀表达式可以用二叉树的前序遍历得到,中缀表达式可以用二叉树的中序遍历得到,后缀表达式可以用二叉树的后序遍历得到。在转换过程中,始终以操作符作为根节点

例如,对于中缀表达式:

(1 + 2) * (3 + 4)

对应的二叉树为

将其转化为前缀表达式为

* + 1 2 + 3 4

将其转化为后缀表达式为

1 2 + 3 4 + *

练习:逆波兰表达式求值

题目链接:150. 逆波兰表达式求值 - 力扣(LeetCode)

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
有效的算符为 '+''-''*''/'
每个操作数(运算对象)都可以是一个整数或者另一个表达式。
两个整数之间的除法总是 向零截断
表达式中不含除零运算。
输入是一个根据逆波兰表示法表示的算术表达式。
答案及所有中间计算结果可以用 32 位 整数表示。

思路解析:

对于逆波兰表达式一般用栈的数据结构解决,当表达式中的字符为操作数时,操作数入栈,当表达式中的字符为操作符时,依次弹出两个操作数,进行对应操作符的运算

参考代码:

C语言代码

使用C语言及栈来解决时,需要注意下面的问题

  1. 因为题目给的运算式是单个字符串,在比较时需要使用到strcmp函数,而不是直接使用==进行判断
  2. 因为*的ASCII值小于其余三个运算符,并且数字可能存在负数,所以在处理减号不入栈时需要处理负数的情况
  3. 设计栈时,可以直接使用实际实现的栈数据结构,也可用一个空数组来模拟栈
// 使用C语言和栈解决问题
// 栈的声明
typedef int STDataType;
typedef struct stack
{
    STDataType* data;
    int top;      // 栈顶位置
    int capacity; // 元素个数
} ST;

// 栈的初始化
void STInit(ST* st);
// 栈的销毁
void STDestroy(ST* st);
// 数据入栈
void STPush(ST* st, STDataType x);
// 数据出栈
void STPop(ST* st);
// 判断栈是否为空
bool STEmpty(ST* st);
// 获取栈元素
STDataType STTop(ST* st);

// 栈的实现
// 栈的初始化
void STInit(ST* st)
{
    // 判断是否存在队列
    assert(st);
    // 初始化队列
    st->data = NULL;
    st->top = 0; // 栈顶指针指向存储数据的下一个位置,代表栈内无数据
    // st->top = -1;//栈顶指针指向存储数据的位置,代表栈内无数据
    st->capacity = 0;
}

// 栈的销毁
void STDestroy(ST* st)
{
    // 确保有栈的存在
    assert(st);
    // 销毁栈
    free(st->data);
    st->data = NULL;
    st->top = st->capacity = 0;
}

// 数据入栈
void STPush(ST* st, STDataType x)
{
    // 确保有栈的存在
    assert(st);
    // 向top位置增加数据,并使top向后移动
    // 需要判断栈的容量大小
    if (st->top == st->capacity)
    {
        // 如果栈的空间为0,则开辟四个空间,如果栈容量不为0,则扩容原来容量的2倍
        int newCapacity = st->capacity == 0 ? 4 : st->capacity * 2;
        STDataType* tmp = (STDataType*)realloc(st->data, sizeof(STDataType) * newCapacity);
        assert(tmp);
        st->data = tmp;
        st->capacity = newCapacity;
    }

    // 数据压栈并改变top
    st->data[st->top++] = x;
}
// 数据出栈
void STPop(ST* st)
{
    // 确保有栈的存在
    assert(st);
    // 确保栈不会越界
    assert(!STEmpty(st));

    // 直接移动top指针,“看不见即删除”
    st->top--;
}
// 判断栈是否为空
bool STEmpty(ST* st)
{
    // 确保有栈的存在
    assert(st);
    // 栈为空返回真,栈不为空返回假
    return st->top == 0; // 判断表达式返回值只有1和0,如果为真返回1(true),如果为假返回0(false)
}
// 获取栈元素
STDataType STTop(ST* st)
{
    // 确保栈存在
    assert(st);
    // 确保栈不为空
    assert(!STEmpty(st));
    // top为栈内数据的下一个位置,要获取当前位置的元素需要-1操作
    return st->data[st->top - 1];
}

int evalRPN(char** tokens, int tokensSize) {
    ST st;
    STInit(&st);

    for (int i = 0; i < tokensSize; i++)
    {
        //当遇到操作数时进栈
        if (((strcmp(tokens[i], "+") > 0) + (strcmp(tokens[i], "-") >= 0 && atoi(tokens[i]) < 0) + (strcmp(tokens[i], "*") > 0) + (strcmp(tokens[i], "/") > 0)) > 2)
        {

            STPush(&st, atoi(tokens[i]));
        }
        else
        {
            //当遇到操作符时出栈运算
            int num1 = STTop(&st);
            STPop(&st);
            int num2 = STTop(&st);
            STPop(&st);

            if (strcmp(tokens[i], "+") == 0)
            {
                STPush(&st, (num2 + num1));
            }

            if (strcmp(tokens[i], "-") == 0)
            {
                STPush(&st, (num2 - num1));
            }

            if (strcmp(tokens[i], "*") == 0)
            {
                STPush(&st, (num2 * num1));
            }

            if (strcmp(tokens[i], "/") == 0)
            {
                STPush(&st, (num2 / num1));
            }
        }
    }
    int ans = STTop(&st);
    STPop(&st);
    return ans;
}

C++代码后续补充……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/526087.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第四十七周:文献阅读+AGCN+Wavenet network

目录 摘要 Abstract 文献阅读&#xff1a;结合自适应图卷积和CNN-LSTM的多站点水质预测模型 现有问题 提出方法 方法论 Adaptive graph convolution network&#xff08;自适应图卷积网络&#xff09; WaveNet network&#xff08;WaveNet网络&#xff09; CNN-LSTM混…

php反序列化漏洞——phar反序列化漏洞

一.什么是phar文件 类比java语言 JAR是开发Java程序一个应用&#xff0c;包括所有的可执行、可访问的文件&#xff0c;都打包进了一个JAR文件里使得部署过程十分简单。 PHAR("Php ARchive")是PHP里类似于JAR的一种打包文件 对于PHP 5.3 或更高版本&#xff0c;Ph…

【UE 网络】DS框架学习路线

目录 0 引言1 如何学习DS框架1. 熟悉Unreal Engine基础2. 学习网络编程基础3. 掌握UE网络概念4. 实践和实验5. 加入社区和论坛6. 官方示例和案例研究7. 专业书籍和在线课程 2 DS框架重要知识点有哪些1. 网络复制2. 远程过程调用&#xff08;RPC&#xff09;3. 客户端服务器架构…

0点起C语言

用sizeof()来查看在你的平台上到底占用多少你多少字节的内存。 Int x sizeof(int); Int xsizeof(shrt int); Int xsizeof(long); Int xsizeof(long double); 等等。 http://www.enet.com.cn/article/2012/0822/A20120822153730_2.shtml #—是个预处理的标志&#xff0c;表示对文…

如何本地搭建Discuz论坛并实现无公网IP远程访问

文章目录 前言1.安装基础环境2.一键部署Discuz3.安装cpolar工具4.配置域名访问Discuz5.固定域名公网地址6.配置Discuz论坛 前言 Crossday Discuz! Board&#xff08;以下简称 Discuz!&#xff09;是一套通用的社区论坛软件系统&#xff0c;用户可以在不需要任何编程的基础上&a…

自动化测试的6大适用场景

不能代替手工测试&#xff0c;因为自动化测试有适用场景&#xff1a;自动化测试的6大适用场景 自动化测试可以在短时间内执行大量的测试任务&#xff0c;缩短了测试时间和人工成本&#xff1b;而自动化测试脚本可以重复执行&#xff0c;提高了测试效率&#xff1b;而通过自动化…

【C++】流程控制语句:跳转语句之Break

在C编程语言中&#xff0c;流程控制不仅包括循环和条件分支&#xff0c;还包括一类特别重要的语句——跳转语句。 这类语句允许程序在执行过程中“打破”常规流程&#xff0c;转而执行其他位置的代码。 C提供了四种跳转语句&#xff1a;break、continue、goto 以及 return。…

充电桩项目,开源啦!

好&#xff0c;我是田哥 很多人&#xff0c;最近都在关注我的充电桩项目&#xff0c;之前建了一个微服务架构的项目&#xff0c;也有单体项目的代码开源。 今天&#xff0c;我把最新版微服务架构的充电桩项目源代码开源。 充电桩的输入端与交流电网直接连接&#xff0c;输出端都…

【线段树】【前缀和】:1687从仓库到码头运输箱子

本题简单解法 C前缀和算法的应用&#xff1a;1687从仓库到码头运输箱子 本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 线段树 LeetCode1687从仓库到码头运输箱子 你有一辆货运卡车&#xff0c;你需要用这一辆车…

【Vue】响应式原理与ref

首先讲讲JS中的Proxy JavaScript 运行环境包含了一些不可枚举、不可写入的对象属性&#xff0c;然而在 ES5 之前开发者无法定义他们自己的不可枚举属性或不可写入属性。ES5 引入 Object.defineProperty() 方法以便开发者在这方面能够像 JS 引擎那样做。 ES6 为了让开发者能进…

阿里云服务器可以干嘛?阿里云服务器八大用途介绍

阿里云服务器可以干嘛&#xff1f;能干啥你还不知道么&#xff01;简单来讲可用来搭建网站、个人博客、企业官网、论坛、电子商务、AI、LLM大语言模型、测试环境等&#xff0c;阿里云百科aliyunbaike.com整理阿里云服务器的用途&#xff1a; 阿里云服务器活动 aliyunbaike.com…

springboot实现上传文件接口(简单版)

使用springboot实现一个最简单版本的上传文件接口 private String uploadPath "C:/imageFiles";RequestMapping(value "/upload", method RequestMethod.POST)private Result upload( RequestParam("modelName") String modelName,RequestPar…

前端实现拖拽div修改宽度,用于菜单栏等多处场景

1、演示 2、 比较简单&#xff0c;直接上源码&#xff08;内部有注释&#xff09; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-…

鸿蒙内核源码分析 (并发并行篇) | 内核如何管理多个 CPU?

理解并发概念 并发&#xff08;Concurrent&#xff09;: 多个线程在单个核心运行&#xff0c;同一时间只能一个线程运行&#xff0c;内核不停切换线程&#xff0c;看起来像同时运行&#xff0c;实际上是线程被高速的切换. 通俗好理解的比喻就是高速单行道&#xff0c;单行道指…

【canvas】canvas的基础使用(一):创建canvas

canvas Canvas API 提供了一个通过JavaScript 和 HTML的<canvas>元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。 Canvas API 主要聚焦于 2D 图形。 canvas元素 <canvas> 元素可被用来通过 JavaScript&#xff…

【Figma】安装指南及基础操作

先前做UI设计一直都是用PS等绘图软件设计&#xff0c;但发现在纠结像素和排版问题上会花很多时间&#xff0c;再加上AI没来得及上手&#xff0c;就需要迅速出成图&#xff0c;此时通过论坛发现了figma&#xff0c;基本上可以满足足够的需求&#xff0c;并且可以在windows系统上…

程序员如何搞副业

#程序员如何搞副业&#xff1f;# 在快速发展的IT行业中&#xff0c;程序员作为技术骨干&#xff0c;通常拥有扎实的编程能力和丰富的项目经验。然而&#xff0c;随着职业生涯的深入&#xff0c;许多程序员开始思考如何进一步提升自我价值&#xff0c;实现更多的经济收益。副业成…

身份证实名认证接口的价格一般是多少呢?基于PHP身份核验接口

身份证实名认证接口分为身份证二要素、三要素、三要素人像核验接口&#xff0c;被广泛的应用于婚恋、交友、电商等等一系列行业领域&#xff0c;身份证实名认证需要实时数据&#xff0c;对于数据源来说也需要可靠&#xff0c;那么&#xff0c;身份证实名认证的价格是不是很贵呢…

Yolov8-pose关键点检测:特征融合 | CAMixing:卷积-注意融合模块和多尺度提取能力 | 2024年4月最新成果

💡💡💡本文独家改进:CAMixingBlock更好的提取全局上下文信息和局部特征,包括两个部分:卷积-注意融合模块和多尺度前馈网络; 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特征的提取能力;2)放在detect前面,增强detect提取能力; 提供多种改进方…

HarmonyOS实战开发-如何使用调用系统任务管理的能力。

介绍 本示例通过调用系统任务管理的能力&#xff0c;使用ohos.application.missionManager 、ohos.multimedia.image 等接口完成对系统任务执行锁定、解锁、清理、切换到前台等操作。 效果预览 使用说明 1.下拉“获取系统任务信息”&#xff0c;获取当前系统任务的包名、运行…