西北工业大学NOJ数据结构—008逆波兰式

本文介绍了一种使用栈将中缀表达式转换为逆波兰式的算法实现过程,包括算法思路解析、优先级设定及具体代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题为将一个中缀表达式转化为逆波兰式,同样为栈的应用,以下为原题(づ ̄3 ̄)づ╭❤~


有必要解释以下逆波兰式,其实就是后缀表达式,也就是计算机计算时识别的语言,比如上方的ab+c*,那么计算机就依次读取,a、b然后+,之后就可以计算a+b,然后c、*,也就是把a+b的和与c相乘,稍微详细一点的逆波兰式推荐知乎搜索:逆波兰式到底是什么鬼(虽然提问者有点睿智,但是几个回答者都是dalao得意),那么下面为题目分析

为了解决这个问题我创建了三个栈S1,S2,S3,其实从中缀到后缀的转化只需要一个栈(而从中缀到前缀则需要两栈),因为只需要将运算符放到栈S1中来回倒就ok(滑稽),额外创建的两个栈.......没什么用,储存表达式罢了,完全可以直接用字符串解决.......睿智了我......

思路分析,依次读取字符串的字符,先将一个“#”压进S1,作为一个比较的基础(\(^o^)/)

1.如果是字符,则直接压倒栈S2中,(知道为啥有S3了吗,因为压到S2中后输出是反的!反的!迫不得已最后再倒进S3在输出,哭唧唧)

2.如果是运算符,则就需要比较这个运算符和栈顶元素的优先级别了,假设之前栈顶的运算符为c1,后来读取的运算符为c2。

