基于栈的后缀表达式求值

题目:基于栈的后缀表达式求值

实验目的:
1. 掌握中缀表达式转换为后缀表达式的算法。
2. 掌握后缀表达式求值的算法。
实验内容:
问题描述
输入一个中缀算术表达式,将其转换为后缀表达式,然后对后缀表达式进行求值。运算符包括: + 、 -、 * / = ( ) ,参与运算的为小于 10 的自然数 ( 只考虑二元运算即可 )
输入要求
多组数据,每组数据一行,对应一个算术表达式,每个表达式均以 “=” 结尾。当表达式只有一个 “=”
时,输入结束。
输出要求
对于每组数据输出 2 行,第 1 行为中缀表达式对应的后缀式,第 2 行为后缀式求值的结果。
输入 样例
9+(3-1)*3+1/2=
1+2=
=
输出样例
931-3*+12/+
15
12+
3

代码

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>//字符分类
#include <string.h>
#define MAX_EXPR_LENGTH 50 // 假设每个表达式的最大长度为50
// 定义栈结构
typedef struct {
    int top;//栈顶元素的位置	
    int* array;//指向整型数组的指针,用于储存栈中元素的数组
} Stack;

// 初始化栈
Stack* createStack(int n) {
    Stack* stack = (Stack*)malloc(sizeof(Stack));//动态分配一个存储一个Stack结构体的内存空间,即得到一个指向新分配的栈结构体的指针
    stack->top = -1;//初始化栈为空
    stack->array = (int*)malloc(n * sizeof(int));//为栈的array成员变量分配足够的内存空间来存储n个整数,即得到一个存储栈中元素的数组
    return stack;
}

// 判断栈是否为空
int isEmpty(Stack* stack) {//检测Stack*指针所指向的栈是否为空
    return stack->top == -1;//1栈为空, 0栈非空
}

// 获取栈顶元素
int GetTop(Stack* stack) {//获取Stack*指针所指向栈的栈顶元素
    return stack->array[stack->top];//tack->array: 这是一个指向整数数组的指针,它存储了栈中的元素。stack->top栈顶元素的位置
}

// 元素入栈
void push(Stack* stack, int item) {
    stack->array[++stack->top] = item;//++stack->top使新的值对应栈顶元素的位置,将item放在新的栈顶位置
}

// 元素出栈
int pop(Stack* stack) {
    if (!isEmpty(stack)) {//栈不为空
        return stack->array[stack->top--];//先返回栈顶元素的值,再使新的stack-top值对应着新的栈顶元素
    }
    return -1; // 栈为空
}

// 判断字符是否为运算符
int isOperator(char ch) {
    return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}

// 获取运算符优先级
int getPriority(char ch) {
    switch (ch) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return 0; 
    }
}

//中缀表达式转后缀表达式
void infixToPostfix(char* infix, char* postfix) {
    Stack* stack = createStack(strlen(infix));//创建一个用于存储运算符和括号的栈,并初始化大小为中缀表达式的长度
   
	// i中缀表达式的字符索引,j后缀表达式的字符索引
	for (int i = 0, int j = 0; infix[i]; ++i) {
        if (isdigit(infix[i])) {//当前字符是否为数字
            postfix[j++] = infix[i];
        } else if (infix[i] == '(') {
            push(stack, infix[i]);//‘(’ 压入栈中
        } else if (infix[i] == ')') {
            while (!isEmpty(stack) && GetTop(stack) != '(') {
                postfix[j++] = pop(stack);//从stack中弹出元素并添加到后缀表达式字符数组postfix中,直到遇到‘(’,将‘(’弹出,但是并不添加到后缀表达式中
            }
           pop(stack); 
        } else if (isOperator(infix[i])) {
			//如果栈顶运算符优先级大于等于当前运算符优先级,则从栈stack中弹出元素并添加到后缀表达式字符数组postfix中,直到栈顶运算符优先级小于当前运算符优先级或栈为空。然后将当前运算符压入栈 stack
            while (!isEmpty(stack) && getPriority(GetTop(stack)) >= getPriority(infix[i])) {
                postfix[j++] = pop(stack);
            }
            push(stack, infix[i]);
        }
    }
	//在中缀表达式处理完毕后,将栈stack中剩余的所有运算符依次弹出并添加到后缀表达式字符数组postfix中
    while (!isEmpty(stack)) {
        postfix[j++] = pop(stack);
    }
	 postfix[j] = '\0'; //字符串的结束
	free(stack);//释放为stack分配的内存空间
}

// 使用后缀表达式求值
int evaluatePostfix(char* postfix) {
    Stack* stack = createStack(strlen(postfix));//创建一个存储数值的栈,初始化大小为后缀表达式的长度
	//postfix[i]为NULL时,循环结束
    for (int i = 0; postfix[i]; ++i) {
        if (isdigit(postfix[i])) {
            push(stack, postfix[i] - '0');//把postfix中char转为int存入stack栈中
			//对于ASCII编码系统,十进制数字字符(例如 '0'、'1'、'2' 等)的编码值是连续的,它们与对应的整数值相差一个固定的偏移量,即字符 '0' 的ASCII码值。
        } else if (isOperator(postfix[i])) {//postfix[i] 是否为运算符。如果是,则从栈 stack 中弹出两个元素作为操作数
            int y = pop(stack);//弹出栈顶元素作为第二个操作数
            int x = pop(stack);//再弹出栈顶元素作为第一个操作数
            switch (postfix[i]) {
                case '+':
                    push(stack, x + y);
                    break;
                case '-':
                    push(stack, x - y);
                    break;
                case '*':
                    push(stack, x * y);
                    break;
                case '/':
                    push(stack, x / y);
                    break;
            }
        }
    }
    return pop(stack);//从栈 stack 中弹出最后一个元素,该元素即为后缀表达式的计算结果。
	free(stack);
}

int main() {
	int n = 0;
    char (*infix)[MAX_EXPR_LENGTH] = NULL;
    char (*postfix)[MAX_EXPR_LENGTH] = NULL;

    // 动态分配数组空间,初始大小为10
    infix = (char(*)[MAX_EXPR_LENGTH])malloc(10 * sizeof(char[MAX_EXPR_LENGTH]));
    postfix = (char(*)[MAX_EXPR_LENGTH])malloc(10 * sizeof(char[MAX_EXPR_LENGTH]));

    printf("请输入多个中缀表达式(每行一个算术表达式),以单个等号(=)结束输入:\n");

    while (1) {
        scanf("%s", infix[n]); // 使用scanf函数输入一行字符

        if (strlen(infix[n]) == 1 && infix[n][0] == '=') { // 检查字符串长度是否为1且第一个字符是否为等号
            break;
        }

        n++;
    }

    for (int i = 0; i < n ; i++) {
        infixToPostfix(infix[i], postfix[i]);
        int result = evaluatePostfix(postfix[i]);
        printf("转换成后缀表达式是:%s\t后缀表达式的结果为: %d\n", postfix[i], result);
    }

    free(infix);
    free(postfix);
    return 0;
}

运行结果 

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一吨土豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值