数据结构之线性表——中缀表达式和后缀表达式(栈的应用)

来源:互联网 发布:学术数据库有哪些 编辑:程序博客网 时间:2024/04/29 22:19


1 中缀表达式

中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。

举例:
(3 + 4) × 5 - 6 就是中缀表达式
3 4 + 5 × 6 - 后缀表达式

2 后缀表达式

不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *

3 中缀表达式转后缀表达式

中缀转后缀的算法
遍历表达式中的数字和符号
对于数字:直接输出
对于符号:
左括号:进栈
运算符号:与栈顶元素进行优先级比较
 若栈顶符号优先级低:此符号进栈(默认:栈顶若是左括号,左括号优先级最低)
 若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
右括号:将栈顶符号弹出并输出
遍历结束:将栈中所有符号弹出并输出
中缀转后缀


代码实现:其中LinkStack.h的内容参考《数据结构之线性表——栈的链式存储》

#include"LinkStack.h"#include<stdio.h>using namespace std;/*中缀转后缀的算法遍历表达式中的数字和符号对于数字:直接输出对于符号:左括号:进栈运算符号:与栈顶元素进行优先级比较  若栈顶符号优先级低:此符号进栈(默认:栈顶若是左括号,左括号优先级最低)  若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈右括号:将栈顶符号弹出并输出遍历结束:将栈中所有符号弹出并输出中缀转后缀*//*计算表达式结果:*/int isNumber(char c){return ('0' <= c) && (c <= '9');}int isOperator(char c){return (c == '+') || (c == '-') || (c == '*') || (c == '/');}int isLeft(char c){return (c == '(');}int isRight(char c){return (c == ')');}int priority(char c){int ret = 0;if ((c == '+') || (c == '-')){ret = 1;}if ((c == '*') || (c == '/')){ret = 2;}return ret;}void output(char c){if (c != '\0'){printf("%c ", c);}}void transform(const char* exp){int i = 0;LinkStack* stack = LinkStack_Create();while (exp[i] != '\0'){if (isNumber(exp[i])){output(exp[i]);}else if (isOperator(exp[i])){while (LinkStack_Size(stack) > 0 && priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack))){output((char)(int)LinkStack_Pop(stack));}LinkStack_Push(stack, (void*)(int)exp[i]);}else if (isLeft(exp[i])){LinkStack_Push(stack, (void*)(int)exp[i]);}else if (isRight(exp[i])){//char c = '\0';while (!isLeft((char)(int)LinkStack_Top(stack))){output((char)(int)LinkStack_Pop(stack));}LinkStack_Pop(stack);}else{printf("Invalid expression!");break;}i++;}while ((LinkStack_Size(stack) > 0) && (exp[i] == '\0')){output((char)(int)LinkStack_Pop(stack));}LinkStack_Destroy(stack);}int main(){transform("8+(3-1)*5");printf("\n");return 0;}

4 后缀表达式的计算

遍历后缀表达式中的数字和符号

对于数字:进栈

对于符号:

从栈中弹出右操作数

从栈中弹出左操作数

根据符号进行运算

将运算结果压入栈中

遍历结束:栈中的唯一数字为计算结果


代码实现:其中LinkStack.h的内容参考《数据结构之线性表——栈的链式存储

#include"LinkStack.h"#include<stdio.h>int isNumber(char c){return ('0' <= c) && (c <= '9');}int isOperator(char c){return (c == '+') || (c == '-') || (c == '*') || (c == '/');}int value(char c){return (c - '0');}int express(int left, int right, char op){int ret = 0;switch (op){case '+':ret = left + right;break;case '-':ret = left - right;break;case '*':ret = left * right;break;case '/':ret = left / right;break;default:break;}return ret;}int compute(const char * exp){LinkStack * stack = LinkStack_Create();int ret = 0;int i = 0;while (exp[i] != '\0'){if (isNumber(exp[i])){LinkStack_Push(stack, (void *)value(exp[i]));}else if (isOperator(exp[i])){int right = (int)LinkStack_Pop(stack);int left = (int)LinkStack_Pop(stack);int result = express(left, right, exp[i]);LinkStack_Push(stack, (void *)result);}else{printf("Invalid expression!");break;}i++;}if ((LinkStack_Size(stack) == 1) && (exp[i] == '\0')){ret = (int)LinkStack_Pop(stack);}else{printf("Invalid expression!");}LinkStack_Destroy(stack);return ret;}int main(){printf("8 + (3 - 1) * 5  = %d\n", compute("831-5*+"));//system("pause");return 0;}


0 0
原创粉丝点击