算法详解——leetcode150(逆波兰表达式)

欢迎来看博主的算法讲解
博主ID:代码小豪

文章目录

    • 逆波兰表达式
    • 逆波兰表达式的作用
    • 代码
    • 将中缀表达式转换成后缀表达式
    • 文末代码

逆波兰表达式

先来看看leetcode当中的原题
在这里插入图片描述
大多数人初见逆波兰表达式的时候大都一脸懵逼,因为与平时常见的表达式不同,很难将常见的表达式与逆波兰表达式联系在一次。

比如:
常见表达式(中缀表达式):((2 + 1) * 3) = 9。
其逆波兰表达式为(后缀表达式):2 1+ 3 *

再解决这个问题之前,首先我们先来了解一下为什么要用逆波兰表达式,而不是中缀表达式呢?

逆波兰表达式的作用

对于人来说,中缀表达式显然是通俗易懂的,但是如果让计算机来处理输入的中缀表达式呢?大家可以想想该如何实现。

显而易见,计算机处理输入的中缀表达式是较为麻烦的。为了解决让计算机便于进行四则运算,逆波兰表达式被发明出来了。

逆波兰表达式的计算方式如下:
将逆波兰表达式从头开始遍历,如果遇到数字,就将数字压入栈中,如果遇到符号,就将栈顶的两个数字弹出,并将计算结果压入栈中。

以:2 1+ 3 *
为例
将2,1压入栈中,遇到+,将1,2弹出,1+2=3,将计算结果的3压入栈中。接着再将3压入栈中,遇到*将3,3弹出,3*3=9,最终结果为9.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过了解后缀表达式的计算方法后,可以发现后缀表达式可以通过栈操作来计算出来,这也是计算机中常见的存储结构之一。这就是逆波兰表达式的意义。

既然已经知道了逆波兰表达式的计算方法,那么完成这道题就不难了。

代码

//以下是栈的操作函数
typedef int datatype;
typedef struct stack
{
	datatype* data;
	int capacity;
	int top;
}stack;

void StackInit(stack* ps);//将栈进行初始化
void StackDestory(stack* ps);//释放栈空间

void StackPush(stack* ps, datatype n);//压栈操作
void StackPop(stack* ps);//出栈操作

datatype StackTopData(stack* ps);//获取栈顶
bool StackEmpty(stack* ps);//判断栈是否为空

//逆波兰表达式的函数
int evalRPN(char** tokens, int tokensSize) {
	stack* rpn = malloc(sizeof(stack));
	StackInit(rpn);//初始化栈空间
	int ret = 0;
	while (tokensSize--)//遍历整个后缀表达式
	{
		if (**tokens == '+' ||//判断符号
			**tokens == '-' ||
			**tokens == '*' ||
			**tokens == '/')
		{
			if (strlen(*tokens) == 1)//由于测试案例中有“-1”这种特殊字符串,因此设计的判断条件。
			{
				int num1 = StackTopData(rpn);
				StackPop(rpn);
				int num2 = StackTopData(rpn);
				StackPop(rpn);

				switch (**tokens)
				{
				case '+':StackPush(rpn, num2 + num1);
					break;
				case'-':StackPush(rpn, num2 - num1);
					break;
				case'*':StackPush(rpn, num2 * num1);
					break;
				case'/':StackPush(rpn, num2 / num1);
					break;
				}
			}
			else {
				int num = 0;
				num = atoi(*tokens);
				StackPush(rpn, num);
			}
		}
		else
		{
			int num = 0;
			num = atoi(*tokens);//将字符转换成整型数据(库函数)
			StackPush(rpn, num);
		}
		tokens++;
	}
	ret = StackTopData(rpn);//将计算结果弹出栈
	StackDestory(rpn);
	return ret;//返回计算结果
}

(为了节省篇幅,将栈的相关操作的函数定义进行省略,如果想要完整版代码,可以再文章末尾查看)

将中缀表达式转换成后缀表达式

力扣当中的原题直接将后缀表达式作为输入,因此在完成这道题时并不需要考虑将中缀表达式转换成后缀表达式。

后缀表达式是为了让计算机能用栈来处理四则运算,所以后缀表达式的主要作用是按照顺序来,展示中缀表达式的优先级。

比如:2 1+ 3 *
其中缀表达式为(2+1)*3
()的优先级高于*,因此先将优先级高的数字进行计算,即(2+1),。接着计算*3,因此总体的计算方式为2+1,接着*3,为了满足前边所讲的栈操作,因此应该写为2 1 +(先算2+1)。然后3*,总体上为2 1 + 3 *.

将中缀表达式转换成后缀表达式的过程也可以用栈来实现,原理如下:
建立一个栈,用于压入符号。遇到数字直接输出就行。
(1)判断压入栈中的符号的优先级是否高于栈顶,如果不高于栈顶,则将栈内的所有符号弹出,再把符号压入栈中
(2)将()括号内的符号弹出栈
以9+(3-1)*3+10/2为例。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

