中缀表达式转逆波兰式并求值

合集下载

c++逆波兰式计算

c++逆波兰式计算

c++逆波兰式计算C++逆波兰式计算是一种基于后缀表达式的计算方法。

逆波兰式也称为后缀表达式,其中操作符位于操作数之后。

下面我会从多个角度来解释逆波兰式计算。

1. 逆波兰式的转换:将中缀表达式转换为逆波兰式的过程称为逆波兰式的转换。

这个过程可以通过使用栈来实现。

具体步骤如下:从左到右扫描中缀表达式的每个元素。

如果遇到操作数,则直接输出到逆波兰式。

如果遇到操作符,则与栈顶操作符比较优先级。

如果栈顶操作符优先级高于当前操作符,则将栈顶操作符输出到逆波兰式,然后将当前操作符入栈;否则将当前操作符入栈。

如果遇到左括号,则将其入栈。

如果遇到右括号,则将栈顶操作符输出到逆波兰式,直到遇到左括号。

左括号出栈,但不输出到逆波兰式。

扫描结束后,将栈中剩余的操作符依次输出到逆波兰式。

2. 逆波兰式的计算:逆波兰式计算是通过对逆波兰式进行求值来得到结果的过程。

这个过程同样可以使用栈来实现。

具体步骤如下:从左到右扫描逆波兰式的每个元素。

如果遇到操作数,则入栈。

如果遇到操作符,则从栈中弹出两个操作数,进行相应的运算,并将结果入栈。

扫描结束后,栈中的唯一元素即为最终的结果。

3. C++实现逆波兰式计算:在C++中,可以使用栈来实现逆波兰式的计算。

具体步骤如下:定义一个栈来存储操作数。

从左到右扫描逆波兰式的每个元素。

如果遇到操作数,则将其转换为数字并入栈。

如果遇到操作符,则从栈中弹出两个操作数,进行相应的运算,并将结果入栈。

扫描结束后,栈中的唯一元素即为最终的结果。

总结:逆波兰式是一种基于后缀表达式的计算方法,可以通过转换中缀表达式得到。

逆波兰式计算可以使用栈来实现,通过扫描逆波兰式的每个元素,根据操作数和操作符进行相应的操作,最终得到计算结果。

在C++中,可以使用栈来实现逆波兰式的计算。

希望以上解释能够满足你的需求。

把表达式转换为逆波兰表达式的方法

把表达式转换为逆波兰表达式的方法

把表达式转换为逆波兰表达式的方法把表达式转换为逆波兰表达式的方法什么是逆波兰表达式?逆波兰表达式(Reverse Polish Notation,简称RPN)是一种数学表达式的表示方法,其中运算符位于操作数的后面,而不是中间。

例如,将中缀表达式 3 + 4转换为逆波兰表达式的结果是 3 4 +。

为什么要使用逆波兰表达式?逆波兰表达式具有以下优点:1.不需要括号:逆波兰表达式由于运算符在操作数的后面,所以不需要括号来定义运算次序。

2.方便计算机计算:逆波兰表达式可以直接由计算机进行计算,减少了计算机解析表达式的复杂性。

3.避免二义性:逆波兰表达式的书写方式清晰明确,没有二义性。

方法一:使用栈实现转换1.初始化一个空栈和一个空列表用于存储转换后的逆波兰表达式。

2.从左到右扫描表达式。

3.如果遇到操作数(数字),则直接添加到逆波兰表达式列表中。

4.如果遇到运算符,按照以下规则处理:–如果栈为空或栈顶为左括号(或无运算符优先级低于当前运算符),则直接将运算符入栈。

–如果栈顶为运算符,并且其优先级大于等于当前运算符,将栈顶运算符出栈并添加到逆波兰表达式列表中,直到栈为空或栈顶为左括号(或无运算符优先级低于当前运算符)为止,然后将当前运算符入栈。

–如果当前运算符为右括号,则将栈顶运算符依次出栈并添加到逆波兰表达式列表中,直到遇到左括号为止。

5.扫描完成后,将栈中剩余的运算符依次出栈并添加到逆波兰表达式列表中。

6.逆波兰表达式列表即为转换后的结果。

方法二:使用递归实现转换1.定义一个递归函数,传入表达式和当前处理位置。

2.判断当前位置处的字符:–如果是数字,则直接返回该数字。