则有:如果c2优先级高于c1,那么c2压进S1栈储存

          如果c2优先级低于c1,那么S1将c1弹出并压进S2,然后比较新的S1的栈顶元素和c2,如果还是c2优先级别低,那就再弹一个c1,最后直到c1的优先级别低于c2,此时将c2压进栈S1。(大概就这样....其实意思就是要是c2想进栈,栈顶元素的优先级必须比他小,别忘了最下边还压着一个“#”,这玩意优先级别最低)

     那么他们的优先级顺序如下图所示,(很重要!!但是不需要背啊啥的,看看就懂了,乘除优先于加减,括号优先,就酱=_=)

        需要特别注意为‘(’,因为左括号的优先级其实是有改变的,如果c2是左括号,则优先级别最高,如果c1是左括号,则优先级别最低,稍微理解一下,因为如果下一个来的是左括号的话,那么你必须先运算括号里边的,所以优先级别超级高,但是如果左括号已经压进栈内了,那么你必须等到有一个右括号来跟他(交配),才能完成括号内的计算。

好了思路就这样,上代码

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

typedef struct Node{//定义带有节点的链表
	char info;
	struct Node *next;
}Node;

typedef struct linkstack{//定义栈的栈顶指针
	struct Node *top;
}stack;

stack *creat(void)
{
	stack *plstack;//创建一个空栈并返回指针
	plstack=(struct linkstack*)malloc(sizeof(struct linkstack));
	if(plstack!=NULL)
		plstack->top=NULL;
	else
		printf("out!\n");
	return plstack;
}

int is_empty(stack *plstack)//检查栈是否为空
{
	return(plstack->top==NULL);
}

void push(stack *plstack,char x)//动态申请并将一元素入栈
{
	struct Node *p;
	p=(struct Node*)malloc(sizeof(struct Node));
	if(p==NULL)
		printf("out!\n");
	else
	{
		p->info=x;
		p->next=plstack->top;
		plstack->top=p;
	}
}

char pop(stack *plstack)
{//如果栈不为空则将栈顶元素出栈并返回该元素
	struct Node *p;
	char elem;
	if(is_empty(plstack))
		printf("out!5");
	else
	{
		p=plstack->top;
		elem=p->info;
		plstack->top=plstack->top->next;
		free(p);
	}
	return elem;
}

char toplink(stack *plstack)//如果栈非空则返回栈顶元素
{
	if(is_empty(plstack))
		printf("out!7");
	return plstack->top->info;
}

stack *nibolan(char *e)
{
	stack *s1,*s2,*s3;
	s1=creat();
	s2=creat();
	s3=creat();//创建三个栈
	push(s1,'#');//在一个中压进#
	char *p=e,ch,cp;
	int length=0;
	for(;*p!='\0';p++)
	{
		switch(*p)
		{
			case'(':{
				push(s1,*p);
				break;   //左括号直接入栈
			}
			case')':{    //如果是右括号则将左括号之前的全部出栈并依此压进2栈
				while(toplink(s1)!='(')
				{
					ch=pop(s1);
					push(s2,ch);
				}
				cp=pop(s1);    //将左括号出栈,不要了,因为后缀表达式不需要括号
				break;
			}
			case'+':
			case'-':{
				for(ch=toplink(s1);ch!='#';ch=toplink(s1))//一出现加减号那么可以说一下就可以运算之前所有的
				{             //如果是加号减号则检查栈顶元素
					if(ch=='(')
					{
						break;  //如果是左括号那显然直接压进去就ok
					}
					else{      //但是如果是加减乘除号,就要考虑往外弹了,以为之前压进去的加减号的优先级也是大于后来的加减号
						ch=pop(s1);     //优先级低依此出栈并压进2栈
						push(s2,ch);
					}
				}
				push(s1,*p);           //到最后再吧这个加减号压进S1
				length++;
				break;
			}
			case'*':
			case'/':{
				for(ch=toplink(s1);ch!='#'&&ch!='+'&&ch!='-';ch=toplink(s1))
				{           //如果是乘号和除号则判定是否优先  比他低的优先级就是加减号
					if(ch=='(')
					{
						break;
					}
					else{//同样 之前的若是乘除号,也是先进的优先级高于后来的
						ch=pop(s1);
						push(s2,ch);
					}
				}
				push(s1,*p);     //直到碰到优先级高直接压进
				length++;
				break;
			}
			default:
			push(s2,*p);       //其他数字直接压进2栈
			length++;
		}
	}
	while(!is_empty(s1)&&toplink(s1)!='#')
	{          //结束后1栈不空则依此从出栈并压进2栈
		ch=pop(s1);
		push(s2,ch);
	}
	while(!is_empty(s2))
	{       //依此将2栈出栈压进三战逆置
		ch=pop(s2);
		push(s3,ch);
	}
	return (s3);
}

void show(stack *p)
{          //从栈顶元素开始出栈,并输出出栈元素
	stack *a=p;
	while(!is_empty(a))
	{
		printf("%c",a->top->info);
		pop(a);
	}
}

int main()
{
	char a[100],*e;
	stack *c;
	e=&a[0];
	scanf("%s",a);
	c=nibolan(e); //调用逆波兰函数得到栈3
	show(c);   //输出逆波兰式
	return 0;
}



西北工业大学NOJC程序设计习题答案(非本人制作,侵删) 1.“1“的传奇 2.A+B 3.A+BⅡ 4.AB 5.ACKERMAN 6.Arithmetic Progressions 7.Bee 8.Checksum algorithm 9.Coin Test 10.Dexter need help 11.Double 12.Easy problem 13.Favorite number 14.Graveyard 15.Hailstone 16.Hanoi Ⅱ 17.Houseboat 18.Music Composer 19.Redistribute wealth 20.Road trip 21.Scoring 22.Specialized Numbers 23.Sticks 24.Sum of Consecutive 25.Symmetric Sort 26.The Clock 27.The Ratio of gainers to losers 28.VOL大学乒乓球比赛 29.毕业设计论文打印 30.边沿与内芯的差 31.不会吧,又是A+B 32.不屈的小蜗 33.操场训练 34.插入链表节点 35.插入排序 36.插入字符 37.成绩表计算 38.成绩转换 39.出租车费 40.除法 41.创建与遍历职工链表 42.大数乘法 43.大数除法 44.大数加法 45.单词频次 46.迭代求根 47.多项式的猜想 48.二分查找 49.二分求根 50.发工资的日子 51.方差 52.分离单词 53.分数拆分 54.分数化小数 55.分数加减法 56.复数 57.高低交换 58.公园喷水器 59.韩信点兵 60.行程编码压缩算法 61.合并字符串 62.猴子分桃 63.火车站 64.获取指定二进制位 65.积分计算 66.级数和 67.计算A+B 68.计算PI 69.计算π 70.计算成绩 71.计算完全数 72.检测位图长宽 73.检查图像文件格式 74.奖金发放 75.阶乘合计 76.解不等式 77.精确幂乘 78.恐怖水母 79.快速排序 80.粒子裂变 81.链表动态增长或缩短 82.链表节点删除 83.两个整数之间所有的素数 84.路痴 85.冒泡排序 86.你会存钱吗 87.逆序整数 88.排列 89.排列分析 90.平均值函数 91.奇特的分数数列 92.求建筑高度 93.区间内素数 94.三点顺序 95.山迪的麻烦 96.删除字符 97.是该年的第几天 98.是该年的第几天? 99.数据加密 100.搜索字符 101.所有素数 102.探索合数世纪 103.特殊要求的字符串 104.特殊整数 105.完全数 106.王的对抗 107.危险的组合 108.文件比较 109.文章统计 110.五猴分桃 111.小型数据库 112.幸运儿 113.幸运数字”7“ 114.选择排序 115.寻找规律 116.循环移位 117.延伸的卡片 118.羊羊聚会 119.一维数组”赋值“ 120.一维数组”加法“ 121.勇闯天涯 122.右上角 123.右下角 124.圆及圆球等的相关计算 125.圆及圆球等相关计算 126.程序员添加行号 127.找出数字 128.找幸运数 129.找最大数 130.整数位数 131.重组字符串 132.子序列的和 133.子字符串替换 134.自然数立方的乐趣 135.字符串比较 136.字符串复制 137.字符串加密编码 138.字符串逆序 139.字符串排序 140.字符串替换 141.字符串左中右 142.组合数 143.最次方数 144.最大乘积 145.最大整数 146.最小整数 147.最长回文子串 148.左上角 149.左下角
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值