文末代码

typedef int datatype;
typedef struct stack
{
	datatype* data;
	int capacity;
	int top;
}stack;

void StackInit(stack* ps);
void StackDestory(stack* ps);

void StackPush(stack* ps, datatype n);
void StackPop(stack* ps);

datatype StackTopData(stack* ps);
bool StackEmpty(stack* ps);

void StackInit(stack* ps)
{
	if (ps == NULL)
	{
		ps = malloc(sizeof(stack));
		return ;
	}
	ps->data = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

void StackPush(stack* ps, datatype e)
{
	assert(ps);

	if (ps->capacity == ps->top)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		ps->capacity = newcapacity;
		stack* tmp = realloc(ps->data, ps->capacity * sizeof(datatype));
		assert(tmp);
		ps->data = tmp;
	}

	ps->data[ps->top] = e;
	ps->top++;
}

void StackPop(stack* ps)
{
	if (StackEmpty(ps))
	{
		perror("Stack is empty\n");
		return;
	}

	ps->top--;
}

bool StackEmpty(stack* ps)
{
	return ps->top == 0;
}

datatype StackTopData(stack* ps)
{
	if (StackEmpty(ps))
	{
		perror("Stack is empty\n");
		exit(1);
	}
	return ps->data[ps->top - 1];
}

