【数据结构--栈的应用--计算多项式】

表达式求值

总体思路

自左至右扫描表达式,若遇到操作数则压入操作数栈;遇到运算符,则需要比较其与运算符栈栈顶元素的优先级,若其优先级高于栈顶元素优先级则进栈,反之则取出栈顶运算符和操作数栈栈顶的连续两个操作数进行运算,并将结果存入操作数栈,然后继续比较该运算符与栈顶运算符的优先级。左括号压入运算符栈,右括号不压入运算符栈,取出运算符栈栈顶运算符和操作数栈栈顶的两个操作数进行运算,并将结果压入操作数栈,直到弹出左括号为止。

代码实现

初始化

此处需创建两个栈,一个栈用于存放操作数,另一个用于存放运算符,代码实现如下:

typedef struct numStack
{
    int numTop;
    int numData[MAXSIZE];
} numStack, *numStackPtr;

typedef struct charStack
{
    int charTop;
    char charData[MAXSIZE];
} charStack, *charStackPtr;

/* 数字栈初始化 */
numStackPtr initNumStack()
{
    numStackPtr numHeader = (numStackPtr)malloc(sizeof(numStack));
    numHeader->numTop = -1;
    return numHeader;
}

/* 操作符栈初始化 */
charStackPtr initCharStack()
{
    charStackPtr charHeader = (charStackPtr)malloc(sizeof(charStack));
    charHeader->charTop = -1;
    return charHeader;
}

操作数压栈及运算符压栈

  • 自左至右扫描表达式,当遇到操作数时将其压入操作数栈

  • 当遇到运算符时,若其优先级高于栈顶元素优先级则进栈

  • 反之取出栈顶运算符和操作数栈栈顶的连续两个操作数进行运算,并将结果存入操作数栈,然后继续比较该运算符与栈顶运算符的优先级。

/* 数字压栈 */
void numPush(numStackPtr tempNumStack, int tempNum)
{
    if(tempNumStack->numTop >= MAXSIZE - 1)
    {
        printf("无法压入元素%d:栈已满!\n",tempNum);
        return;
    }
    tempNumStack->numTop++;
    tempNumStack->numData[tempNumStack->numTop] = tempNum;
}

/* 操作符压栈 */
void charPush(charStackPtr tempCharStack, char tempChar)
{
    if(tempCharStack->charTop >= MAXSIZE - 1)
    {
        printf("无法压入元素%c:栈已满!\n",tempChar);
        return;
    }
    tempCharStack->charTop++;
    tempCharStack->charData[tempCharStack->charTop] = tempChar;
}

操作数及运算符弹栈

此处较为简单,就不再赘述了

/* 数字弹栈 */
int numPop(numStackPtr tempNumStack)
{
    if(tempNumStack->numTop == -1)
    {
        printf("无法弹出元素:栈为空!\n");
        return NULL;
    }
    tempNumStack->numTop--;
    return tempNumStack->numData[tempNumStack->numTop+1];
}

/* 操作符弹栈 */
char charPop(charStackPtr tempCharStack)
{
    if(tempCharStack->charTop == -1)
    {
        printf("无法弹出元素:栈为空!\n");
        return NULL;
    }
    tempCharStack->charTop--;
    return tempCharStack->charData[tempCharStack->charTop+1];
}

判断优先级

*/的优先级高于+-,故在表达式中应与数学上先查出后加减的规则相同,此处设*/的优先级数为2+-的优先级数为1,通过比较返回的优先级数的大小比较运算符的优先级。

int judgePriority(char tempChar)
{
    if(tempChar == '+' || tempChar == '-')
    {
        return 1;
    }else if(tempChar == '*' || tempChar == '/')
    {
        return 2;
    }
}

计算(核心代码)

1. 由于输入表达式时,是将数字以字符形式存入字符串中,所以一个单元格只能存一位数字,在处理多位数时,采用归并的思想,先读取一位数字expression[j++],再设int tempResult = 0,通过tempResult = tempResult * 10 +expression[j++] - '0'实现将已读取到的数字归并到tempResult 中;以此往复,若下一位为数字则归并一次。

