数据结构课实验习题--中缀表达式转换为后缀表达式并求值

所谓中缀表达式与后缀表达式的定义,即是看运算符在操作数的位置如何

中缀表达式即作符是以中缀形式处于操作数的中间(例:3 + 4)

后缀表达式(也叫逆波兰表达式)则为3 4 +

以下摘抄百度百科:

一个表达式E的后缀形式可以如下定义:

(1)如果E是一个变量或常量,则E的后缀式是E本身。

(2)如果E是E1 op E2形式的表达式,这里op是任何二元操作符,则E的后缀式为E1'E2' op,这里E1'和E2'分别为E1和E2的后缀式。

(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。

如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+

(a+b)*c-(a+b)/e的后缀表达式为:

(a+b)*c-(a+b)/e

→((a+b)*c)((a+b)/e)-

→((a+b)c*)((a+b)e/)-

→(ab+c*)(ab+e/)-

→ab+c*ab+e/-

由这个例子可以看出,中缀表达式转化为后缀表达式的实质就是,将每个 “部分式” 的算术符号移到式子后面

还是以百度的例子为例:

第一步,把整个式子看作一个部分,左边的数是(a+b)*c,右边的是(a+b)/e,将➖号移到式子最后

第二步,再把第一步式子的两个“数”做相似处理,例如(a+b)*c,看成(a+b) 和c,将✖号移到式子最后

第三步。。。。。。

那么我们如何使用栈来实现转换呢?

读入中缀表达式infix[i];

1.遇到数字 0-9 ,则将其直接送进后缀表达式postfix[]数组

2.如果遇到左括号 '(' ,入栈(起到了限制范围的作用)

3.如果遇到右括号')' ,弹出上一个左括号'('之前的所有运算符并送入postfix ;注意左括号'('只弹出不赋值

4.如果遇到运算符(+ - * /),就将栈中所有优先级大于等于它的运算符出栈,直到栈空,再把该运算符入栈

后缀表达式求值:

1.遇到数字0-9,直接进栈

2.遇到运算符(+ - * /),将栈中头两个数弹出来进行运算,并将结果入栈

附代码:

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

typedef struct _nodechar
{
    char data;
    struct _nodechar *next;
} nodechar;

typedef struct _stackchar
{
    int size;
    nodechar *top;
} stackchar;
typedef struct _nodeint
{
    int data;
    struct _nodeint *next;
} nodeint;

typedef struct _stackint
{
    int size;
    nodeint *top;
} stackint;

int getPriority(char opt)
{
    if(opt == '+' || opt =='-')
        return 1;
    if(opt == '*' || opt == '/')
        return 2;
    return 0;
}

int calucalte(int opt1, char opt, int opt2)
{
    switch(opt)
    {
    case '+':
        return opt1 + opt2;
        break;
    case '-':
        return opt1 - opt2;
        break;
    case '*':
        return opt1 * opt2;
        break;
    case '/':
        return opt1 / opt2;
        break;
    }
    return 0;
}
stackchar *createStackchar(void)
{
    stackchar* p = (stackchar*)malloc(sizeof(stackchar));
    p->size = 0;
    p->top = NULL;
    return p;
}
void pushchar(stackchar* pStack, char x)
{
    nodechar *t = (nodechar*)malloc(sizeof(nodechar));
    t->data = x;
    t->next = pStack->top;
    pStack->top = t;
    pStack->size++;
}
void popchar(stackchar* pStack)
{
    nodechar *t = pStack->top;
    pStack->top = t->next;
    free(t);
    pStack->size--;
}
char topchar(stackchar* pStack)
{
    return pStack->top->data;
}
bool emptychar(stackchar* pStack)
{
    return pStack->top == NULL;
}
void destroyStackchar(stackchar* pStack)
{
    while (!emptychar(pStack))
    {
        popchar(pStack);
    }
    free(pStack);
}

stackint *createStackint(void)
{
    stackint* p = (stackint*)malloc(sizeof(stackint));
    p->size = 0;
    p->top = NULL;
    return p;
}
void pushint(stackint* pStack, int x)
{
    nodeint *t = (nodeint*)malloc(sizeof(nodeint));
    t->data = x;
    t->next = pStack->top;
    pStack->top = t;
    pStack->size++;
}
void popint(stackint* pStack)
{
    nodeint *t = pStack->top;
    pStack->top = t->next;
    free(t);
    pStack->size--;
}
int topint(stackint* pStack)
{
    return pStack->top->data;
}
bool emptyint(stackint* pStack)
{
    return pStack->top == NULL;
}
void destroyStackint(stackint* pStack)
{
    while (!emptyint(pStack))
    {
        popint(pStack);
    }
    free(pStack);
}
int main(void)
{
	//转换部分 
    int n;
    scanf("%d", &n);
    while(n--)
    {
        char infix[21], postfix[21] = "\0";
        int index = 0;
        scanf("%s", infix);
        stackchar *pStackchar = createStackchar();
        for(int i = 0; infix[i] != '\0'; i++)
        {
            if(infix[i] >= '0' && infix[i] <= '9')
            {
                postfix[index++] = infix[i];
            }
            else if(infix[i] == '(')
            {
                pushchar(pStackchar, infix[i]);
            }
            else if(infix[i] == ')')
            {
                char c = topchar(pStackchar);
                popchar(pStackchar);
                while(c != '(')
                {
                    postfix[index++] = c;
                    c = topchar(pStackchar);
                    popchar(pStackchar);
                }
            }
            else//算术符号 
            {
                if(emptychar(pStackchar) || getPriority(infix[i]) > getPriority(topchar(pStackchar)))
                {
                    pushchar(pStackchar, infix[i]);
                }
                else
                {
                    while(!emptychar(pStackchar) && getPriority(infix[i]) <= getPriority(topchar(pStackchar)))
                    {
                        char c = topchar(pStackchar);
                        popchar(pStackchar);
                        postfix[index++] = c;
                    }
                    pushchar(pStackchar, infix[i]);
                }
            }
        }
        while(!emptychar(pStackchar))
        {
            char c = topchar(pStackchar);
            popchar(pStackchar);
            postfix[index++] = c;
        }
        printf("%s", postfix);
        destroyStackchar(pStackchar);
        
        //算值部分,优先级高的数在栈顶,优先级高的计算符号在符号序列最左边 
        stackint *pStackint = createStackint();
        for(int i = 0; postfix[i] != '\0'; i++)
        {
            if(postfix[i] >= '0' && postfix[i] <= '9')
            {
                int m = postfix[i] - '0';
                pushint(pStackint, m);
            }
            else
            {
                char opt = postfix[i];
                int opt2, opt1;
                opt2 = topint(pStackint);
                popint(pStackint);
                opt1 = topint(pStackint);
                popint(pStackint);
                pushint(pStackint, calucalte(opt1, opt, opt2));//先弹出的数要放在操作符的右边
            }
        }
        int ans = topint(pStackint);
        printf(" %d\n", ans);
        popint(pStackint);
        destroyStackint(pStackint);
    }
    return 0;
}

首先需要将中缀表达式转换后缀表达式。可以使用一个操作符栈来辅助转换过程。从左到右扫描中缀表达式的每个字符,并根据优先级进行相应的操作。 具体步骤如下: 1. 定义一个操作符栈和一个后缀表达式字符串。 2. 从左到右扫描中缀表达式的每个字符: - 如果遇到数字,直接添加到后缀表达式字符串中。 - 如果遇到左括号,将其压入操作符栈。 - 如果遇到右括号,弹出操作符栈中的操作符,并将其添加到后缀表达式字符串中,直到遇到左括号为止,并将左括号从操作符栈中弹出。 - 如果遇到操作符,比较其与操作符栈栈顶操作符的优先级: - 如果该操作符优先级大于栈顶操作符优先级,将其压入操作符栈。 - 如果该操作符优先级小于等于栈顶操作符优先级,将栈顶操作符弹出,并将其添加到后缀表达式字符串中,直到栈顶操作符优先级小于该操作符,或者栈为空,然后将该操作符压入操作符栈。 3. 扫描完中缀表达式后,将操作符栈中的所有操作符依次弹出,并添加到后缀表达式字符串中。 4. 最后,后缀表达式字符串即为转换后的后缀表达式。 接下来是对后缀表达式进行求值的过程: 1. 定义一个数值栈。 2. 从左到右扫描后缀表达式的每个字符: - 如果遇到数字,将其转换成数值并压入数值栈。 - 如果遇到操作符,从数值栈中弹出两个数值,进行相应的操作,并将结果压入数值栈。 3. 扫描完后缀表达式后,数值栈中的唯一元素即为求值结果。 综上所述,将中缀表达式转换后缀表达式求值的过程如上所述。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值