–如果是运算符,则递归调用函数获取左右两个操作数,并根据运算符将其组合成一个逆波兰表达式返回。

–如果是左括号,则继续向后处理直到找到对应的右括号。

3.递归函数返回结果即为转换后的逆波兰表达式。

方法三:使用中缀转后缀的方法1.定义两个栈,一个用于临时存储运算符,一个用于存储转换后的逆波兰表达式。

java逆波兰表达式求值

java逆波兰表达式求值

java逆波兰表达式求值一、什么是逆波兰表达式逆波兰表达式(Reverse Polish notation,简称RPN)是一种将运算符放在操作数后面的表达式表示方法。

例如,中缀表达式“2+3”可以写成逆波兰表达式“2 3 +”。

二、为什么要使用逆波兰表达式使用逆波兰表达式可以避免使用括号来区分优先级,使得计算机在计算时更加高效。

三、如何将中缀表达式转换为逆波兰表达式1. 创建一个栈S用于存储运算符。

2. 从左到右扫描中缀表达式的每个元素:(1)如果元素是数字,则直接输出。

(2)如果元素是运算符,则判断:a. 如果栈S为空或栈顶元素为左括号“(”,则将该运算符压入栈S中;b. 否则,比较该运算符与栈顶运算符的优先级:i. 如果该运算符优先级高于栈顶运算符,则将该运算符压入栈S中;ii. 否则,将栈顶元素弹出并输出,然后继续比较该运算符与新的栈顶元素的优先级。

(3)如果元素是左括号“(”,则将其压入栈S中。

(4)如果元素是右括号“)”,则依次弹出栈顶元素并输出,直到遇到左括号“(”,将左括号弹出但不输出。

3. 如果中缀表达式扫描完毕,则依次弹出栈中所有运算符并输出。

四、如何使用逆波兰表达式求值1. 创建一个栈S用于存储操作数。

2. 从左到右扫描逆波兰表达式的每个元素:(1)如果元素为数字,则将其压入栈S中。

(2)如果元素为运算符,则弹出栈顶的两个操作数进行运算,并将结果压入栈S中。

3. 如果逆波兰表达式扫描完毕,则栈S中只剩下一个数字,即为该表达式的计算结果。

五、Java实现逆波兰表达式求值可以通过使用Java的Stack类来实现上述算法。

具体步骤如下:1. 将中缀表达式转换为逆波兰表达式,得到一个字符串数组tokens。

2. 创建一个Stack<Integer>对象stack用于存储操作数。

3. 从左到右扫描tokens数组的每个元素:(1)如果元素为数字,则将其转换为整数并压入stack中。

中缀式到逆波兰式的转换及求值

中缀式到逆波兰式的转换及求值

号 等 ) 的 运 算 规 则 , 因 此 ,人 们 习 惯 用 中缀 式 对 于 运 算 的 实
现 ,特 别 是 计 算 机 或 计 算 器 的 实 现 来 说 ,实 际 上 是 比较 麻 烦 的。 同 样 ,在计 算 机 科 学 的 编译 领 域 中 。要 从 中缀式 直 接产 生 目标 代码 相 对 来 说 也 是 比较 麻 烦 的 。这 样 的 现 象 同样 体 现 在 一 些 财 务 或会 计 软 件 ( 工 资管 理 ) 中 。在 这 些 软 件 中 ,不 可避 如 免 地 都 要用 到公 式 的 定 义及 求 值 , 由于 财 务 、会 计计 算 中公 式 的复 杂 性 和 动 态 性 ,如 果 直 接用 中 缀 式 来 实 现 其 定 义 和 求 值 ,
表 1 中 缀式 、逆 波 兰 式对 照表
中缀式
a b + a b‘ + c
将 中缀 式 转换 成 逆 波 兰 式 并 进 行求 值 需 要 完 成 如 下 几 件工
作:
逆波兰式
a+ b a b* + c
( ) 对 中 缀 式 进 行 语 法 分 析 ( 的地 方 也 称 其 为 合 法 性 1 有
的运 算 的首 选 算法 。
逆 波 兰 式 不仅 能用 于 表 示 和 计 算 表 达式 .还 可 用 于 表 示 其
他 的语 法 结 构 ,此 时 的逆 波 兰 表 达 式 中 的运 算 符 不 再 仅仅 局 限
于算 术 运 算 符 、关 系运 算 符 和 逻辑 运算 符 ,而 且 ,每 个 运算 符
表 1是与 中缀 式对 应 的逆 波 兰 表示 。
另 外 ,逆 波 兰 式 的输 入 过 程 实 质 上 就 是 其 计 算 过 程 .因 此 ,可 以清 楚 地 看 到 整个 计 算 的 中间 结 果 。 它 的 这一 特 点 增 强 了交 互性 ,让 用 户 能够 在 运 算 的 过 程 中 方便 地发 现 和 改 正 运 算 错 误 ,并 且 还 能 很 好地 跟 踪 运 算 流 程 .动 态 地 自定义 运 算 过 程 中某 个 运 算 符 的 优 先 级 。在 1 7 9 2年 He l tP c ad公 司 发 现 we — akr t

rpn计算公式

rpn计算公式

rpn计算公式RPN(Reverse Polish Notation,逆波兰表达式)是一种数学表达式的计算方法,与传统的中缀表达式不同,它可以避免使用括号,减少了运算符优先级的问题,使得计算机可以更加方便地进行计算。

下面是将中缀表达式转换成逆波兰表达式,以及如何使用逆波兰表达式进行计算的方法:1. 将中缀表达式转换成逆波兰表达式:建立一个空的栈和一个空的输出列表。

从左到右扫描中缀表达式,遇到操作数时,将其加入到输出列表中;遇到运算符时,比较其优先级与栈顶运算符的优先级,如果栈顶运算符优先级高于或等于该运算符,则弹出栈顶运算符加入到输出列表中,直到栈顶运算符优先级低于该运算符,然后将该运算符加入到栈中。

重复上述步骤,直到完成所有运算符的处理,将栈中剩余的所有运算符依次弹出并加入到输出列表中。

最终输出列表中的就是逆波兰表达式。

例如,将中缀表达式”(2+3)*4-1”转换成逆波兰表达式的过程如下:中缀表达式:(2+3)*4-1逆波兰表达式:2 3 + 4 * 1 -2. 使用逆波兰表达式进行计算:建立一个空的栈。

从左到右扫描逆波兰表达式,遇到操作数时,将其压入栈中;遇到运算符时,从栈中弹出两个操作数,进行相应的计算,并将计算结果压入栈中。

重复上述步骤,直到完成所有运算符的处理,栈中仅剩下一个元素,就是表达式的计算结果。

例如,使用逆波兰表达式”2 3 + 4 * 1 -”进行计算的过程如下:逆波兰表达式:2 3 + 4 * 1 -计算过程:2 3 + -> 5;5 4 * -> 20;20 1 -> 19计算结果:19逆波兰表达式是一种数学表达式的计算方法,可以避免使用括号,减少了运算符优先级的问题,使得计算机可以更加方便地进行计算。

编译原理实验报告6-逆波兰式的翻译和计算

编译原理实验报告6-逆波兰式的翻译和计算

编译原理实验报告6-逆波兰式的翻译和计算实验6 逆波兰式的翻译和计算一、实验目的通过实验加深对语法指导翻译原理的理解,掌握算符优先分析的方法,将语法分析所识别的表达式变换成中间代码的翻译方法。

二、实验内容设计一个表示能把普通表达式(中缀式)翻译成后缀式,并计算出结果的程序。

三、实验要求1、给出文法如下:G[E]E->T|E+T;T->F|T*F;F->i(E);对应的转化为逆波兰式的语义动作如下:E-> E(1)op E(2) {E.CODE:=E(1).CODE||E(2).CODE||op}E->(E(1)) { E.CODE := E(1).CODE}E->id { E.CODE := id} 2、利用实验5中的算符优先分析算法,结合上面给出的语义动作实现逆波兰式的构造;3、利用栈,计算生成的逆波兰式,步骤如下:1)中缀表达式,从文本文件读入,每一行存放一个表达式,为了降低难度,表达式采用常数表达式;2)利用结合语法制导翻译的算符优先分析,构造逆波兰式;3)利用栈计算出后缀式的结果,并输出;四、实验环境PC微机DOS操作系统或Windows 操作系统Turbo C 程序集成环境或Visual C++ 程序集成环境#include<math.h>using namespace std;#define max 100char ex[max];int n;char GetBC(FILE* fp) {//读取文件的字符直至ch不是空白c har ch;d o {ch = fgetc(fp);} while (ch == ' ' || ch == '\t' || ch == '\n');r eturn ch;}void acquire(FILE* fp){c har str[max];c har stack[max];c har ch;i nt sum, i, j, t, top = 0;i = 0;/*读取一行表达式*/G etBC(fp);i f (feof(fp))return;e lse {fseek(fp, -1L, 1);printf("\n(%d)", n);n++;}d o{i++;str[i] = GetBC(fp);} while (str[i] != ';' && i != max); s um = i;t = 1;i = 1;c h = str[i];i++;w hile (ch != ';'){switch (ch){case '(':top++; stack[top] = ch;break;case ')':while (stack[top] != '(') {ex[t] = stack[top];top--;t++;}top--;break;case '+':case '-':while (top != 0 && stack[top] != '(') {ex[t] = stack[top];top--;t++;}top++;stack[top] = ch;break;case '*':case '/':while (stack[top] == '*' || stack[top] == '/'){ex[t] = stack[top];top--;t++;}top++;stack[top] = ch;break;case ' ':break;default:while (ch >= '0'&&ch <= '9'){ ex[t] = ch;t++;/*ex[ ]中存放逆波兰式 */ch = str[i];i++;/*str[ ]中存放中缀表达式*/ }i--;ex[t] = ',';t++;break;}ch = str[i];i++;}/*当中缀表达式扫描完毕,检查ω栈是否为空,若不空则一一退栈*/w hile (top != 0) {ex[t] = stack[top];t++;top--;}e x[t] = ';';f or (j = 1; j < sum; j++)printf("%c", str[j]);p rintf("\n输出:");f or (j = 1; j < t; j++)printf("%c", ex[j]);}void getValue() {f loat stack[max], d;c har ch;i nt t = 1, top = 0;c h = ex[t];t++;w hile (ch != ';'){switch (ch){case '+':stack[top - 1] = stack[top - 1] + stack[top];top--;break;case '-':stack[top - 1] = stack[top - 1] - stack[top];top--;break;case '*':stack[top - 1] = stack[top - 1] * stack[top];top--;break;case '/':if (stack[top] != 0)stack[top - 1] = stack[top - 1] / stack[top];else{printf("除零错误\n");break;/*异常退出*/}top--;break;/*将数字字符转化为对应的数值*/ default:d = 0;while (ch >= '0'&&ch <= '9') {d = 10 * d + ch - '0';ch = ex[t];t++;}top++;stack[top] = d;}ch = ex[t];t++;}p rintf("\t%g\n", stack[top]);}void main() {F ILE* fp;e rrno_t err;i f ((err = fopen_s(&fp,"C:\\Users\\Administrator\\Desktop\\e xpression.txt", "r")) != NULL){ //以只读方式打开文件,失败则退出程序printf("file can not open!");exit(0);}n = 1;p rintf("逆波兰式的翻译和计算结果如下:\n");w hile (1) {acquire(fp);if (feof(fp)) break;getValue(); }f close(fp);f p = NULL;}实验结果:问题:这次实验较之之前不同,在设计算法与数据结构上花的时间较少,因为之前在数据结构课程里做过使用堆栈完成表达式的计算,也学过中缀式和后缀式,所以代码编得较快,但是其中的算法其实是较复杂的,调试时显得更复杂而编程时我用的是VS,在调试开始时,断点是不能增加的,这样影响了调试的进度,其实之前做实验就注意到了,只是没有特别在意,但这个实验的算法较复杂,断点设得较多,这让我想到使用JAVA,也许使用java开发会更容易,调试的问题也可以解决,主要是使用现在对于C++的熟练程度远不如Java,如果能充分使用类和对象的特点,各种算法的实现将更加有条理,更易读易修改。

