中缀表达式求值

根据输入的中缀表达式构造一棵等价的中缀表达式树,并通过此树计算中缀表达式的值。


通过中缀表达式树计算中缀表达式

一、构造中缀表达式树:

①初始化操作数栈运算符栈

②扫描中缀表达式:

  • 若扫描到操作数,压入操作数栈;
  • 若扫描到界限符,遇到(直接压入运算符栈,遇到)依次弹出运算符栈内运算符,直到弹出(
  • 若扫描到运算符,依次弹出运算符栈中优先级高于或等于当前运算符的所有运算符,直到遇到(或运算符栈空,之后再将当前运算符压入运算符栈;
  • 若扫描到等于号,依次弹出运算符栈中的所有运算符。
  • 同时:a.每次压栈时,将操作数或运算符转化为二叉树结点形式再压栈。b.每当运算符栈中弹出运算符时,依次弹出操作数栈中的两个元素作为右操作数左操作数,分别挂在当前运算符结点的左右孩子处,之后将当前子树作为一个操作数压入操作数栈

二、通过后序遍历递归计算中缀表达式树。


输入样例:
1+2+3*(4+5)=
1+(2+4*4/2)-1=
((9/(5-(1+1)))*3)-(2+(1+1))=
=

输出样例:
30
10
5


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


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

#define MaxSize 10
#define ElemType BiTree

typedef struct BiTNode {
    char data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

typedef struct SqStack {
    ElemType data[MaxSize];
    int top;
} SqStack;

BiTree BiTreeCreate(char *nodeData);
void BiTreeDestroy(BiTree *root);
BiTNode *nodeCreate(char c);

int calculate(BiTree root);
bool isLessOrEqual(char c1, char c2);

/*为简化代码,所有的栈操作都不作出错检查*/
void StackInit(SqStack *stack);
bool StackEmpty(SqStack stack);
void StackPush(SqStack *stack, ElemType e);
ElemType StackPop(SqStack *stack);
ElemType StackGetTop(SqStack stack);

int main() {
    char str[MaxSize] = "";

    while (scanf("%[^\n]%*c", str) && str[0] != '=') {
        BiTree T = NULL;

        T = BiTreeCreate(str);
        printf("%d\n", calculate(T));

        BiTreeDestroy(&T);
    }
    return 0;
}

/**
 * 根据中序表达式构造二叉表达式树
 */
BiTree BiTreeCreate(char *nodeData) {
    SqStack numStack;//操作数栈
    SqStack opStack;//运算符栈
    BiTNode *op;//用于暂存出栈的运算符

    StackInit(&numStack);
    StackInit(&opStack);

    for (int i = 0; nodeData[i] != 0; i++) {
        if (nodeData[i] >= 48 && nodeData[i] <= 57) {
            /*当前结点是操作数,直接压操作数栈*/
            StackPush(&numStack, nodeCreate(nodeData[i]));
        } else if (nodeData[i] == '+' || nodeData[i] == '-' || nodeData[i] == '*' || nodeData[i] == '/') {
            if (!StackEmpty(opStack)) {
                op = StackGetTop(opStack);
                if (isLessOrEqual(nodeData[i], op->data)) {
                    /*当前运算符优先级低于或等于栈顶运算符,将栈顶运算符出栈并运算*/
                    op = StackPop(&opStack);
                    /*将左、右操作数挂在左、右孩子位置上的过程就相当于运算*/
                    op->rchild = StackPop(&numStack);
                    op->lchild = StackPop(&numStack);
                    /*运算结果相当于一个操作数*/
                    StackPush(&numStack, op);
                }
            }
            StackPush(&opStack, nodeCreate(nodeData[i]));
        } else if (nodeData[i] == '(') {
            /*左括号直接压栈*/
            StackPush(&opStack, nodeCreate(nodeData[i]));
        } else if (nodeData[i] == ')') {
            /*如果遇到右括号,运算符栈一直出栈并运算,直到左括号出栈*/
            while (1) {
                op = StackPop(&opStack);
                if (op->data != '(') {
                    op->rchild = StackPop(&numStack);
                    op->lchild = StackPop(&numStack);
                    StackPush(&numStack, op);
                } else {
                    break;
                }
            }
        } else {
            /*遇到等号将栈中剩余运算符出栈运算,并将结果返回*/
            while (!StackEmpty(opStack)) {
                op = StackPop(&opStack);
                op->rchild = StackPop(&numStack);
                op->lchild = StackPop(&numStack);
                StackPush(&numStack, op);
            }
            return op;
        }
    }
}

/**
 * 释放二叉树内存空间
 */
void BiTreeDestroy(BiTree *root) {
    if (*root) {
        BiTreeDestroy(&(*root)->lchild);
        BiTreeDestroy(&(*root)->rchild);
        free(*root);
        *root = NULL;
    }
}

/**
 * 将输入数据转化为二叉树结点
 */
BiTNode *nodeCreate(char c) {
    BiTNode *newNode = (BiTNode *) malloc(sizeof(BiTNode));

    newNode->data = c;
    newNode->lchild = newNode->rchild = NULL;
    return newNode;
}

/**
 * 通过表达式树进行计算
 */
int calculate(BiTree root) {
    if (root) {
        switch (root->data) {
            case '+':
                return calculate(root->lchild) + calculate(root->rchild);
            case '-':
                return calculate(root->lchild) - calculate(root->rchild);
            case '*':
                return calculate(root->lchild) * calculate(root->rchild);
            case '/':
                return calculate(root->lchild) / calculate(root->rchild);
            default:
                return root->data - 48;
        }
    }
}

/**
 * 判断c1的优先级是否小于c2
 */
bool isLessOrEqual(char c1, char c2) {
    int priority1 = 1, priority2 = 1;

    if (c1 == '(') {
        priority1 = 0;
    } else if (c1 == '*' || c1 == '/') {
        priority1 = 2;
    }

    if (c2 == '(') {
        priority2 = 0;
    } else if (c2 == '*' || c2 == '/') {
        priority2 = 2;
    }

    return priority1 <= priority2;
}

/**
 * 初始化栈
 */
void StackInit(SqStack *stack) {
    stack->top = -1;
}

/**
 * 判栈空
 */
bool StackEmpty(SqStack stack) {
    return (stack.top == -1) ? true : false;
}

/**
 * 入栈
 */
void StackPush(SqStack *stack, ElemType e) {
    stack->data[++stack->top] = e;
}

/**
 * 出栈
 */
ElemType StackPop(SqStack *stack) {
    return stack->data[stack->top--];
}

/**
 * 取栈顶元素但不出栈
 */
ElemType StackGetTop(SqStack stack) {
    return stack.data[stack.top];
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值