2. 读取时遇到运算符,则比较其与运算符栈栈顶元素的优先级,若其优先级低于栈顶元素优先级则进行计算,并将结果存入操作数栈,继续比较该运算符与栈顶运算符的优先级。遇到右括号时不将其压入运算符栈,取出运算符栈栈顶运算符和操作数栈栈顶的两个操作数进行运算,并将结果压入操作数栈,直到弹出左括号为止。

/* 计算 */
void eval(numStackPtr tempNumStack, charStackPtr tempCharStack)
{
    int a = numPop(tempNumStack);
    int b = numPop(tempNumStack);
    char c = charPop(tempCharStack);
    int tempResult;
    switch (c)
    {
    case '+':
        tempResult = b + a;
        break;
    case '-':
        tempResult = b - a;
        break;
    case '*':
        tempResult = b * a;
        break;
    case '/':
        tempResult = b / a;
        break;
    default:
        break;
    }
    numPush(tempNumStack,tempResult);
}

int main()
{
    numStackPtr tempNumStack = initNumStack();
    charStackPtr tempCharStack = initCharStack();
    char expression[2*MAXSIZE];
    gets(expression);
    for(int i = 0;i < strlen(expression); ++i)
    {
        char temp = expression[i];
        if(isdigit(temp))
        {
            int tempResult = 0,j = i;
            while (j < strlen(expression) && isdigit(expression[j]))
            {
                tempResult = tempResult * 10 +expression[j++] - '0';
            }
            i = j - 1;
            numPush(tempNumStack,tempResult);
        }else if(temp == '(')
        {
            charPush(tempCharStack,temp);
        }else if(temp == ')')
        {
            while (tempCharStack->charData[tempCharStack->charTop] != '(')
            {
                eval(tempNumStack,tempCharStack);
            }
            charPop(tempCharStack);
        }else
        {
            while(tempCharStack->charTop != -1 && tempCharStack->charData[tempCharStack->charTop] != '(' && judgePriority(tempCharStack->charData[tempCharStack->charTop]) >= judgePriority(temp))
            {
                eval(tempNumStack,tempCharStack);
            }
            charPush(tempCharStack,temp);
        }
    }
    while(tempCharStack->charTop != -1)
    {
        eval(tempNumStack,tempCharStack);
    }
    printf("%d\n",tempNumStack->numData[tempNumStack->numTop]);
    return 0;
}

完整代码

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

#define MAXSIZE 40

typedef struct numStack
{
    int numTop;
    int numData[MAXSIZE];
} numStack, *numStackPtr;

typedef struct charStack
{
    int charTop;
    char charData[MAXSIZE];
} charStack, *charStackPtr;

/* 数字栈初始化 */
numStackPtr initNumStack()
{
    numStackPtr numHeader = (numStackPtr)malloc(sizeof(numStack));
    numHeader->numTop = -1;
    return numHeader;
}

/* 操作符栈初始化 */
charStackPtr initCharStack()
{
    charStackPtr charHeader = (charStackPtr)malloc(sizeof(charStack));
    charHeader->charTop = -1;
    return charHeader;
}

/* 数字压栈 */
void numPush(numStackPtr tempNumStack, int tempNum)
{
    if(tempNumStack->numTop >= MAXSIZE - 1)
    {
        printf("无法压入元素%d:栈已满!\n",tempNum);
        return;
    }
    tempNumStack->numTop++;
    tempNumStack->numData[tempNumStack->numTop] = tempNum;
}

/* 操作符压栈 */
void charPush(charStackPtr tempCharStack, char tempChar)
{
    if(tempCharStack->charTop >= MAXSIZE - 1)
    {
        printf("无法压入元素%c:栈已满!\n",tempChar);
        return;
    }
    tempCharStack->charTop++;
    tempCharStack->charData[tempCharStack->charTop] = tempChar;
}

/* 数字弹栈 */
int numPop(numStackPtr tempNumStack)
{
    if(tempNumStack->numTop == -1)
    {
        printf("无法弹出元素:栈为空!\n");
        return NULL;
    }
    tempNumStack->numTop--;
    return tempNumStack->numData[tempNumStack->numTop+1];
}