中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)

中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)

中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)定义:中缀表达式:在通常的表达式中,⼆元运算符总是置于与之相关的两个运算对象之间,这种表⽰法也称为中缀表达式后缀表达式:⼜叫逆波兰表达式,不包含括号,放在两个运算对象的后⾯,所有的计算按运算符出现的顺序,严格从左向右进⾏(不再考虑运算符的优先规则,如:(2 + 1) * 3 ,即2 1 + 3 *⼀个字符串表达式s = “9 + ( 3 - 1 ) * 3 + 10 / 2”)求值的过程分为两步(⼀) 将中缀表达式s变为后缀表达式s_after = "9 3 1 - 3 * + 10 2 / +",具体的规则如下:⾸先维护两个空栈,(stack_exp)存放逆波兰表达式,(stack_ops)暂存操作符,运算结束后stack_ops必为空循环遍历字符串(将表达式分为四种元素 1、数值; 2、操作符; 3、左括号; 4、右括号),具体情况如下1、遇到数值,将该值⼊栈stack_exp2、遇到左括号,将左括号⼊栈stack_ops3、遇到右括号,将stack_ops中的操作符从栈顶依次出栈并⼊栈stack_exp,直到第⼀次遇到左括号终⽌操作(注意:该左括号出栈stack_ops但不⼊栈stack_exp)⾄此消除表达式中的⼀对括号4、遇到四则运算操作符号(+ - * /)4-1、如果stack_ops为空,操作符⼊栈stack_ops4-2、如果stack_ops不空,将stack_ops栈顶操作符与遍历到的操作符(op)⽐较:4-2-1:如果stack_ops栈顶操作符为左括或者op优先级⾼于栈顶操作符优先级, op⼊栈stack_ops,当前遍历结束4-2-2:如果op优先级⼩于或者等于stack_ops栈顶操作符, stack_ops栈顶操作符出栈并⼊栈stack_exp,重复4-1、 4-2直到op⼊栈stack_ops5、字符串遍历结束后如果stack_ops栈不为空,则依次将操作符出栈并⼊栈stack_exppython代码实现如下:ops_rule = {'+': 1,'-': 1,'*': 2,'/': 2}def middle_to_after(s):expression = []ops = []ss = s.split('')for item in ss:if item in ['+', '-', '*', '/']:while len(ops) >= 0:if len(ops) == 0:ops.append(item)breakop = ops.pop()if op == '('or ops_rule[item] > ops_rule[op]:ops.append(op)ops.append(item)breakelse:expression.append(op)elif item == '(':ops.append(item)elif item == ')':while len(ops) > 0:op = ops.pop()if op == '(':breakelse:expression.append(op)else:expression.append(item)while len(ops) > 0:expression.append(ops.pop())return expression(⼆) 将后缀表达式s_after = "9 3 1 - 3 * + 10 2 / +" 求值,具体的规则如下:初始化⼀个空栈stack_value,⽤于存放数值循环s_after1、如果遇到数字,⼊栈stack_value;2、如果遇到运算符,从stack_value中依次出栈两个数(先出栈的在右,后出栈的在左)连同遍历到的运算符组成⼆⽬运算,求值后将结果压栈stack_value3、继续遍历下⼀个元素,直到结束遍历完后stack_value中的结果便是表达式的值python代码实现如下:def expression_to_value(expression):stack_value = []for item in expression:if item in ['+', '-', '*', '/']:n2 = stack_value.pop()n1 = stack_value.pop()result = cal(n1, n2, item)stack_value.append(result)else:stack_value.append(int(item))return stack_value[0]def cal(n1, n2, op):if op == '+':return n1 + n2if op == '-':return n1 - n2if op == '*':return n1 * n2if op == '/':return n1 / n2if __name__ == '__main__':expression = middle_to_after('9 + ( 3 * ( 4 - 2 ) ) * 3 + 10 / 2')value = expression_to_value(expression)print value。

