3.3利用栈解决多项式的运算

作者:胡敬灏

#include <stdio.h>
#include <ctype.h>   // 用于字符判断
#include <stdlib.h>  // 用于exit函数

#define MAX_SIZE 100 // 栈的最大容量

/* 操作数栈结构(存储计算过程中的数值) */
typedef struct {
    double data[MAX_SIZE]; // 存储数值的数组
    int top;               // 栈顶指针(-1表示空栈)
} OperandStack;

/* 运算符栈结构(存储运算符和括号) */
typedef struct {
    char data[MAX_SIZE];  // 存储运算符的数组
    int top;              // 栈顶指针
} OperatorStack;

// 函数原型声明
void initOperandStack(OperandStack *s);
void pushOperand(OperandStack *s, double val);
double popOperand(OperandStack *s);
char peekOperator(OperatorStack *s);
int getPriority(char op);
double calculate(double a, double b, char op);
double evaluateExpression(const char *expr);

int main() {
    const char *expr = "(3+5)*2-6/3"; // 测试表达式
    double result = evaluateExpression(expr);
    printf("表达式 %s 的结果是: %.2f\n", expr, result);
    return 0;
}

/* 初始化操作数栈 */
void initOperandStack(OperandStack *s) {
    s->top = -1; // 栈顶指针初始化为-1表示空栈
}

/* 操作数入栈 */
void pushOperand(OperandStack *s, double val) {
    if (s->top >= MAX_SIZE - 1) {
        printf("操作数栈溢出!");
        exit(1);
    }
    s->data[++s->top] = val; // 栈顶指针先加1再存入数据
}

/* 操作数出栈 */
double popOperand(OperandStack *s) {
    if (s->top < 0) {
        printf("操作数栈为空!");
        exit(1);
    }
    return s->data[s->top--]; // 返回栈顶数据后指针减1
}

/* 查看运算符栈顶元素 */
char peekOperator(OperatorStack *s) {
    return s->data[s->top];
}

/* 获取运算符优先级 */
int getPriority(char op) {
    switch(op) {
        case '+': case '-': return 1;   // 加减法优先级
        case '*': case '/': return 2;   // 乘除法优先级
        case '(':           return 0;   // 括号特殊处理
        default: 
            printf("非法运算符:%c", op);
            exit(1);
    }
}

/* 执行实际计算 */
double calculate(double a, double b, char op) {
    switch(op) {
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': 
            if (b == 0) {
                printf("除数不能为零!");
                exit(1);
            }
            return a / b;
        default: 
            printf("非法运算符:%c", op);
            exit(1);
    }
}

/* 核心表达式求值函数 */
double evaluateExpression(const char *expr) {
    OperandStack numStack;   // 操作数栈
    OperatorStack opStack;    // 运算符栈
    initOperandStack(&numStack);
    opStack.top = -1;         // 初始化运算符栈

    int i = 0;
    while (expr[i] != '\0') {
        // 情况1:处理数字(包括多位数)
        if (isdigit(expr[i])) {
            double num = 0;
            while (isdigit(expr[i])) {
                num = num * 10 + (expr[i] - '0'); // 数字位拼接
                i++;
            }
            pushOperand(&numStack, num);
        }
        // 情况2:处理左括号
        else if (expr[i] == '(') {
            opStack.data[++opStack.top] = expr[i];
            i++;
        }
        // 情况3:处理右括号
        else if (expr[i] == ')') {
            while (opStack.data[opStack.top] != '(') {
                // 弹出括号内的运算符进行计算
                char op = opStack.data[opStack.top--];
                double b = popOperand(&numStack);
                double a = popOperand(&numStack);
                pushOperand(&numStack, calculate(a, b, op));
            }
            opStack.top--; // 弹出左括号
            i++;
        }
        // 情况4:处理运算符
        else if (expr[i] == '+' || expr[i] == '-' || 
                 expr[i] == '*' || expr[i] == '/') {
            // 比较运算符优先级,执行栈内运算
            while (opStack.top != -1 && 
                   getPriority(expr[i]) <= getPriority(opStack.data[opStack.top])) {
                char op = opStack.data[opStack.top--];
                double b = popOperand(&numStack);
                double a = popOperand(&numStack);
                pushOperand(&numStack, calculate(a, b, op));
            }
            opStack.data[++opStack.top] = expr[i]; // 当前运算符入栈
            i++;
        }
        // 跳过空格等其他字符
        else {
            i++;
        }
    }

    // 处理剩余运算符
    while (opStack.top != -1) {
        char op = opStack.data[opStack.top--];
        double b = popOperand(&numStack);
        double a = popOperand(&numStack);
        pushOperand(&numStack, calculate(a, b, op));
    }

    return popOperand(&numStack);
}

心得:1.对两个栈的熟练使用,一个数字栈,一个字符栈

2.对字符的比较,利用Switch case 分类讨论 用数字123比较 并且可以在放入运算前有比较 是一个很好的思路

3.遇到一个新的字符时,先比较后,先进行运算再放入

4.这是一个对栈很综合的应用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值