void StackDestory(stack* ps)
{
	assert(ps);
	free(ps->data);
	ps->data = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

int evalRPN(char** tokens, int tokensSize) {
	stack* rpn=malloc(sizeof(stack));
	StackInit(rpn);
	int ret = 0;
	while (tokensSize--)
	{
		if (**tokens == '+' ||
			**tokens == '-' ||
			**tokens == '*' ||
			**tokens == '/')
		{
			if (strlen(*tokens) == 1)
			{
				int num1 = StackTopData(rpn);
				StackPop(rpn);
				int num2 = StackTopData(rpn);
				StackPop(rpn);

				switch (**tokens)
				{
				case '+':StackPush(rpn, num2 + num1);
					break;
				case'-':StackPush(rpn, num2 - num1);
					break;
				case'*':StackPush(rpn, num2 * num1);
					break;
				case'/':StackPush(rpn, num2 / num1);
					break;
				}
			}
			else {
				int num = 0;
				num = atoi(*tokens);
				StackPush(rpn, num);
			}
		}
		else
		{
			int num = 0;
			num = atoi(*tokens);
			StackPush(rpn, num);
		}
		tokens++;
	}
	ret = StackTopData(rpn);
	StackDestory(rpn);
	return ret;
}

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

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

相关文章

C语言学习笔记,学懂C语言,看这篇就够了!(中)

附上视频链接:X站的C语言教程 目录 第8章、函数8.1 函数是什么8.2 函数的分类8.2.1 库函数8.2.1.1 如何使用库函数 8.2.2 自定义函数 8.3 函数参数8.3.1 实际参数(实参)8.3.2 形式参数(形参) 8.4 函数调用8.4.1 传值调用8.4.2 传址调用8.4.3 练习 8.5 函数的嵌套调…

如何使用ArcGIS Pro进行坡度分析

坡度分析是地理信息系统中一种常见的空间分析方法,用于计算地表或地形的坡度,这里为大家介绍一下如何使用ArcGIS Pro进行坡度分析,希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的DEM数据,除了DEM数据&…

Python爬虫:http和https介绍及请求

HTTP和HTTPS 学习目标: 记忆 http、https的概念和区别记忆 浏览器发送http请求的过程记忆 http请求头的形式记忆 http响应头的形式了解 http响应状态码 1 为什么要复习http和https 在发送请求,获取响应的过程中 就是发送http或https的请求&#xff0c…

自然语言发展历程

一、基础知识 自然语言处理:能够让计算理解人类的语言。 检测计算机是否智能化的方法:图灵测试 自然语言处理相关基础点: 基础点1——词表示问题: 1、词表示:把自然语言中最基本的语言单位——词,将它转…

中国电子学会2021年9月份青少年软件编程Sc ratch图形化等级考试试卷四级真题

【 单选题 】 1.下面哪个选项程序可以交换下图列表中第2项和第3项的位置? A: B: C: D: 2.雷峰塔景区的门票价格政策是:成人40元/人;6周岁(含6周岁)以下的实行免票&#…

常用MII接口详解

开放式系统互连 (OSI) 模型 七层开放系统互连 (OSI) 模型中,以太网层 位于最底部两层 - 物理层和数据链路层。 从百兆以太网接口开始 首先是百兆以太网规定的两种接口 介质无关接口 (MII) Media Independent Interface 介质相关接口 (MDI) Medium Depen…

manjaro 安装 wps 教程

内核: Linux 6.6.16.2 wps-office版本: 11.10.11719-1 本文仅作为参考使用, 如果以上版本差别较大不建议参考 安装wps主体 yay -S wps-office 安装wps字体 (如果下载未成功看下面的方法) yay -S ttf-waps-fonts 安装wps中文语言 yay …

如何用YOLOv8实现图像分割

1. 介绍 在之前的文章中,介绍了如何使用 YOLOv8 在不同的编程语言来检测图片中的对象。然而,YOLOv8 还可以把检测到的目标图像分割出来,本篇文章将介绍如何使用YOLOv8做图片分割。 对象检测的结果是所有检测到的对象的边界框。图像分割的结果是所有检测到的对象的蒙版。它是…

一篇文章简单介绍YOLO v1到v8的演变

大家好,YOLO(You Only Look Once)是一种流行的目标检测库,它的第一个版本在2015年发布。YOLO工作速度很快,提供了良好的结果,而且预训练模型是公开可用的。该模型迅速变得流行,该项目至今仍在积…

ai学习前瞻-python环境搭建

python环境搭建 Python环境搭建1. python的安装环境2. MiniConda安装3. pycharm安装4. Jupyter 工具安装5. conda搭建虚拟环境6. 安装python模块pip安装conda安装 7. 关联虚拟环境运行项目 Python环境搭建 1. python的安装环境 ​ python环境安装有4中方式。 从上图可以了解…

python之数组,链表,栈,队列

1.数组 优点: 索引操作速度快:通过索引可以直接访问元素,因此索引操作的时间复杂度是 $O(1)$,即常数级 缺点: 插入、删除元素慢: 如果需要在中间或开始位置插入或删除元素,可能需要移动大量…

漫漫数学之旅036

文章目录 经典格言数学习题古今评注名人小传 - 爱因斯坦 经典格言 纯数学在其领域内是逻辑思想的诗歌。——阿尔伯特爱因斯坦 “纯数学在其领域内是逻辑思想的诗歌”这句话体现了爱因斯坦对数学的深刻理解和热爱。在这句话中,爱因斯坦将纯数学比作诗歌,…

mmdetection如何计算准确率、召回率、F1值

1、训练 python tools/train.py configs/fcos/fcosrdweed3.py 2、测试 这一步要加–outresult.pkl,才能计算准确率和召回率 python tools/test.py configs/fcos/fcosrddweed3.py work_dirs/fcosrddweed3/epoch_300.pth --outresultfcos.pkl3、计算准确率和召回率…

三维GIS的业务导向

的确,目前三维GIS以做特效居多,酷炫、亮眼,从二维转到三维,第一眼就给人眼前一亮的感觉,就凭这一项,很多客户就会买单,GIS的客户以政府、科研院所、特种行业为主,买过一次单后&#…

riscv简单常用汇编指令xv6

文章目录 前言entry.Smretasm volatileread csrwrite csrriscv常见csr寄存器 ecall, 系统调用指令cpu执行异常处理指令的三种事件 异常处理相关寄存器用户态trapsret指令页表切换操作用户态系统调用过程总结 内核态trap缺页异常 中断与设备驱动Locking调度文件系统操作系统拥有…

Docker完整版(一)

Docker完整版(一) 一、Docker概述1.1、Docker简介1.2、Docker的用途1.3、容器与虚拟机的区别1.4、Docker系统架构1.5、Docker仓库 二、Docker引擎2.1、Docker引擎架构2.2、Docker引擎分类2.3、Docker引擎的安装2.4、Docker镜像加速器 三、Docker镜像3.1、…

Android 完整SDK项目中添加对应的JNI与底层通信

安卓应用发消息给底层 近日需要写一个安卓app和底层发消息,这就涉及到java如何到c层的一个逻辑,app已经写好,就差发个消息了。至于如何对接底层,得和写底层的人进一步沟通,本文笔者只写从java层通信到cpp,…

视频远程监控平台EasyCVR集成后播放只有一帧画面的原因排查与解决

智慧安防视频监控平台EasyCVR能在复杂的网络环境中(专网、局域网、广域网、VPN、公网等)将前端海量的设备进行统一集中接入与视频汇聚管理,平台可支持的接入协议包括:国标GB28181、RTSP/Onvif、RTMP,以及厂家的私有协议…

C++ 字符串OJ

目录 1、14. 最长公共前缀 2、 5. 最长回文子串 3、 67. 二进制求和 4、43. 字符串相乘 1、14. 最长公共前缀 思路一:两两字符串进行比较,每次比较过程相同,可以添加一个函数辅助比较,查找最长公共前缀。 class Solution { pu…

Vue.set:Vue中的数据绑定利器

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…