/* 操作符弹栈 */
char charPop(charStackPtr tempCharStack)
{
    if(tempCharStack->charTop == -1)
    {
        printf("无法弹出元素:栈为空!\n");
        return NULL;
    }
    tempCharStack->charTop--;
    return tempCharStack->charData[tempCharStack->charTop+1];
}

int judgePriority(char tempChar)
{
    if(tempChar == '+' || tempChar == '-')
    {
        return 1;
    }else if(tempChar == '*' || tempChar == '/')
    {
        return 2;
    }
}

/* 计算 */
void eval(numStackPtr tempNumStack, charStackPtr tempCharStack)
{
    int a = numPop(tempNumStack);
    int b = numPop(tempNumStack);
    char c = charPop(tempCharStack);
    int tempResult;
    switch (c)
    {
    case '+':
        tempResult = b + a;
        break;
    case '-':
        tempResult = b - a;
        break;
    case '*':
        tempResult = b * a;
        break;
    case '/':
        tempResult = b / a;
        break;
    default:
        break;
    }
    numPush(tempNumStack,tempResult);
}

int main()
{
    numStackPtr tempNumStack = initNumStack();
    charStackPtr tempCharStack = initCharStack();
    char expression[2*MAXSIZE];
    gets(expression);
    for(int i = 0;i < strlen(expression); ++i)
    {
        char temp = expression[i];
        if(isdigit(temp))
        {
            int tempResult = 0,j = i;
            while (j < strlen(expression) && isdigit(expression[j]))
            {
                tempResult = tempResult * 10 +expression[j++] - '0';
            }
            i = j - 1;
            numPush(tempNumStack,tempResult);
        }else if(temp == '(')
        {
            charPush(tempCharStack,temp);
        }else if(temp == ')')
        {
            while (tempCharStack->charData[tempCharStack->charTop] != '(')
            {
                eval(tempNumStack,tempCharStack);
            }
            charPop(tempCharStack);
        }else
        {
            while(tempCharStack->charTop != -1 && tempCharStack->charData[tempCharStack->charTop] != '(' && judgePriority(tempCharStack->charData[tempCharStack->charTop]) >= judgePriority(temp))
            {
                eval(tempNumStack,tempCharStack);
            }
            charPush(tempCharStack,temp);
        }
    }
    while(tempCharStack->charTop != -1)
    {
        eval(tempNumStack,tempCharStack);
    }
    printf("%d\n",tempNumStack->numData[tempNumStack->numTop]);
    return 0;
}

运行测试

在这里插入图片描述

4+4*2+4*(3+2)+(3+7)/5
4+4*2+4*(3+2)+(3+7)/5 = 34

c++版本

#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <unordered_map>

using namespace std;

stack<int> num;
stack<char> op;

void eval()
{
    auto b = num.top();
    num.pop();
    auto a = num.top();
    num.pop();
    auto c = op.top();
    op.pop();
    int x;
    if (c == '+') x = a + b;
    else if (c == '-') x = a - b;
    else if (c == '*') x = a * b;
    else x = a / b;
    num.push(x);
}

int main()
{
    unordered_map<char, int> pr{ {'+', 1}, {'-', 1}, {'*', 2}, {'/', 2} };
    string str;
    cin >> str;
    for (int i = 0; i < str.size(); i++)
    {
        auto c = str[i];
        if (isdigit(c))
        {
            int x = 0, j = i;
            while (j < str.size() && isdigit(str[j]))
                x = x * 10 + str[j++] - '0';
            i = j - 1;
            num.push(x);
        }
        else if (c == '(') op.push(c);
        else if (c == ')')
        {
            while (op.top() != '(') eval();
            op.pop();
        }
        else
        {
            while (op.size() && op.top() != '(' && pr[op.top()] >= pr[c]) eval();
            op.push(c);
        }
    }
    while (op.size()) eval();
    cout << str <<" = "<< num.top() << endl;
    return 0;
}

运行结果

在这里插入图片描述

4+4*2+4*(3+2)+(3+7)/5
4+4*2+4*(3+2)+(3+7)/5 = 34

注:该代码需在较高版本环境下才能运行

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黎子想写好代码

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

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

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

打赏作者

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

抵扣说明:

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

余额充值