逆波兰计算器--中缀表达式转后缀表达式

首先说说,啥是中缀表达式

1+(2+3)*4+5/2
这就叫中缀表达式,也就是说运算符在两个操作数中间,这比较符合我们人类正常的计算题书写规则与习惯.一目了然有木有;

那么啥是后缀表达式呢,聪明的朋友应该很容易就想到了,就是运算符在操作数的后面,

比如1+3 要写成1 3+
1*( 2 + 3)要写成1 2 3 + *
那么上面的中缀表达式转换成后缀表达式的写法就是:
1 2 3 + 4 * + 5 2 / +
看着很扎心有没有,不要不好意思承认.但是计算机却很喜欢这样的写法,是不是有点反人类.为什么会这样呢,因为计算机没有办法像人类一样一眼瞟过去就知道优先级.先算什么再算什么,必须你给它摆的明明白白的才可以,而后缀表达式就可以解决这个问题,但是要结合栈的记忆功能才能做到,具体原理如下:
每次遇到数字就入栈,遇到操作符就从栈顶依次弹栈得到就近的两个操作数,再将计算出的结果入栈.然后继续往后走,当整个表达式读取完时,栈中的数据就是最终结果,将其弹出即可.

慢镜头演示一下计算机处理:1 2 3 + 4 * + 5 2 / + 的过程

–1,2,3依次进栈,此时栈内依次为1 2 3
–遇到+ 2 3出栈计算得到5, 5再进栈,此时栈内依次为1 5
–4进栈,此时栈内依次为1 5 4
–遇到 * ,4 5 出栈计算得到20, 20再进栈, 此时栈内依次为1 20
–遇到+, 1 20出栈计算得到21, 21再进栈, 此时栈内依次为21
–5 2 进栈, 此时栈内依次为21 5 2
–遇到 /, 5 2出栈计算得到2.5, 2.5再进栈, 此时栈内依次为21 2.5
–遇到 +, 21 2.5出栈计算得到23.5, 23.5再进栈, 此时栈内依次为23.5
–最后23.5出栈,即为表达式1+(2+3)*4+5/2的最终结果

那么要让计算机能够处理带优先级的算术题,首先就要解决将中缀表达式转化为后缀表达式的问题,这是第一步.

再次对比中缀与后缀两种的写法
1 + (2 + 3) * 4 + 5 / 2
1 2 3 + 4 * + 5 2 / +

对照以下规则反复推敲演变过程:

1,逐个读取输入的中缀表达式中的字符
2,如果是数字,直接打印
3,如果是+或-,那么我们可以断定栈顶符号的优先级不可能比它们更低.此时若栈不为空,则将栈顶符号依次出栈并打印,如果出栈过程中遇到左括号’(‘,就老老实实的再将它老人家放回去,因为 ‘(’ 只有在遇到 ‘)’ 时才会出栈.也就是说守在外面的+或-只有在遇到’(‘或者栈空了才能进去,这应该是整个逻辑中最复杂的一环
4,如果是’)’,那么栈顶元素依次出栈并打印,直到’(‘出栈,配对成功为止.
5,如果是’(‘或者’*’或者’/’,不用想直接进栈
6,处理完成时一定要确保栈内所有元素均已出栈并打印

废话少说,丢代码

SqStack.h

#define _CRT_SECURE_NO_WARNINGS
#include    <stdio.h>
#include    <stdlib.h>
#include    <time.h>
#define     OK          1
#define     ERROR       0
#define     MAXSIZE     100

typedef char    SElemType;
typedef int     Status;
typedef struct
{
    SElemType       data[MAXSIZE];
    int             top;
}SqStack;

//栈的初始化
Status InitStack(SqStack **S);

//入栈
Status  Push(SqStack *S, SElemType e);

//出栈
Status  Pop(SqStack *S, SElemType *e);

//判断是否为空栈
int StackEmpty(SqStack *S);

SqStack.c

#include    "SqStack.h"

//栈的初始化
Status InitStack(SqStack **S)
{
    *S = (SqStack*)malloc(sizeof(SqStack));
    if (!(*S))
        return ERROR;
    (*S)->top = -1;
    return OK;
}

//入栈
Status  Push(SqStack *S, SElemType e)
{
    if (S->top == MAXSIZE - 1)
    {
        return ERROR;       //栈满
    }
    S->top++;
    S->data[S->top] = e;
    return OK;
}


//出栈
Status  Pop(SqStack *S, SElemType *e)
{
    if (S->top == -1)
    {
        return ERROR;       //空栈
    }
    *e = S->data[S->top];
    S->top--;
    return OK;
}

//判断是否为空栈
int StackEmpty(SqStack *S)
{
    return S->top == -1;
}

main.c

#include    "SqStack.h"
int main()
{
    SqStack *S;
    SElemType c , e;
    InitStack(&S);
    puts("\n请输入中缀表达式,以#符号作为结尾");
    c = getchar();
    while ('#' != c)
    {
        while(c >= '0' && c <= '9')
        {
            putchar(c);
            c = getchar();
            if (c < '0' || c > '9')
            {
                putchar(' ');
            }
        }

        if (')' == c)
        {
            Pop(S, &e);
            while ('(' != e)
            {
                printf("%c ",e);
                Pop(S, &e);
            }
        }
        else if ('+' == c || '-' == c)
        {
            if (StackEmpty(S))
            {
                Push(S, c);
            }
            else
            {
                do
                {
                    Pop(S, &e);
                    if ('(' == e)
                    {
                        Push(S, e);
                    }
                    else
                    {
                        printf("%c ", e);
                    }
                } while (!StackEmpty(S) && e != '(');
                Push(S, c);
            }
        }
        else if ('(' == c || '*' == c || '/' == c)
        {
            Push(S, c);
        }
        else if ('#' == c)
        {
            break;
        }
        else
        {
            puts("输入格式错误\n");
            return -1;
        }
        c = getchar();
    }
    while (!StackEmpty(S))
    {
        Pop(S, &e);
        printf("%c ", e);
    }
    getchar();
    getchar();
    return 1;
}

运行截图

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值