相关数据结构:栈
一、实验内容
后缀表达式求值
二、问题描述
输入一个中缀算术表达式,将其转换为后缀表达式,然后对后缀表达式进行求值。运算符包括+ - * /
,参与运算的为小于10的自然数。
三、输入与输出
输入要求
一组数据,每组数据一行,对应一个算术表达式
输出要求
对每组数据输出2行,第1行为中缀表达式对应的后缀式,第2行为后缀式求值的结果。
输入样例
9+(3-1)*3+1+2
输出样例
931-3*+1+2+
18
三、代码实现
#include<stdio.h>
#include<stdlib.h>
#include <stdbool.h>
#define MaxSize 20
//定义操作数栈
typedef struct {
int data[MaxSize];
int top;
}opnd;
//定义运算符栈
typedef struct {
char data[MaxSize];
int top;
}oprt;
//函数声明
void Init_opnd(opnd* o); //操作数栈初始化
void Init_oprt(oprt* o); //运算符栈初始化
void Push_opnd(opnd* o, int e); //操作数入栈
int Pop_opnd(opnd* o); //操作数出栈
int get_opnd(opnd* o); //取操作数栈顶元素
void Push_oprt(oprt* o, char ch); //运算符入栈
char Pop_oprt(oprt* o); //运算符出栈
char get_oprt(oprt* o); //取操作符栈顶元素
bool biJiao(char ch1, char ch2); //比较运算符与栈顶元素优先级
int compute(int a, char total, int b); //运算部分
void function(opnd* o1, oprt* o2, char str1[]); //中缀转后缀再计算
int main(void) {
opnd* o1 = (opnd*)malloc(sizeof(opnd));
Init_opnd(o1);
oprt* o2 = (oprt*)malloc(sizeof(oprt));
Init_oprt(o2);
char str1[MaxSize];
scanf("%s", str1); //输入中缀表达式
function(o1, o2, str1);
return 0;
}
//操作数栈初始化
void Init_opnd(opnd* o) {
o->top = -1;
}
//操作数入栈
void Push_opnd(opnd* o, int e) {
if (o->top == MaxSize - 1) {
printf("栈满!\n");
}else {
o->top++;
o->data[o->top] = e;
}
}
//操作数出栈
int Pop_opnd(opnd* o) {
if (o->top == -1) {
printf("栈空!\n");
} else {
return o->data[o->top--];
}
}
//取操作数栈顶元素
int get_opnd(opnd* o) {
if (o->top == -1) {
printf("栈空!\n");
} else {
return o->data[o->top];
}
}
//运算符栈初始化
void Init_oprt(oprt* o)
{
o->top = -1;
}
//运算符入栈
void Push_oprt(oprt* o, char ch) {
if (o->top == MaxSize - 1) {
printf("栈满!\n");
} else {
o->top++;
o->data[o->top] = ch;
}
}
//运算符出栈
char Pop_oprt(oprt* o) {
if (o->top == -1) {
printf("栈空!\n");
} else {
return o->data[o->top--];
}
}
//取操作符栈顶元素
char get_oprt(oprt* o) {
if (o->top == -1) {
printf("栈空!\n");
} else {
return o->data[o->top];
}
}
//比较运算符与栈顶元素优先级
bool biJiao(char a, char b) {
if ((a == '+' || a == '-') && (b == '+' || b == '-')) {
return true; //同级
}
if ((a == '+' || a == '-') && (b == '*' || b == '/')) {
return true; //低一级
}
if ((a == '*' || a == '/') && (b == '*' || b == '/')) {
return true; //同级
}
if ((a == '*' || a == '/') && (b == '+' || b == '-')) {
return false; //高一级
}
}
//运算部分
int compute(int a, char total, int b) {
switch (total) {
case '+':
return b + a;
case '-':
return b - a;
case '*':
return b * a;
case '/':
return b / a;
}
}
//中缀转后缀再计算
void function(opnd* o1, oprt* o2, char str1[]) { //o1为操作数栈,o2为运算符栈,str[]为输入的中缀表达式
int i, j, a, b;
char str2[MaxSize];
char* p, * q, total;
p = str1; //赋值输入的中缀表达式
q = str2; //用来存放转换之后的后缀表达式
while(*p!='\0') {
if (*p >= '0' && *p <= '9') { //为0~9的数字时
*q++ = *p;
Push_opnd(o1, *p++ - '0'); //压入操作数栈内,并将要读取的位置往后移一位
} else { //非数字时
if (o2->top == -1 || *p == '(') { //当运算符栈为空or中缀表达式中读取为左括号
Push_oprt(o2, *p++); //直接压入运算符栈
} else {
if (get_oprt(o2) == '(') { //当运算符栈栈顶元素为左括号时
Push_oprt(o2, *p++); //直接压入运算符栈
} else {
if (*p == ')') { //当读取到中缀表达式中的右括号时
total = get_oprt(o2); //取得栈顶元素
while (total != '(') { //在没将运算符栈的左括号取出来时,会将左括号前面的符号出栈,直到遇到左括号为止
total = Pop_oprt(o2); //运算符栈出栈
*q++ = total; //将出栈元素赋值给用来存放后缀表达式的字符数组,赋值之后,q所指向str2[]的位置向后移动一位,方便存储下一个字符
a = Pop_opnd(o1); //操作数栈出栈两个元素
b = Pop_opnd(o1);
Push_opnd(o1, compute(a, total, b)); //将连续出栈的a,b进行运算后的值再压入操作数栈中
total = get_oprt(o2); //之前的运算符已经使用,需要重新赋值新的运算符
}
total = Pop_oprt(o2); //当上面的循环结束,total中存放的为:)
p++; //接着读取中缀表达式中的下一位
} else { //没有遇到中缀表达式中的右括号时
if (!biJiao(*p, get_oprt(o2))) { //当两优先级为false时,即:中缀表达式中读取到的运算符比运算符栈的栈顶元素的优先级要高时
Push_oprt(o2, *p++); //压入运算符栈中
} else {
total = Pop_oprt(o2); //出栈
*q++ = total; //将出栈的运算符存入后缀表达式的字符数组中
Push_opnd(o1, compute(Pop_opnd(o1), total, Pop_opnd(o1)));
}
}
}
}
}
}
while (o2->top != -1) { //当运算符栈中仍有元素时
total = Pop_oprt(o2);
*q++ = total;
Push_opnd(o1, compute(Pop_opnd(o1), total, Pop_opnd(o1)));
}
printf("%s",str2); //输出由中缀表达式转换的后缀表达式
printf("\n%d", Pop_opnd(o1)); //此时操作数栈中的最后一个值便是整个式子计算的结果
}