您的位置:首页 > 其它

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

2018-01-01 23:03 357 查看

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

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;
}


运行截图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: