逆波兰计算器--中缀表达式转后缀表达式
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; }
运行截图
相关文章推荐
- 逆波兰计算器与中缀表达式向后缀表达式的转化实例
- 逆波兰表达式-中缀转后缀(计算器)
- 将中缀表达式转化成后缀表达式(逆波兰式)
- 中缀表达式转后缀表达式之多项式计算器
- 中缀表达式转后缀表达式(逆波兰表达式)
- ---中缀表达式转换为后缀表达式---模拟计算器-----堆栈
- 中缀表达式转换为后缀表达式及逆波兰式计算
- 计算器实现---中缀表达式转后缀表达式
- 中缀表达式转化为后缀表达式,计算中缀表达式,计算后缀表达式(有注释)(逆波兰表达式)
- 中缀表达式转后缀(逆波兰)表达式
- 计算器(中缀表达式转后缀表达式)
- 逆波兰:将中缀表达式转为后缀表达式
- 中缀表达式转换成后缀表达式以及逆波兰表示法求值
- 逆波兰中 中缀表达式转后缀表达式的方法
- 整理一下中缀表达式转后缀表达式(逆波兰表达式)的算法-调度场算法(shunting yard algorithm)
- 逆波兰式(中缀表达式转成后缀表达式)
- c++ 中缀表达式转后缀表达式 计算器
- 【数据结构】逆波兰表示法(RPN):中缀表达式转后缀表达式
- 计算器:中缀表达式转后缀表达式
- C语言利用栈实现将中缀表达式转换为后缀表达式(即逆波兰式)