利用栈来实现算术表达式求值的算法

利用栈来实现算术表达式求值的算法

利用栈来实现算术表达式求值的算法利用栈来实现算术表达式求值的算法算术表达式是指按照一定规则组成的运算式,包含数字、运算符和括号。

在计算机中,求解算术表达式是一项基本的数学运算任务。

根据算术表达式的性质,我们可以考虑利用栈这一数据结构来实现求值算法。

一、算法思路首先,我们需要明确一个重要概念——逆波兰表达式(ReversePolish notation)。

逆波兰表达式是一种没有括号的算术表达式,其运算规则是先计算后面的数字和运算符,再计算前面的数字和运算符。

例如,对于算术表达式“3+4*5-6”,其对应的逆波兰表达式为“3 45 * +6 -”。

那么,我们可以利用栈来实现将中缀表达式转化为逆波兰表达式的过程,具体步骤如下:1. 创建两个栈——操作数栈和操作符栈。

2. 从左到右扫描中缀表达式的每一个数字和运算符,遇到数字则压入操作数栈中,遇到运算符则进行如下操作:(1)如果操作符栈为空或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符压入操作符栈中。

(2)如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入操作数栈中,重复此过程直到遇到优先级较低的运算符或操作符栈为空为止,然后将当前运算符压入操作符栈中。

