严蔚敏数据结构C语言版表达式求值

由于正常情况下一般采用=作为表达式结尾,故本文所示代码将课本中的‘#’改为了‘=’以便更好地应用于现实情况

一、表达式求值所用到的数据结构——栈

首先来实现栈的基本操作,不知道的可以看我之前发过的一篇文章:栈的基本操作

在表达式求值中,只需用到以下列出的几个函数


typedef char SElemType;
typedef char Status;
typedef struct {
    SElemType* top;
    SElemType* base;
    int stacksize;
}Stack;
Status InitStack(Stack& S);
bool StackEmpty(Stack S);
int StackLength(Stack S);
Status DestroyStack(Stack& S);
Status Push(Stack& S, SElemType e);
Status Pop(Stack& S, SElemType& e);
Status GetTop(Stack S);

不再进行额外的解释,下面附上这些函数的代码


Status GetTop(Stack S)
{
    if (S.top == S.base)return 0;
    Status e = *(S.top - 1);
    return e;
}
Status InitStack(Stack& S)
{
    S.base = (SElemType*)malloc(sizeof(SElemType) * MAXSIZE);
    if (!S.base)return 0;
    S.top = S.base;
    S.stacksize = MAXSIZE;
    return 1;
}
bool StackEmpty(Stack S)
{
    return S.top == S.base;
}
int StackLength(Stack S)
{
    return S.top - S.base;
}
Status DestroyStack(Stack& S)
{
    if (!S.base)return 0;
    free(S.base);
    S.base = S.top = NULL;
    return 1;
}
Status Push(Stack& S, SElemType e)
{
    if (!S.base)return 0;
    if (S.top - S.base == S.stacksize)return 0;
    *S.top++ = e;
    return 1;
}
Status Pop(Stack& S, SElemType& e)
{
    if (StackEmpty(S))return 0;
    e = *--S.top;
    return 1;
}

二、表达式求值核心函数

1.核心函数


int EvaluateExpression()
{
    char x;
    Stack OPTR, OPND;
    InitStack(OPTR);
    InitStack(OPND);
    Push(OPTR, '=');
    char c = getchar();
    while (c != '=' || GetTop(OPTR) != '=')
    {
        printf("OPTR:"); for (int i = 0; i < OPTR.top - OPTR.base; i++)printf("%c ", OPTR.base[i]); puts("");
        printf("OPND:"); for (int i = 0; i < OPND.top - OPND.base; i++)printf("%d ", OPND.base[i]); puts("\n");
        if (!In(c)){Push(OPND, c-'0'); c = getchar(); }
        else
        {
            switch (Precede(GetTop(OPTR), c))
            {
            case'<':
                Push(OPTR, c);
                c = getchar();
                break;
            case'=':
                Pop(OPTR, x);
                c = getchar();
                break;
            case'>':
                char theta, p, q;
                Pop(OPTR, theta);
                Pop(OPND, p);
                Pop(OPND, q);
                Push(OPND, Operate(p, theta, q));
            }
        }
    }
    int g = (int)GetTop(OPND);
    DestroyStack(OPTR);
    DestroyStack(OPND);
    return g;
}

在这个函数中用到了一些除了栈的基本操作外的其他函数,下面逐一说明这些函数的功能

2.判断字符函数

在主函数中用此函数用来判断最后一个输入的字符是否是运算符


bool In(char c)
{
    if (c <= '9' && c >= '0')return 0;
    else return 1;
}

3.判断优先级的函数

在主函数中用来判断两个运算符的优先级谁大谁小


Status Precede(char a, char b)
{
    char x[10]     =    {'+','-','*','/','(',')','='};
    char OP[10][10] = { {'>','>','<','<','<','>','>'},
                        {'>','>','<','<','<','>','>'},
                        {'>','>','>','>','<','>','>'},
                        {'>','>','>','>','<','>','>'},
                        {'<','<','<','<','<','=',' '},
                        {'>','>','>','>',' ','>','>'},
                        {'<','<','<','<','<',' ','='} };
    for (int i = 0; i < 7; i++)
    {
        if (a == x[i])a = i;
        if (b == x[i])b = i;
    }
    return OP[a][b];
}

4.运算函数

用来运算,注意在出栈的时候后者先出,故减和除的运算数需要颠倒,其次注意除法分母不为零


