09黑马笔记之栈的应用_中缀表达式转后缀表达式

2023-11-09

09黑马笔记之栈的应用_中缀表达式转后缀表达式

1 前提:
1)数字:直接输出。
2)左括号:直接进栈(优先级默认最低)。
3)右括号:将栈顶符号输出,直到匹配到左括号。
4)运算符:1)若一开始没有可比较直接进栈; 2)若栈顶元素优先级低,进栈; 3)若栈顶元素优先级高,将栈顶元素弹出并输出,直至低就进栈。
//最后将栈中的元素遍历弹出输出。
我们以char str = "8+(3-1)5"为例,8先输出,+进栈,左括号直接进栈,3输出,栈顶元素左括号"(“比减号”-"低,进栈。1直接输出,右括号时,此时栈中有“+(-”,将减号弹出并输出,最后弹出左括号。+比乘号低,进栈,5直接输出。栈中还剩乘号和加号,弹出并输出。最终中缀转后缀后应为831-5*+。

我们利用之前写过的链式栈做。
2 栈的头文件:

#ifndef SEQLINKSTACK
#define SEQLINKSTACK

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//使用企业链表实现,也可传统
typedef struct LINKSNODE{
	struct LINKSNODE *next;
}LinkSNode;

//管理链表结构体
typedef struct LINKSTACK{
	LinkSNode head;
	int size;
}LinkStack;

//链式栈初始化
LinkStack* Init_LinkStack();
//入栈
int Push_LinkStack(LinkStack *lstack,LinkSNode *data);
//出栈
int Pop_LinkStack(LinkStack *lstack);
//判断是否为空
int IsEmpty_LinkStack(LinkStack *lstack);
//返回第一个有效元素
LinkSNode *Top_LinkStack(LinkStack *lstack);
//返回栈大小
int Size_LinkStack(LinkStack *lstack);
//清空链式栈
int Clear_LinkStack(LinkStack *lstack);
//释放内存
int Destory_LinkStack(LinkStack *lstack);

#endif

3 栈的实现.c文件:

#include"Seq_LinkStack.h"

//链式栈初始化 ok
LinkStack* Init_LinkStack(){

	LinkStack *lstack=(LinkStack*)malloc(sizeof(LinkStack));
	lstack->head.next=NULL;    
	lstack->size=0;

	return lstack;
}
//入栈 ok
int Push_LinkStack(LinkStack *lstack,LinkSNode *data){

	if(lstack==NULL){
		return -1;
	}
	if(data==NULL){
		return -1;
	}
	//每次都在链表的头结点插入,与顺序栈想反
	//所以每次对头结点操作插入
	data->next =lstack->head.next;
	lstack->head.next=data;

	lstack->size++;

	return 0;
}
//出栈  ok
int Pop_LinkStack(LinkStack *lstack){

	if(lstack==NULL){
		return -1;
	}
	if(lstack->size==0){
		return -1;
	}
	//也是只对头结点操作
	//使头结点指向第二个有效节点
	LinkSNode *first=lstack->head.next;
	lstack->head.next=first->next;  //使head指向第二个元素

	lstack->size--;

	return 0;

}
//判断是否为空
int IsEmpty_LinkStack(LinkStack *lstack){
	if(lstack==NULL){
		return -1;
	}
	if(lstack->size==0){
		return 1;
	}
	
	return 0;
}
//返回第一个有效元素 ok
LinkSNode *Top_LinkStack(LinkStack *lstack){

	if(lstack==NULL){
		return NULL;
	}
	if(lstack->size==0){
		return NULL;
	}
	return lstack->head.next;

}
//返回栈大小  ok
int Size_LinkStack(LinkStack *lstack){

	if(lstack==NULL){
		return -1;
	}

	return lstack->size;
}
//清空链式栈 ok
int Clear_LinkStack(LinkStack *lstack){
	if(lstack==NULL){
		return -1;
	}
	//lstack->head.next=NULL;
	lstack->size=0;

	return 0;
}
//释放内存
int Destory_LinkStack(LinkStack *lstack){
	if(lstack==NULL){
		return -1;
	}
	free(lstack);

	return 0;
}

4 主要实现代码,前面的栈代码看不懂也没关系,直接用就行。

#include"Seq_LinkStack.h"
#include<stdio.h>

//是否为数字
int IsNumber(char p) {
	return p >= '0' && p <= '9';
}
//是否为左括号
int IsLeft(char p) {
	return p == '(';
}
//是否为右括号
int IsRight(char p) {
	return p == ')';
}
//是否为运算符
int IsOperator(char p) {
	return p == '+' || p == '-' || p == '*' || p == '/';
}

//返回运算符号优先级 左括号默认为0
int GetPriority(char c) {
	if (c == '*' || c == '/') {
		return 2;
	}
	if (c == '+' || c == '-') {
		return 1;
	}
	return 0;
}

//链式栈数据节点
typedef struct SNODE {
	LinkSNode node;
	char *p;
}Snode;

void test01() {

	//数字:直接输出
//左括号:直接进栈(优先级默认最低)
//右括号:将栈顶符号输出,直到匹配到左括号
//运算符:1)若一开始没有可比较直接进栈; 2)若栈顶元素优先级低,进栈; 3)若栈顶元素优先级高,将栈顶元素弹出并输出,直至低就进栈
//最后将栈中的元素遍历弹出输出

//中缀转后缀后应为831-5*+
	char *str = "8+(3-1)*5";
	char *p = str;

	//创建栈
	LinkStack *stack = Init_LinkStack();

	//遍历整个字符串
	while ((*p) != 0) {
		//1 如果是数字 直接输出
		if (IsNumber(*p)) {
			printf("%c", *p);
		}
		//2 如果是左括号 进栈
		if (IsLeft(*p)) {
			Snode *data = (Snode*)malloc(sizeof(Snode));
			data->p = p;
			Push_LinkStack(stack, (LinkSNode*)data);
		}
		//3 如果是右括号 将栈中元素弹出并输出 直至遇到左括号
		if (IsRight(*p)) {

			while (Size_LinkStack(stack) > 0) {
				Snode *tmp = (Snode*)Top_LinkStack(stack);
				if (IsLeft(*(tmp->p))) {
					//如果是左括号 结束并弹出左括号
					Pop_LinkStack(stack);
					free(tmp);
					break;
				}
				else {
					printf("%c", *tmp->p);
				}
				Pop_LinkStack(stack);
				free(tmp);
			}

		}
		//4 如果是运算符
		//1)若一开始没有可比较直接进栈; 2)若栈顶元素优先级低,进栈; 3)若栈顶元素优先级高,将栈顶元素弹出并输出,直至低就进栈
		if (IsOperator(*p)) {

			//先取出栈顶元素
			Snode *tmp1 = (Snode*)Top_LinkStack(stack);

			//1)栈无
			if (tmp1 == NULL) {
				Snode *data = (Snode*)malloc(sizeof(Snode));
				data->p = p;
				Push_LinkStack(stack, (LinkSNode*)data);
				//插入后应进行下一个字符判断 否则因tmp1为空导致下面代码出错出错
				p++;
				continue;
			}
			//2)栈低
			if (GetPriority(*(tmp1->p)) < GetPriority(*p)) {
				Snode *data1 = (Snode*)malloc(sizeof(Snode));
				data1->p = p;
				Push_LinkStack(stack, (LinkSNode*)data1);
			}
			//栈高
			else {
				while (Size_LinkStack(stack) > 0) {
					//栈高输出并弹出
					tmp1 = (Snode*)Top_LinkStack(stack);
					if (GetPriority(*(tmp1->p)) > GetPriority(*p)) {
						printf("%c", *tmp1->p);
						Pop_LinkStack(stack);
						free(tmp1);
					}
					//栈低入栈
					else {
						Snode *data2 = (Snode*)malloc(sizeof(Snode));
						data2->p = p;
						Push_LinkStack(stack, (LinkSNode*)data2);
					}
				}
			}
		}

		p++;
	}

	//最后将栈中的元素遍历输出
	while (Size_LinkStack(stack) > 0) {
		Snode* tmp2 = (Snode*)Top_LinkStack(stack);
		printf("%c", *tmp2->p);
		Pop_LinkStack(stack);
		free(tmp2);
	}

	//销毁栈
	Destory_LinkStack(stack);

}

int main(void) {

	test01();

	return 0;
}

总结:总的来说,并不是很难,只要知道一开始说的四前提就可以照着写出。

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

09黑马笔记之栈的应用_中缀表达式转后缀表达式 的相关文章

随机推荐

  • wx.login wx.getUserProfile 获取登录凭证

    wx login 调用接口获取登录凭证 code 通过凭证进而换取用户登录态信息 包括用户在当前小程序的唯一标识 openid 微信开放平台帐号下的唯一标识 unionid 若当前小程序已绑定到微信开放平台帐号 及本次登录的会话密钥 ses
  • 通过hexo快速搭建个人博客

    个人博客预览点击这里 菜卷的博客 快速搭建一个博客 一 需要安装的工具 二 开始安装Hexo 三 安装完成后 初始化项目 四 在项目根目录下执行命令 五 启动项目 六 部署到github 七 配置文件 八 安装next主题 九 优化next
  • C语言程序实训--实验设备管理系统

    之前学校c语言程序实训课要求写的 如果程序有错误或可以改进的地方 希望各位指出 开发环境 IDE Visual Studio Code Dev C 处理器 AMD Ryzen 7 PRO 6850HS with Radeon Graphic
  • 73家!华为鸿蒙OS合作伙伴汇总

    6月2日 华为发布了最新版的鸿蒙操作系统 HarmonyOS 2 0 以及一系列搭载鸿蒙的硬件产品 比如手机 手表 平板 耳机 显示器等等 如今的智能终端越来越多 厂商不可能为每个设备单独准备一个系统 因为这不仅让开发者工作量倍增 消费者用
  • Flask网站中使用Keras时报错“Tensor Tensor(*) is not an element of this graph”

    HyperLPR车牌识别程序本地中能进行正常识别 但将其放到flask搭建的网站中进行识别 不能运行 并报错 Tensor Tensor is not an element of this graph HyperLPR中的识别模型采用的是K
  • Mask掩码

    Python中Mask的用法 引例 Numpy的MaskedArray模块 小于 或小于等于 给定数值 大于 或大于等于 给定数值 在给定范围内 超出给定范围 在算术运算期间忽略NaN和 或infinite值 All men are scu
  • Count Color

    http poj org problem id 2777 Description Chosen Problem Solving and Program design as an optional course you are require
  • 【QT】——布局

    目录 1 在UI窗口中布局 2 API设置布局 2 1 QLayout 2 2 QHBoxLayout 2 3 QVBoxLayout 2 4 QGirdLayout 注意 示例 Qt 窗口布局是指将多个子窗口按照某种排列方式将其全部展示到
  • Apifox—诠释国产接口管理工具新高度

    揭开Apifox的神秘面纱 曾经在对于接口管理和调试工作上 大量的开发者往往会选择使用Swagger做接口文档管理 用Postman做接口调试工具 然而这样使用的痛处其实也不言而喻 原本同一类型的工作却被放置在不同的软件工具上 并且对于接口
  • 图像二值化方法--OTSU(最大类间方差法)

    前面学习了直方图双峰法 图像二值化方法中的阈值法 最大类间方差法 OTSU 是找到自适应阈值的常用方法 原理参考了冈萨雷斯的 数字图像处理 以下是自己写的函数 获取灰度图in的OTSU阈值 int Segment otsuMat Mat i
  • [译] Scratch 平台的神经网络实现(R 语言)

    原文地址 Neural Networks from Scratch in R 原文作者 Ilia Karmanov 译文出自 掘金翻译计划 本文永久链接 github com xitu gold m 译者 CACppuccino 校对者 I
  • 【通信协议】笔记之Redis协议抓取分析

    RESP Redis序列化协议 概念 Redis底层使用的通信协议是RESP Redis Serialization Protocol的缩写 RESP协议可以序列化多种类型 比如Simple Strings 简单字符串 Errors 错误类
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • 数学建模第二天:数学建模工具课之MATLAB绘图操作

    目录 一 前言 二 二维绘图 1 曲线图 散点图plot 2 隐函数 显函数与参数方程的绘图 ezplot fplot 三 三维绘图 1 单曲线plot3 2 多曲线plot3 3 曲面 实曲面surf 网格曲面mesh 四 特殊的二维 三
  • 9.Linux虚拟机下Hive的安装配置

    hadoop 3 1 3 jdk 8u162 linux x64 apache hive 3 1 2 bin 本案例软件包 链接 https pan baidu com s 1ighxbTNAWqobGpsX0qkD8w 提取码 lkjh
  • 基于Python机器学习算法小分子药性预测(岭回归+随机森林回归+极端森林回归+加权平均融合模型)

    目录 前言 总体设计 系统整体结构图 系统流程图 运行环境 Python 环境 配置工具包 模块实现 1 数据预处理 2 创建模型并编译 3 模型训练 系统测试 工程源代码下载 其它资料下载 前言 麻省理工科技评论 于2020年发布了 十大
  • Kafka如何获取topic最近n条消息

    问题来源 项目运行中我们经常需要诊断个个环节是否正确 其中到kafka就需要查看最新的消息到达kafka没有 达到的内容是什么 这就需要查看kafka指定topic的最近的n条消息 将kakfa消息全部打印出来非常耗时而且不必要 当然我们可
  • mpvue vuex持久化缓存

    mpvue vuex持久化缓存 使用vuex persistedstate插件 npm install vuex persistedstate save 在store index js中添加plugins export default ne
  • 正则表达式/i,/g,/ig,/gi,/m

    正则表达式中 i g ig gi m的区别和含义 i 忽略大小写 g 全文查找出现的所有匹配字符 m 多行查找 gi 全文查找 忽略大小写 ig 全文查找 忽略大小写 这些是模式修正符 解说正则表达式模式中使用的修正符i 如果设定此修正符
  • 09黑马笔记之栈的应用_中缀表达式转后缀表达式

    09黑马笔记之栈的应用 中缀表达式转后缀表达式 1 前提 1 数字 直接输出 2 左括号 直接进栈 优先级默认最低 3 右括号 将栈顶符号输出 直到匹配到左括号 4 运算符 1 若一开始没有可比较直接进栈 2 若栈顶元素优先级低 进栈 3