3. 扫描完中缀表达式后,若操作符栈不为空,则将其中所有运算符弹出并加入操作数栈中。

4. 最终,操作数栈中存放的就是逆波兰表达式,我们可以按照逆波兰表达式的计算规则来计算其结果。

二、算法优点利用栈来实现算术表达式求值的算法具有以下优点:1. 代码简洁易懂,易于实现和维护。

2. 由于将中缀表达式转化为逆波兰表达式后,可以减少运算符的优先级关系而消除括号,从而减少求值的复杂度,提高程序的执行效率。

三、代码实现下面是利用栈来实现算术表达式求值的算法的Python代码实现:```pythonclass Stack:def __init__(self):self.items = []def push(self, item):self.items.append(item)def pop(self):return self.items.pop()def peek(self):return self.items[-1]def is_empty(self):return len(self.items) == 0def size(self):return len(self.items)def calculate(op_num1, op_num2, operator):if operator == "+":return op_num1 + op_num2elif operator == "-":return op_num1 - op_num2elif operator == "*":return op_num1 * op_num2elif operator == "/":return op_num1 / op_num2def infix_to_postfix(infix_expr):opstack = Stack()postfix_expr = []prec = {"+": 1, "-": 1, "*": 2, "/": 2, "(": 0} token_list = infix_expr.split()for token in token_list:if token.isdigit():postfix_expr.append(token)elif token == '(':opstack.push(token)elif token == ')':top_token = opstack.pop()while top_token != '(':postfix_expr.append(top_token)top_token = opstack.pop()else:while (not opstack.is_empty()) and(prec[opstack.peek()] >= prec[token]):postfix_expr.append(opstack.pop())opstack.push(token)while not opstack.is_empty():postfix_expr.append(opstack.pop())return " ".join(postfix_expr)def postfix_eval(postfix_expr):opstack = Stack()token_list = postfix_expr.split()for token in token_list:if token.isdigit():opstack.push(int(token))else:op_num2 = opstack.pop()op_num1 = opstack.pop()result = calculate(op_num1, op_num2, token) opstack.push(result)return opstack.pop()infix_expr = "3 + 4 * 5 - 6"postfix_expr = infix_to_postfix(infix_expr)print(postfix_expr)print(postfix_eval(postfix_expr))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

中缀表达式转逆波兰式并求值// 标题: 栈的应用——中缀表达式转逆波兰式 // 时间: 2015年4月14日// 所有者: Vae#include<stdio.h>#include<malloc.h>#include<stdlib.h>#include<windows.h>#include<Winuser.h>#define STACK_INIT_SIZE 100 #define STACKCREATE 10 #define OK 1 #define ERROR 0typedef struct double_stack {int *num;int *index;}DOUBLESTACK;typedef struct SqStack{DOUBLESTACK top; DOUBLESTACK base;int stacksize;}SqStack;// 函数名: InitStack // 形参类型: SqStack * // 函数功能构造一个栈void InitStack(SqStack *S) {S->base.index = (int *)malloc(sizeof(int)*STACK_INIT_SIZE);S->base.num = (int *)malloc(sizeof(int)*STACK_INIT_SIZE);if (!(S->base.num && S->base.index)){printf("构造栈失败!\n");exit(-1);}S->top.num = S->base.num;S->top.index = S->base.index;S->stacksize = STACK_INIT_SIZE;return ;}// 函数名: Push// 形参类型: SqStack *, int, int // 函数功能插入e为新的栈顶元素int Push(SqStack *S, int m, int n){if ((S->top.num - S->base.num) >= S->stacksize){S->base.index = (int *)realloc(S->base.index,sizeof(int)*(STACK_INIT_SIZE+STACKCREATE));S->base.num = (int *)realloc(S->base.num,sizeof(int)*(STACK_INIT_SIZE+STACKCREATE));if (!(S->base.num || S->base.index))return ERROR; }*S->top.index++ = n;*S->top.num++ = m;S->stacksize = S->stacksize + STACKCREATE;return OK;}// 函数名: Pop// 形参类型: SqStack *, int *, int * // 函数功能出栈并用e返回int Pop(SqStack *S, int *a, int *b) {if (S->base.num == S->top.num) return ERROR;*a = * --S->top.num;*b = * --S->top.index;return OK;}// 函数名: GetTop// 形参类型: SqStack *, int * // 函数功能用e返回栈顶元素int GetTop(SqStack S, int *e) {if (S.top.num == S.base.num)return ERROR;*e = *(S.top.num - 1);return OK;}// 函数名: EmptyStack // 形参类型: SqStack// 函数功能判断是否为空栈int EmptyStack(SqStack S) {if (S.base.num == S.top.num)return OK;elsereturn ERROR;}// 函数名: Precede// 形参类型: char, char// 函数功能判断运算符的优先关系char Precede(char t1, char t2) { char f;switch(t2){case '+':case '-':if(t1=='(' || t1=='\n')f = '<'; //t1<t2elsef = '>'; // t1>t2break;case '*':case '/':if (t1=='*' || t1=='/' || t1==')') f = '>';elsef = '<';break;case '(':if (t1 == ')'){printf("括号不匹配\n");exit(-1);}elsef = '<';break;case ')':switch(t1){case '(': f = '=';break;case '\n': printf("缺乏左括号\n"); exit(-1); default:f = '>';}break;case '\n':switch(t1){case '\n':f = '='; break; case '(':printf("缺乏右括号\n");exit(-1);default:f = '>'; }}return f;}// 函数名: In// 形参类型: char // 函数功能判断是否为7种运算符之一int In(char c){switch(c){case '+' :case '-' :case '*' :case '/' :case '(' :case ')' :case '\n': return OK;default : return ERROR;}}// 函数名: ShowStack // 形参类型: SqStack // 函数功能输出表达式的逆波兰式void ShowStack(SqStack S) {int a, b;SqStack q;InitStack(&q);while (!EmptyStack(S)){Pop(&S,&a,&b);Push(&q,a,b);}printf("原表达式转换成逆波兰式为\n"); while (!EmptyStack(q)){Pop(&q,&a,&b);if (b == 0)printf("%c ", a);elseprintf("%d ", a);}printf("\n");}// 函数名: Opertae // 形参类型: int, char, int // 函数功能做四则运算 a theta bint Operator_(int a, char theta, int b){switch(theta){case '+':return a+b; case '-':return a-b;case '*':return a*b;}return a/b;}// 函数名: GetValue // 形参类型: SqStack// 函数功能求的表达式的值void GetValue(SqStack S) {int a, b;SqStack q,p;int value;int m, n;int c, d;char z;InitStack(&q);InitStack(&p);while (!EmptyStack(S)) {Pop(&S,&a,&b);Push(&q,a,b); }while (!EmptyStack(q)) {Pop(&q,&a,&b);if (b == 0){Pop(&p,&m,&c);Pop(&p,&n,&d);z = toascii(a);value = Operator_(n,z,m); Push(&p,value,1);}elsePush(&p,a,1);}Pop(&p,&a,&b);printf("表达式的值为:%d\n", a);return ;}// 函数名: EvaLuateExpression // 形参类型: void// 函数功能得到逆置的后缀表达式void EvaluateExpression(){SqStack OPRT, OPND; // 设OPTR 和 OPND 分别为运算符栈和运算数栈d, x; charint y;char c;char z[11];int i;InitStack(&OPRT);InitStack(&OPND);Push(&OPRT,'\n',0); //将换行符压入运算符栈的栈底c = getchar();GetTop(OPRT,&x);//将运算符栈OPTR的栈顶元素赋值给xwhile (c!='\n' || x!='\n'){if (In(c)) //c是7种运算符之一{switch(Precede(x,c)) //判断x和c的优先级 {case '<':Push(&OPRT,c,0);c = getchar();break; case '=':Pop(&OPRT,&x,&y);c=getchar();break;case '>':Pop(&OPRT,&x,&y);Push(&OPND,x,y);}}else if (c>='0' && c<='9'){i = 0;while (c>='0' && c<= '9') {z[i++] = c;c = getchar(); }z[i] = '\0';d = atoi(z); //将z中保存的数值型字符窜转化为整型存于d中 Push(&OPND,d,1);}else{printf("出现非法字符!\n");exit(-1);}GetTop(OPRT,&x);}ShowStack(OPND);GetValue(OPND);}int main(void){printf("请输入表达式,负数用(0-正数)表示:"); EvaluateExpression();return 0;}。

相关文档
最新文档