char Operate(char p, char theta, char q)
{
    if (theta == '+')return p + q;
    else if (theta == '-')return q - p;
    else if (theta == '*')return p * q;
    else if (theta == '/')
    {
        if (p == 0)
        {
            printf("输入不合法!");
            return INF;
        }
        return q / p;
    }
    else return INF;
}

三、总代码和运行结果展示


#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
#define INCREAMENTSIZE 10
#define INF 1e9
typedef char SElemType;
typedef char Status;
typedef struct {
    SElemType* top;
    SElemType* base;
    int stacksize;
}Stack;
Status InitStack(Stack& S);
bool StackEmpty(Stack S);
int StackLength(Stack S);
Status DestroyStack(Stack& S);
Status Push(Stack& S, SElemType e);
Status Pop(Stack& S, SElemType& e);
Status GetTop(Stack S);
int EvaluateExpression();
char Operate(char p, char theta, char q);
bool In(char c);
Status Precede(char a, char b);
int main()
{
    printf("请输入一串表达式,以等号“=”结尾:");
    printf("最终结果为:%d", EvaluateExpression());
    return 0;
}
int EvaluateExpression()
{
    char x;
    Stack OPTR, OPND;
    InitStack(OPTR);
    InitStack(OPND);
    Push(OPTR, '=');
    char c = getchar();
    while (c != '=' || GetTop(OPTR) != '=')
    {
        printf("OPTR:"); for (int i = 0; i < OPTR.top - OPTR.base; i++)printf("%c ", OPTR.base[i]); puts("");
        printf("OPND:"); for (int i = 0; i < OPND.top - OPND.base; i++)printf("%d ", OPND.base[i]); puts("\n");
        if (!In(c)){Push(OPND, c-'0'); c = getchar(); }
        else
        {
            switch (Precede(GetTop(OPTR), c))
            {
            case'<':
                Push(OPTR, c);
                c = getchar();
                break;
            case'=':
                Pop(OPTR, x);
                c = getchar();
                break;
            case'>':
                char theta, p, q;
                Pop(OPTR, theta);
                Pop(OPND, p);
                Pop(OPND, q);
                Push(OPND, Operate(p, theta, q));
            }
        }
    }
    int g = (int)GetTop(OPND);
    DestroyStack(OPTR);
    DestroyStack(OPND);
    return g;
}
Status Precede(char a, char b)
{
    char x[10]     =    {'+','-','*','/','(',')','='};
    char OP[10][10] = { {'>','>','<','<','<','>','>'},
                        {'>','>','<','<','<','>','>'},
                        {'>','>','>','>','<','>','>'},
                        {'>','>','>','>','<','>','>'},
                        {'<','<','<','<','<','=',' '},
                        {'>','>','>','>',' ','>','>'},
                        {'<','<','<','<','<',' ','='} };
    for (int i = 0; i < 7; i++)
    {
        if (a == x[i])a = i;
        if (b == x[i])b = i;
    }
    return OP[a][b];
}
char Operate(char p, char theta, char q)
{
    if (theta == '+')return p + q;
    else if (theta == '-')return q - p;
    else if (theta == '*')return p * q;
    else if (theta == '/')
    {
        if (p == 0)
        {
            printf("输入不合法!");
            return INF;
        }
        return q / p;
    }
    else return INF;
}
bool In(char c)
{
    if (c <= '9' && c >= '0')return 0;
    else return 1;
}
Status GetTop(Stack S)
{
    if (S.top == S.base)return 0;
    Status e = *(S.top - 1);
    return e;
}
Status InitStack(Stack& S)
{
    S.base = (SElemType*)malloc(sizeof(SElemType) * MAXSIZE);
    if (!S.base)return 0;
    S.top = S.base;
    S.stacksize = MAXSIZE;
    return 1;
}
bool StackEmpty(Stack S)
{
    return S.top == S.base;
}
int StackLength(Stack S)
{
    return S.top - S.base;
}
Status DestroyStack(Stack& S)
{
    if (!S.base)return 0;
    free(S.base);
    S.base = S.top = NULL;
    return 1;
}
Status Push(Stack& S, SElemType e)
{
    if (!S.base)return 0;
    if (S.top - S.base == S.stacksize)return 0;
    *S.top++ = e;
    return 1;
}
Status Pop(Stack& S, SElemType& e)
{
    if (StackEmpty(S))return 0;
    e = *--S.top;
    return 1;
}

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AAAAAZBX

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

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

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

打赏作者

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

抵扣说明:

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

余额充值