逆波兰表达式求解
逆波兰表达式
逆波兰表达式逆波兰表达式表达式⼀般由操作数(Operand)、运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间,这称为中缀表达式(Infix Expression),如A+B。
波兰数学家Jan Lukasiewicz提出了另⼀种数学表⽰法,它有两种表⽰形式:把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+;其中,逆波兰表达式在编译技术中有着普遍的应⽤。
算法:⼀、将中缀表达式转换成后缀表达式算法:1、从左⾄右扫描⼀中缀表达式。
2、若读取的是操作数,则判断该操作数的类型,并将该操作数存⼊操作数堆栈3、若读取的是运算符(1) 该运算符为左括号"(",则直接存⼊运算符堆栈。
(2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为⽌。
(3) 该运算符为⾮括号运算符:(a) 若运算符堆栈栈顶的运算符为括号,则直接存⼊运算符堆栈。
(b) 若⽐运算符堆栈栈顶的运算符优先级⾼或相等,则直接存⼊运算符堆栈。
(c) 若⽐运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压⼊运算符堆栈。
4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
⼆、逆波兰表达式求值算法:1、循环扫描语法单元的项⽬。
2、如果扫描的项⽬是操作数,则将其压⼊操作数堆栈,并扫描下⼀个项⽬。
3、如果扫描的项⽬是⼀个⼆元运算符,则对栈的顶上两个操作数执⾏该运算。
4、如果扫描的项⽬是⼀个⼀元运算符,则对栈的最顶上操作数执⾏该运算。
5、将运算结果重新压⼊堆栈。
逆波兰式(后缀表达式)的计算
逆波兰式(后缀表达式)的计算输⼊:后缀表达式(可带浮点数)输出:double型的计算结果代码:#include <stdio.h>#include <stdlib.h>#include <malloc.h>#define ElemType double#define Stack_Init_Size 100#define Increase_Size 10#define MaxBuffer 10typedef struct sqStack{ElemType *top;ElemType *base;int initSize;}sqStack;typedef struct sqStack *LinkStack;//初始化void InitStack( sqStack *s ){s->base = (LinkStack)malloc(Stack_Init_Size * sizeof(ElemType));if(!s->base){printf("存储空间分配失败······\n");return;}s->top = s->base;s->initSize = Stack_Init_Size;}//进栈void Push(sqStack *s,ElemType e){if(s->top - s->base >= s->initSize - 1){s->base = (LinkStack)realloc(s->base,(s->initSize + Increase_Size) * sizeof(ElemType));//第⼀个s->base是增加后的存储空间块的地址,第⼆个是增加空间之前的存储空间块地址,后⾯是增加过的存储空间块的⼤⼩ if(!s->base){printf("增加存储空间失败······\n");return;}s->initSize = Increase_Size + Stack_Init_Size;}*(s->top) = e;(s->top)++;}//出栈void Pop(sqStack *s,ElemType *e){if(s->top == s->base){printf("栈已空,⽆法进⾏出栈操作······\n");return;}s->top--;*e = *s->top;}//求栈的长度int StackLen(sqStack s){return (s.top - s.base);}//逆波兰计算器:输⼊逆波兰式(后缀表达式)输出结果int main(){int i = 0,j,len;double m,n,t;char c;struct sqStack s;char str[MaxBuffer];InitStack(&s);printf("请输⼊您要计算的后缀表达式,按Enter键结束(两个不同的字符之间⽤空格隔开):\n");scanf("%c",&c);while(c != '\n'){while( (c >= '0'&&c <= '9') || c == '.'){str[i] = c;i++;// str[i] = '\0';if(i >= 10){printf("\n输⼊的数字过⼤导致出错\n"); return -1;}scanf("%c",&c);if( c == ' '){t = atof(str);// printf("\nt is %f\n",t);Push(&s,t);i = 0;for(j = 0;j < MaxBuffer;j++){str[j] = '\0';}break;}}switch( c ){case '+':Pop(&s,&m);Pop(&s,&n);Push(&s,n+m);break;case '-':Pop(&s,&m);Pop(&s,&n);Push(&s,n-m);break;case '*':Pop(&s,&m);Pop(&s,&n);Push(&s,n*m);break;case '/':Pop(&s,&m);Pop(&s,&n);if( m == 0){printf("\n除数为0,出错\n");return -1;}else{Push(&s,n/m);break;}}scanf("%c",&c);}Pop(&s,&t);printf("\n最终的计算结果为:%f \n",t);return 0;}。
写出下列逆波兰式的中缀表达式
写出下列逆波兰式的中缀表达式
逆波兰式:
A B + C D E - × /
中缀表达式:
(A + B) / (C - D × E)
今天,我们要来聊聊数学运算中有关逆波兰式的内容。
一般而言,逆波兰式(Reverse Polish Notation,RPN)也叫波兰式,是一种由波兰数学家所发明的数学表达式求值方法。
它将操作符置于操作数之后,然后形成一个序列。
它可以帮助我们简化一些数学表达式的计算方式,从而更加高效率地完成计算工作。
比如,上面提到的逆波兰式: A B + C D E - × /,可以重新排列为中缀表达式: (A + B) / (C - D × E),它的意思就是 A 与 B 相加,然后除以 C 减去 D 乘以 E 的结果。
那么,为什么我们要使用逆波兰式呢?最主要的一个原因是,它比起使用括号的中缀表达式更加简洁易读。
另外,它也具有计算时间上的优势。
这是由于它不需要进行括号匹配和优先级解析,因此可以更快地完成计算。
在程序开发中,使用逆波兰式也十分常见。
它可以帮助我们对一些复杂的数学表达式更加高效地进行计算。
尤其是当计算的数据量很大时,使用逆波兰式可以大大提高计算速度。
总而言之,逆波兰式可以让我们更加准确地表达数学式,同时具备更快的计算效率。
逆波兰表达式求解
逆波兰表达式求值问题描述:后缀表达式———将运算符放在两操作数的后面。
后缀表达式也称逆波兰表达式,因其使表达式求值变得轻松,所以被普遍使用。
读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。
基本要求(1)从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操作数等。
(2)用堆栈来实现需求分析:1、输入形式:将后缀表达式存于文本文件中,其中后缀表达式中两相邻操作数之间利用空格隔开,程序从该文本文件中读出表达式。
2、输出形式:如果该后缀表达式正确,则计算结果,计算结果保留小数点后面两位有效数字,同时将结果输出到该文件中原表达式的后面,结果与表达式之间用“=”后相连;如果不正确,请在输出表达式错误提示到该文件原表达的后面,它们之间用“---”相连。
表达式中操作数为一实数,该实数精到小数点后面两位有效数字。
3、功能描述:a、判断所输入的后缀表达式是否合法b、如果合法则求解后缀表达式的值(精确到小数点后两位数字)4、样例输入输出(数据加强版)输入:42 3 * 1 –#2 3 * 0 / #2 3 * - #2 3 1 - #输出:5.00Error!Error!Error!抽象数据类型(ADT):后缀表达式求值可以用堆栈来实现!抽象数据结构类型描述:Typedef struct{Char st[MaxSize]; //存放栈中元素Int top; //栈顶指针}Stack;顺序栈的基本操作:V oid InitStack(Stack &s) function:置空栈Int push(Stack &s,char x) function:将元素x压入栈中Int gettop(Stack &s,char x) function:将栈顶元素的值赋给x,栈指针不变V oid pop(Stack &s,char x) function:将栈顶元素赋给x,栈指针递减Bool stackempty(Stack &s) function:判断栈是否为空栈概要设计:这就是一个基于数据结构栈的基本简单的操作,每次读入一个字符,当读入的为整数的时候,将其进栈,读入的为运算符的时候进行相应的运算,遇到'#'的时候,终止操作即可。
逆波兰表达式解决四则运算
逆波兰表达式解决四则运算逆波兰表达式又叫做后缀表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式,解决了四则运算中括号改变运算符优先级的问题。
四则运算的表达式一般都是中缀表达式如 1+2*(3-4)+5,即操作符在两个操作数之间。
四则运算需要两个步骤,一是把中缀表达式转为后缀表达式,二是由后缀表达生成结果中缀表达式转为后缀表达式算法描述:(1)首先有个包含中缀表达式元素列表sourceList,然后创建一个符号列表destList保存最终后缀表达式,创建一个操作符堆栈opStack(2)从sourceList取出一个元素A(3a)如是数字则加入到destList中(3b)如果元素A是运算符,将操作符A与操作符堆栈opStack栈顶的运算符的优先关系相比较。
如果,优先关系高于opStack栈顶的运算符,则将该运算符压入操作符堆栈opStack。
倘若不是(低于或等于)的话,则将运算符栈opStack栈顶的运算符从栈中弹出保存到destList,重复此步骤,直到作符A压入操作符堆栈opStack。
(3c)若元素A是左括号"(",则压入操作符堆栈opStack(3d)若元素B是右括号")",则操作符堆栈opStack弹出操作符并加入到destList中,直到弹出左括号"("。
(5)从步骤2重复上述操作,所有元素处理完毕后将操作符堆栈opStack弹出操作符并加入到destList中,这样中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
示例:中缀表达式如 1+2*(3-4)+5,构造元素列表1,+,2,*,(,3,-,4,),5,构造一个空最终后缀表达式destList,一个操作符堆栈opStack1、取出“1”,destList【1】,opStack【】2、取出“+”,destList【1】,opStack【+】3、取出“2”,destList【1,2】,opStack【+】4、取出“*”,destList【1,2】,opStack【+,*】5、取出“(”,destList【1,2】,opStack【+,*,(】6、取出“3”,destList【1,2,3】,opStack【+,*,(】7、取出“-”,destList【1,2,3】,opStack【+,*,(,-】8、取出“4”,destList【1,2,3,4】,opStack【+,*,(,-】9、取出“)”,destList【1,2,3,4,-】,opStack【+,*】 //操作符堆栈opStack 弹出操作符并加入到destList中,直到弹出左括号"("10、取出“+”,destList【1,2,3,4,-,*,+】,opStack【+】 //加号优先级不大于【+,*】11、取出“5”,destList【1,2,3,4,-,*,+,5】,opStack【+】12、处理完毕,destList【1,2,3,4,-,*,+,5,+】,opStack【】后缀表达式到计算结果算法描述:遍历储存后缀表达式的列表,将元素依次进栈,当遇到操作符时,连续出栈两个元素,进行运算,再将结果进栈,最后栈内留下的元素就是计算结果示例:后缀表达式destList【1,2,3,4,-,*,+,5,+】,结果堆栈resultStatck【】格式输入-->:结果[1,2,3,4]-->:resultStatck【1,2,3,4】[-]-->:resultStatck【1,2,3-4】[ * ]-->:resultStatck【1,2*(3-4)】[+]-->:resultStatck【1+2*(3-4)】[5]-->:resultStatck【1+2*(3-4),5】[+]-->:resultStatck【1+2*(3-4)+5】。
实验2 逆波兰表达式求值
1、以字符串方式输入一逆波兰表达式;
2、对逆波兰表达式进行分解、运算,并输出运算结果。
实现提示:
采用栈存储扫描到的运算量或运算的中间结果。
运行环境:
Microsoft visual C++6.0控制台
问题分析:
逆波兰表达式求值可以利用堆栈的数据结构思想进行实现。数组结构即可完成堆栈数据的相同的功能。具体是根据你逆波兰表达式中的操作符提取操作数(相当于堆栈中的pop操作),进行运算之后把结果存回数组(相当于push操作),通过不断的出栈、入栈操作最终栈中保存的数据则为逆波兰表达式的结果。
如果对应操作符不能提取到所需的操作数,即i-1<0,表明输入的逆波兰表达式是错误的表达式,输出提示,并重新输入。此过程通过增加一个flag标识,当flag=1表示有错,flag=0表示表达式正确。
本实验将逆波兰表达式求值定义为一个函数,在主函数中调用该函数,并把结果保存在其参数中,然后打印输出结果。
jj++;
n2++;
switch(*p)//利用该操作符进行对应的操作,并用结果的替代数组a中的倒数第//二个值。
{
case '+':
if(i-1<0)
{flag=1;break;}
answer=a[i]+a[i-1];a[i-1]=answer;i--;n1--; flag=0;break;
case '-':
实验2逆波兰表达式求值
By 20110149杨付乾11级茅信1班
问题描述:
逆波兰表达式也称后缀式,是一种运算量在前,运算符在后的表示方式;运算主要特点是不必考虑运算符的优先顺序。
前缀、中缀、后缀表达式(逆波兰表达式)
前缀、中缀、后缀表达式(逆波兰表达式)前缀、中缀、后缀表达式(逆波兰表达式)介绍前缀表达式、中缀表达式、后缀表达式都是四则运算的表达⽅式,⽤以四则运算表达式求值,即数学表达式的求职中缀表达式简介中缀表达式就是常见的运算表达式,如(3+4)×5-6前缀表达式简介前缀表达式⼜称波兰式,前缀表达式的运算符位于操作数之前⽐如:- × + 3 4 5 6前缀表达式的计算机求值从右⾄左扫描表达式,遇到数字时,将数字压⼊堆栈,遇到运算符时,弹出栈顶的两个数,⽤运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果⼊栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果例如:- × + 3 4 5 61. 从右⾄左扫描,将6、5、4、3压⼊堆栈2. 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做⽐较),计算出3+4的值,得7,再将7⼊栈3. 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35⼊栈4. 最后是-运算符,计算出35-6的值,即29,由此得出最终结果将中缀表达式转换为前缀表达式转换步骤如下:1. 初始化两个栈:运算符栈s1,储存中间结果的栈s22. 从右⾄左扫描中缀表达式3. 遇到操作数时,将其压⼊s24. 遇到运算符时,⽐较其与s1栈顶运算符的优先级1. 如果s1为空,或栈顶运算符为右括号“)”,则直接将此运算符⼊栈2. 否则,若优先级⽐栈顶运算符的较⾼或相等,也将运算符压⼊s13. 否则,将s1栈顶的运算符弹出并压⼊到s2中,再次转到(4-1)与s1中新的栈顶运算符相⽐较5. 遇到括号时1. 如果是右括号“)”,则直接压⼊s12. 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压⼊S2,直到遇到右括号为⽌,此时将这⼀对括号丢弃6. 重复步骤2⾄5,直到表达式的最左边7. 将s1中剩余的运算符依次弹出并压⼊s28. 依次弹出s2中的元素并输出,结果即为中缀表达式对应的前缀表达式例如:1+((2+3)×4)-5具体过程,如下表扫描到的元素|S2(栈底->栈顶)|S1 (栈底->栈顶)|说明---|---|---|---|---5|5|空|数字,直接⼊栈-|5|-|s1为空,运算符直接⼊栈)|5|-)|右括号直接⼊栈4|5 4|-)|数字直接⼊栈x|5 4|-)x|s1栈顶是右括号,直接⼊栈)|5 4|-)x)|右括号直接⼊栈3|5 4 3|-)x)|数字+|5 4 3|-)x)+|s1栈顶是右括号,直接⼊栈2|5 4 3 2|-)x)+|数字(|5 4 3 2 +|-)x|左括号,弹出运算符直⾄遇到右括号(|5 4 3 2 + x|-|同上+|5 4 3 2 + x|-+|优先级与-相同,⼊栈1|5 4 3 2 + x 1|-+|数字到达最左端|5 4 3 2 + x 1 + -|空|s1剩余运算符结果是:- + 1 × + 2 3 4 5后缀表达式简介后缀表达式⼜称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后⽐如:3 4 + 5 × 6 -后缀表达式计算机求值与前缀表达式类似,只是顺序是从左⾄右:从左⾄右扫描表达式,遇到数字时,将数字压⼊堆栈,遇到运算符时,弹出栈顶的两个数,⽤运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果⼊栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果例如后缀表达式“3 4 + 5 × 6 -”:1. 从左⾄右扫描,将3和4压⼊堆栈;2. 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做⽐较),计算出3+4的值,得7,再将7⼊栈;3. 将5⼊栈;4. 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35⼊栈;5. 将6⼊栈;6. 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
【算法】表达式求值--逆波兰算法介绍
【算法】表达式求值--逆波兰算法介绍假定给定⼀个只包含加、减、乘、除,和括号的算术表达式,你怎么编写程序计算出其结果?问题是:在表达式中,括号,以及括号的多层嵌套的使⽤,运算符的优先级不同等因素,使得⼀个算术表达式在计算时,运算顺序往往因表达式的内容⽽定,不具规律性。
这样很难编写出统⼀的计算指令。
使⽤逆波兰算法可以轻松解决这个问题。
他的核⼼思想是将普通的中缀表达式转换为后缀表达式。
什么是中缀表达式?例如a+b,运算符在两个操作数的中间。
这是我们从⼩学开始学习数学就⼀直使⽤的表达式形式。
什么是后缀表达式?例如a b + ,运算符在两个操作数的后⾯。
后缀表达式虽然看起来奇怪,不利于⼈阅读,但利于计算机处理。
转换为后缀表达式的好处是:1、去除原来表达式中的括号,因为括号只指⽰运算顺序,不是实际参与计算的元素。
2、使得运算顺序有规律可寻,计算机能编写出代码完成计算。
⼀个表达式有如下及部分元素组成操作数:可以是任何数值:1,89 , 3.14159 ...运算符:分为单⽬运算符如 sin , cos ,双⽬运算符如加、减、乘、除。
运算符还会分为左结合性和右结合性。
同级的左结合性的运算符从左往右依次计算。
同级的右结合性的运算符从右往左依次计算。
如: 7-6+1 等价于 (7-6) + 1 ,因为普通加减运算符是左结合性的。
如:C语⾔中的组合赋值语句: a = b = 1 等价于 a = (b=1) ,因为赋值运算符在C中是右结合性的。
对于单⽬运算符,还分为前缀运算符和后缀运算符,如 sin(x) 是前缀运算符,⽽阶乘运算符: n ! 就是后缀运算符。
分界符:⼀般是圆括号 ( ) ,⽤于指⽰运算的先后顺序。
在本⽂中,只会考虑算术表达式有加、减、乘、除运算符,左右圆括号 ( , ) ,以及合法的数字简单的情况。
对于更加复杂的运算符,只要对这个算法轻微修改,就可以⽀持。
逆波兰算法的核⼼步骤就2个:1、将中缀表达式转换为后缀表达式,例如输⼊的原始表达式是 3*(5+7),转换得到 3 5 7 + *2、根据后缀表达式,按照特定的计算规则得到最终计算结果下⾯详细介绍这个2步的操作。
逆波兰式
定义逆波兰式也叫后缀表达式(将运算符写在操作数之后)如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+(a+b)*c-(a+b)/e的后缀表达式为:(a+b)*c-(a+b)/e→((a+b)*c)((a+b)/e)-→((a+b)c*)((a+b)e/)-→(ab+c*)(ab+e/)-→ab+c*ab+e/-算法实现将一个普通的中序表达式转换为逆波兰表达式的一般算法是:1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
逆波兰式的作用对于实现逆波兰式算法,难度并不大,但为什么要将看似简单的中序表达式转换为复杂的逆波兰式?原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中序表达式是非常复杂的结构。
相对的,逆波兰式在计算机看来却是比较简单易懂的结构。
因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。
下面以(a+b)*c为例子进行说明:(a+b)*c的逆波兰式为ab+c*,假设计算机把ab+c*按从左到右的顺序压入栈中,并且按照遇到运算符就把栈顶两个元素出栈,执行运算,得到的结果再入栈的原则来进行处理,那么ab+c*的执行结果如下:1)a入栈(0位置)2)b入栈(1位置)3)遇到运算符“+”,将a和b出栈,执行a+b的操作,得到结果d=a+b,再将d 入栈(0位置)4)c入栈(1位置)5)遇到运算符“*”,将d和c出栈,执行d*c的操作,得到结果e,再将e入栈(0位置)经过以上运算,计算机就可以得到(a+b)*c的运算结果e了。
逆波兰表达式求值算法
逆波兰表达式求值算法逆波兰表示法(Reverse Polish Notation,RPN)是一种数学表达式表示法,它不需要括号来明确操作符的优先级。
在这种表示法中,操作符跟在操作数后面。
下面是一个逆波兰表达式的求值算法:1. 初始化一个堆栈用于存储数字。
2. 从左到右读取表达式中的每个字符。
3. 如果字符是一个数字,则将其转换为对应的数值,并压入堆栈。
4. 如果字符是一个操作符(例如加号、减号、乘号或除号),则从堆栈中弹出两个操作数,进行相应的运算,并将结果压回堆栈。
5. 重复步骤2-4,直到表达式结束。
6. 最后,堆栈中剩下的唯一元素就是表达式的计算结果。
下面是一个使用 Python 实现逆波兰表达式求值算法的示例代码:```pythondef eval_rpn(expression):stack = []operators = set('+-/')for token in ():if token not in operators:(int(token))else:y = ()x = ()if token == '+':(x + y)elif token == '-':(x - y)elif token == '':(x y)else: token == '/'(x // y) 使用整数除法,因为逆波兰表达式通常用于整数运算 return stack[0]```使用示例:```pythonexpression = "2 3 + 4 " 计算 (2 + 3) 4 的结果,即 20 result = eval_rpn(expression)print(result) 输出:20```。
逆波兰公式
逆波兰公式逆波兰表达式是一种数学表达式,它采用后缀形式,即操作符在操作数之后出现。
逆波兰表达式通常使用栈来求解,下面我们将介绍逆波兰表达式的优点、求解方法和一些应用场景。
一、逆波兰表达式的优点无需括号:逆波兰表达式可以避免使用括号来明确表达式的优先级和结合性,因为它们可以通过操作符的顺序来推断。
这使得逆波兰表达式更加简洁和易于阅读。
易于实现:逆波兰表达式可以使用栈来求解,这使得它们的计算过程相对简单,并且可以在许多编程语言中实现。
易于扩展:逆波兰表达式的操作符和操作数可以根据需要进行添加或删除,这使得它们非常灵活,并且可以适用于各种数学运算。
二、逆波兰表达式的求解方法逆波兰表达式的求解方法通常使用栈来实现。
具体步骤如下:读取下一个字符,如果是数字则将其压入栈中。
如果读到的字符是操作符,则弹出栈顶的两个元素,进行相应的运算,并将结果压入栈中。
重复上述步骤,直到表达式结束。
栈中的唯一元素即为表达式的求解结果。
例如,考虑以下逆波兰表达式:3 +4 \* 2 / (1 - 5)我们可以按照以下步骤求解:读取字符“3”,将其压入栈中。
读取字符“+”,这是一元操作符,将其压入栈中。
读取字符“4”,将其压入栈中。
读取字符“*”,这是一元操作符,将其压入栈中。
读取字符“2”,将其压入栈中。
读取字符“/”,这是一元操作符,将其压入栈中。
读取字符“(”,这是一个左括号,将其压入栈中。
读取字符“1”,将其压入栈中。
读取字符“-”,这是一元操作符,将其压入栈中。
读取字符“5”,将其压入栈中。
读取字符“)”,这是一个右括号,弹出栈顶的三个元素进行运算,并将结果压入栈中。
读取字符“+”,这是一元操作符,将其压入栈中。
表达式结束,弹出栈顶的元素即为求解结果。
三、逆波兰表达式的应用场景逆波兰表达式在计算机科学中有广泛的应用场景,以下是一些常见的应用场景:在编译器设计中:编译器通常需要对表达式进行解析和计算,逆波兰表达式可以作为一种简单的表示方式,使得编译器更容易处理表达式。
noi 2.2波兰表达式
noi 2.2波兰表达式波兰表达式,也称逆波兰表达式(Reverse Polish Notation,简称RPN)是一种数学表达式的形式,其中运算符位于与之相关的操作数之后。
波兰表达式的优势在于没有括号,并且对于计算机来说更容易解析和计算。
下面将详细介绍波兰表达式的原理和应用。
波兰表达式的特点是将运算符放在操作数的后面。
例如,常见的中缀表达式“3 + 4”在波兰表达式中表示为“3 4 +”。
更复杂的例子,中缀表达式“(5 - 3) * 4”在波兰表达式中表示为“5 3 - 4 *”。
波兰表达式的计算方法相对简单,只需遵循以下步骤:1. 从左到右扫描表达式,直到遇到运算符或者操作数。
2. 如果遇到操作数,将其推入栈中。
3. 如果遇到运算符,从栈顶弹出两个操作数,并进行运算。
将结果推入栈中。
4. 重复步骤2和3,直到表达式被扫描完毕。
5. 最后,栈中的唯一元素即为计算结果。
波兰表达式的一个重要应用是在计算机科学中的计算器和编译器中。
因为波兰表达式不需要括号,所以对于计算机来说更容易解析和计算,可以减少解析表达式的复杂性。
此外,波兰表达式的计算过程也可以通过栈数据结构来实现,使得计算过程更加高效。
波兰表达式还可以用于计算机领域的其他方面,例如表达式解析、逻辑运算等。
在逻辑运算中,波兰表达式可以更直观地表示多个条件的组合,并对其进行计算。
与传统的中缀表达式相比,波兰表达式不需要考虑运算符的优先级和括号的匹配,使得计算过程更加简单和直观。
总结一下,波兰表达式是一种将运算符放在操作数后面的数学表达式形式。
波兰表达式的优点在于没有括号,并且对于计算机来说更易于解析和计算。
波兰表达式在计算器、编译器和其他计算机领域中有广泛的应用。
通过栈数据结构实现波兰表达式的计算过程也使得计算更加高效。
在逻辑运算中,波兰表达式可以更直观地表示多个条件的组合,并对其进行计算。
逆波兰式算法
逆波兰式算法逆波兰式算法是一种数学上的算法,用于求解算术表达式。
它也被称为后缀表达式,因为算术表达式以反序方式写出,而不是一般的以中缀方式书写。
它以后缀形式出现,写作方式是:操作数在操作符之前。
它最早是由波兰数学家Lukasiewicz在1920年发明的。
逆波兰式的优点在于可以用堆栈的形式来解析。
堆栈是一种存储数据的结构,它遵循先进后出原则。
这也意味着,需要将算术表达式的操作数压入堆栈中,然后按照一定的顺序弹出并且被操作符处理,最终得到算术表达式的结果。
它不需要使用括号,也不需要花费大量时间在去识别表达式中优先级相关的问题上,因此运算效率会非常高。
同时,逆波兰式也有一些缺点。
首先,它比较难以理解,对于非专业人士来说,它可能更难掌握。
其次,它容易出错,因为它通常需要从右向左阅读,如果出现单词拼写错误,结果的计算就会出现偏差。
虽然存在上述的缺点,但是逆波兰式算法在计算机领域中仍然是非常重要的一种工具。
它可以用于求解复杂的算术表达式,也可以用于生成编译器的代码,或者进行字符串的比较。
它的优点在于更简单、更快速和更精确,因此在计算机编程中依然被广泛使用。
除了数学计算之外,逆波兰式算法也可以用于表达式求值。
它可以用于求解表达式的结果,而且这种方式可以用来表达式的求值的计算过程。
它可以用于优化线性规划问题,也可以用于求解图论问题,以及其他机器学习和认知科学领域的问题。
在现代,由于计算机系统变得越来越快,逆波兰式算法也一次变得越来越流行。
工程师们也在不断地改进它,使它变得更快,更容易使用。
在未来,逆波兰式算法将继续展现其强大的性能,解决许多复杂的数学问题。
逆波兰式转换规则的推导过程
逆波兰式转换规则的推导过程逆波兰表示法(Reverse Polish Notation,RPN)是一种数学表达式的表示方法,其特点是运算符放在操作数之后。
例如,中缀表达式 "2 + 3" 在逆波兰表示法中写作 "2 3 +"。
逆波兰表示法的推导过程如下:1. 定义操作数和运算符:首先,我们需要定义操作数和运算符。
操作数可以是任何数字,而运算符可以是加法、减法、乘法或除法。
2. 构建逆波兰表示法的规则:如果操作符是加法或减法,则将其放在两个操作数的后面。
例如,"2 + 3" 转换为 "2 3 +"。
如果操作符是乘法或除法,则将其放在两个操作数的中间。
例如,"2 3" 转换为 "2 3 "。
对于括号,我们可以将其视为一个操作数,并按照上述规则处理。
例如,"2 + (3 - 1)" 可以转换为 "2 3 1 - +"。
3. 处理优先级问题:在逆波兰表示法中,我们不需要括号来表示优先级。
这是因为通过将运算符放在操作数之后,我们可以自然地解决优先级问题。
例如,"2 3 + 4" 在逆波兰表示法中是 "2 3 4 +",其中乘法和加法的优先级是明确的。
4. 处理负数和正数:在逆波兰表示法中,我们可以将负数和正数视为特殊的操作数。
例如,"2 - (-3)" 可以转换为 "2 -3 -"。
5. 验证逆波兰表示法的正确性:为了验证逆波兰表示法的正确性,我们可以使用堆栈数据结构。
从左到右读取表达式,如果遇到操作数,则将其压入堆栈;如果遇到运算符,则从堆栈中弹出相应的操作数进行计算,并将结果压回堆栈。
重复这个过程直到表达式结束。
如果最终堆栈中只剩下一个元素,则表达式是有效的;否则,表达式无效。
实验三 逆波兰表达式的产生及计算
实验三逆波兰表达式的产生及计算一、实验目的非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
二、实验内容将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
三、逆波兰表达式的产生及计算实验设计思想及算法◆逆波兰式定义将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。
◆产生逆波兰式的前提中缀算术表达式◆逆波兰式生成的设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
运用以上算法分析表达式(a+b*c)*d的过程如下:当前符号输入区符号栈输出区( a+b*c)*da +b*c)*d (+ *c)*d ( ab c)*d (+ a* )*d (+ abc *d (+* ab) *d (+* abc) *d (+ abc*) d ( abc** abc*+d * abc*+* abc*+dabc*+d(1)构造一个栈,存放运算对象。
(2)读入一个用逆波兰式表示的简单算术表达式。
逆波兰公式
逆波兰公式(实用版)目录1.逆波兰公式的定义与概念2.逆波兰公式的求解方法3.逆波兰公式的应用实例4.逆波兰公式的优缺点分析正文1.逆波兰公式的定义与概念逆波兰公式,又称逆波兰表达式,是一种用于表示算术表达式的方式。
与常见的中缀表达式和中括号表达式不同,逆波兰表达式将运算符写在运算数的后面,从而形成了一种特殊的表达式形式。
这种表达式的求解方式也有所不同,需要采用逆波兰算法来完成。
2.逆波兰公式的求解方法逆波兰算法是一种基于栈的数据结构算法,其基本思想是将表达式中的运算符和运算数依次压入栈中,然后在栈顶进行运算。
具体步骤如下:(1)初始化一个空栈。
(2)从左到右遍历表达式,遇到运算数时,将其压入栈中;遇到运算符时,弹出栈顶的两个运算数进行运算,并将结果压入栈中。
(3)当遍历完整个表达式后,栈顶的元素即为最终的结果。
3.逆波兰公式的应用实例逆波兰公式在计算机科学中有广泛的应用,尤其在表达式求值、四则运算等方面有着重要的作用。
例如,对于表达式“2 + 3 * 4”,采用逆波兰算法可以得到如下的求解过程:(1)将数字 2 压入栈中。
(2)将数字 3 压入栈中。
(3)将运算符“*”压入栈中。
(4)弹出栈顶的数字 3 和数字 2,进行乘法运算,得到结果 6,并将其压入栈中。
(5)弹出栈顶的数字 6 和数字 4,进行加法运算,得到结果 10,即为最终结果。
4.逆波兰公式的优缺点分析逆波兰公式的优点在于其简洁明了的表达方式,可以直观地反映算术表达式的运算顺序。
此外,逆波兰算法的求解过程较为简单,容易实现,且具有较高的效率。
然而,逆波兰公式也存在一定的局限性。
由于逆波兰表达式中运算符位于运算数的后面,可能导致运算顺序不够明确,容易产生歧义。
栈的应用(逆波兰表达式)
栈的应⽤(逆波兰表达式)栈的应⽤(逆波兰表达式的计算)因为中缀表达式对于操作符的优先级很不好计算,就将中缀转成计算机更容易识别的后缀表达式中缀转后缀表达式写法:a+b => a b +a+(b-c) => a b c - +a+(b-c)*d => a b c - d * +a+d*(b-c) => a d b c - * +a=1+3 => a 1 3 + =后缀表达式(逆波兰表达式)计算规则:从左向右扫描,遇到操作符就将左边的两个数取出进⾏运算然后将结果插⼊到原来取出两个数的位置,再向右扫描代码实现:遇到数字就⼊数栈,遇到操作符就取出栈顶和次栈顶的数进⾏运算然后将结果压⼊数栈中,这⾥就不需要操作符栈了,因为每遇到⼀个操作符就进⾏了运算分割数和操作符并存⼊链表public static List<String> getListString(String suffixExpression) {//将表达式分割String[] strs = suffixExpression.split(" ");ArrayList<String> list = new ArrayList<>();//forEach的参数传递的是⼀个消费型接⼝Arrays.stream(strs).forEach((str) -> {list.add(str);});return list;}public static int caculate(List<String> list) {// 创建⼀个栈,只需要⼀个栈,只需要存数字Stack<String> stack = new Stack<>();// 遍历listlist.stream().forEach((str) -> {//这⾥使⽤正则表达式来判断是否是数字if (str.matches("\\d+")) {//匹配的是多位数//⼊栈stack.push(str);} else {//从栈中pop两个数并运算,结果再⼊栈//先pop出来的是被* 被/数//后pop出来的是 / -数int num2 = Integer.parseInt(stack.pop());int num1 = Integer.parseInt(stack.pop());int res = 0;switch (str) {case "+":res = num1 + num2;break;case "-":res = num1 - num2;break;case "*":res = num1 * num2;break;case "/":res = num1 / num2;break;default:throw new RuntimeException("运算符有误");}//结果⼊栈stack.push(res + "");}});//最后留在stack中的数是运算结果return Integer.parseInt(stack.pop());}。
数据结构实验报告——逆波兰表达式求值
实验三逆波兰表达式求值一.问题描述:读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。
二.需求分析:1. 本程序需要基于堆栈的基本操作来实现逆波兰表达式的求值。
2.若表达式正确,界面自动输出后缀表达式的值,否则输出表达式错误的信息,将结果置为0。
3.操作数和操作符均由键盘键入。
4.输入输入一个后缀表达式2 3 * 1 - #输出结果5三.概要设计由于操作的事一串字符,所以首先选择一个字符数组存储该串字符,直接使用编译器自带的字符数组。
由于计算后缀表达式时,具有先进后出的规律,故而考虑使用堆栈其ADT Stack{操作对象:字符,整数,浮点数基本操作:Stack(int size);//构造大小为size的堆栈~Stack();//撤销堆栈Bool IsEmpty();//是否为空,是返回true,否则返回falseBool IsFull();//是否为满,是返回true,否则返回falseVoid Push(T X);//将x压入堆栈Void Pop(T &x);//弹出栈顶元素,并用x保存对于计算后缀表达式的值的算法:首先假设此表达式正确从字符串第一个开始扫描,遇到运算数就先转化成为数值然后压入堆栈中,如遇到运算符则弹出堆栈上面的两个元素,并进行对应的运算,将得到的值压入栈中,直到最后一个字符为止。
对于表达式错误:返回01、小数缺少整数部分:如 .999未检测到数,而是直接检测到小数点2、运算符过多:2 3*-弹出一个数后堆栈便空3、运算数过多:3 7*0最后堆栈不空四.源程序:/*Name: 逆波兰表达式求值Copyright: WCH466-Experiment-3Author: wch466Date: 02/04/12 22:59Description: 读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。
*/// Copyright: WCH466-Experiment-3#include<iostream>#include<string>#include<cmath>using namespace std;class Astack{private:int size;int top;float *list;bool g;public:Astack(int se=4){size=se;top=0;list=new float [size];g=1;}~Astack() {delete [] list;}void push(const float& it) //入{if(top==size) return;list[top++]=it;}float pop(){if(top==0) {g=0;return 0;} //g=0代表表达式错误(运算符多了)return list[--top];}bool judge(){return g;}int length() const {/*cout<<"length of list is "<<top<<endl; */return top;}};// Copyright: WCH466-Experiment-3void Pretreatstr(const char *a) //预处理字符{ int i=0,g=1,s=1,size=strlen(a),k=0;float num=0,in=0,x,y,de=0; //stand for integer,decimalAstack t(size);for(i=0;i<size;i++){ if(a[i]=='#') break;if(a[i]>47){ s=1; //有数if(g)in=in*10+a[i]-48; //提取整数部分else //小数处理{ de=(a[i]-48)*pow(0.1,k++)+de;}}if(a[i]==46){if(g==0) {cout<<"小数点多余!";return ;} g=0;k=1;} //有小数if(a[i]==42||a[i]==43||a[i]==45||a[i]==47||a[i]==' '){if(s) // s=0 代表没数{t.push(in+de);in=0;de=0;g=1;s=0;}/*cout<<"插入:"<<in+de<<endl;*/ if(a[i]!=' ') { y=t.pop(); x=t.pop();}if(a[i]=='+') t.push(x+y);if(a[i]=='-') t.push(x-y);if(a[i]=='*') t.push(x*y);if(a[i]=='/') {if(y==0) {cout<<"分母为零!"<<endl; return;} t.push(x/y); }}}if(t.length()==1&&t.judge()&&a[i-1]<48) //最后一个字符不能为num{ cout<<"表达式的答案是:"<<int(t.pop()*100)/100.0<<endl;}elsecout<<"表达式错误"<<endl;};// Copyright: WCH466-Experiment-3int main(){char s[100];while(gets(s))Pretreatstr(s);system("pause");return 0;}五.测试结果:六.实验心得:1. 通过本次试验,我发现自己分析问题不是很全面,忽略掉一些细节。
js 逆波兰表达式
js 逆波兰表达式JavaScript中的逆波兰表达式(RPN)是一种非常有用的计算方法,可以在处理复杂的算术表达式时提高效率。
逆波兰表达式的计算顺序是先计算操作数,然后根据操作数来执行操作,因此它不需要使用括号来描述先后顺序,这使得它的表达式更加简洁和易于理解。
以下是逆波兰表达式(RPN)的基本算法:1. 创建空栈。
2. 从左到右扫描表达式,直到结尾。
3. 如果遇到操作数,则将其推入栈中。
4. 如果遇到运算符,则弹出栈中的两个操作数,并将它们应用于运算符。
然后将计算结果推入栈中。
5. 重复步骤3和4,直到表达式的最后一项。
6. 最后,栈中剩下的元素就是表达式的结果。
例如,以下是逆波兰表达式(RPN)的一个例子:输入:3 4 2 * 1 5 - 2 3 ^ ^ / +计算过程:1. 空栈2. 3 -> 栈:[3]3. 4 -> 栈:[3, 4]4. 2 -> 栈:[3, 4, 2]5. * -> 栈:[3, 8]6. 1 -> 栈:[3, 8, 1]7. 5 -> 栈:[3, 8, 1, 5]8. - -> 栈:[3, 8, -4]9. 2 -> 栈:[3, 8, -4, 2]10. 3 -> 栈:[3, 8, -4, 2, 3]11. ^ -> 栈:[3, 8, -4, 8]12. ^ -> 栈:[3, 16777224]13. / -> 栈:[0.000000017]14. + -> 栈:[3.000000017]因此,计算结果是3.000000017。
在JavaScript中,可以通过以下方法实现逆波兰表达式(RPN)的计算:function calculateRPN(expression) {const stack = [];for (let token of expression.split(' ')) {if (/^-?\d*\.?\d+$/.test(token)) { // 匹配数字stack.push(parseFloat(token));} else { // 匹配操作符const b = stack.pop();const a = stack.pop();switch (token) {case '+': stack.push(a + b); break;case '-': stack.push(a - b); break;case '*': stack.push(a * b); break;case '/': stack.push(a / b); break;case '%': stack.push(a % b); break;case '**': stack.push(a ** b); break;case '>': stack.push(a > b); break;case '<': stack.push(a < b); break;case '>=': stack.push(a >= b); break;case '<=': stack.push(a <= b); break;case '==': stack.push(a == b); break;case '!=': stack.push(a != b); break;case '&&': stack.push(a && b); break;case '||': stack.push(a || b); break;default: throw new Error('未知的操作符');}}}if (stack.length != 1) throw new Error('表达式错误'); return stack[0];}此方法将表达式作为输入字符串,并将每个标记拆分为数字和操作符。
逆波兰式的产生及计算
实验六逆波兰式的产生及计算一、实验目的:将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
二、实验预习提示1、逆波兰式定义将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。
采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。
2、产生逆波兰式的前提中缀算术表达式3、逆波兰式生成的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
3、逆波兰式计算的实验设计思想及算法(1)构造一个栈,存放运算对象。
(2)读入一个用逆波兰式表示的简单算术表达式。
(3)自左至右扫描该简单算术表达式并判断该字符,如果该字符是运算对象,则将该字符入栈。
若是运算符,如果此运算符是二目运算符,则将对栈顶部的两个运算对象进行该运算,将运算结果入栈,并且将执行该运算的两个运算对象从栈顶弹出。
如果该字符是一目运算符,则对栈顶部的元素实施该运算,将该栈顶部的元素弹出,将运算结果入栈。
(4)重复上述操作直至扫描完整个简单算术表达式的逆波兰式,确定所有字符都得到正确处理,我们便可以求出该简单算术表达式的值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
终于搞定逆波兰算法~!13 - 12 - 1 /*
* 缺点:
* 1:运算符比较少+ - * / ( )
* 2:只能运算10以下的数
* 3:运算结果为整数
*/
#include <stdio.h>//逆波兰
#define MAX 100
#define LEN 2 * MAX
//符号优先级表
int val[7][7] = {// + - * / ( ) #
/* 0 + */{ 1, 1, -1, -1, -1, 1, 1},
/* 1 - */{ 1, 1, -1, -1, -1, 1, 1},
/* 2 * */{ 1, 1, 1, 1, -1, 1, 1},
/* 3 / */{ 1, 1, 1, 1, -1, 1, 1},
/* 4 ( */{-1, -1, -1, -1, -1, 0, 8},
/* 5 ) */{ 1, 1, 1, 1, 8, 1, 1},
/* 6 # */{-1, -1, -1, -1, -1, 8, 0}
};
typedef char InputData;
typedef char ElemTypeOp;
typedef int ElemTypeS;
//-------------栈的操作-------------------
typedef struct Stack {//双栈
ElemTypeOp opData[MAX];//符号栈
ElemTypeS sData[MAX];//操作数栈
int topOp;//符号栈栈顶指针
int topS;//操作数栈顶指针
}Stack;
int initStack(Stack *s) {//初始化栈
s->opData[0] = '#';
s->topOp = 0;
s->topS = -1;
return 0;
}
int pushOp(Stack *s, ElemTypeOp op) {//运算符入栈
s->opData[s->topOp + 1] = op;
s->topOp++;
return 0;
}
int pushS(Stack *s, ElemTypeS num) {//操作数入栈
s->sData[s->topS + 1] = num;
s->topS++;
return 0;
}
int popOp(Stack *s, ElemTypeOp *op) {//运算符出栈
(*op) = s->opData[s->topOp];
s->topOp--;
return 0;
}
int popS(Stack *s, ElemTypeS *num) {//操作数出栈
(*num) = s->sData[s->topS];
s->topS--;
return 0;
}
ElemTypeOp getOpTop(Stack *s) {//得到运算符栈顶元素
return s->opData[s->topOp];
}
ElemTypeS getSTop(Stack *s) {//得到操作数栈顶元素
return s->sData[s->topS];
}
//---------------------------------
int valueOperator(ElemTypeOp op1, ElemTypeOp op2) {//取得符号优先级int x, y;
switch(op1) {
case '+': x = 0; break;
case '-': x = 1; break;
case '*': x = 2; break;
case '/': x = 3; break;
case '(': x = 4; break;
case ')': x = 5; break;
case '#': x = 6; break;
};
switch(op2) {
case '+': y = 0; break;
case '-': y = 1; break;
case '*': y = 2; break;
case '/': y = 3; break;
case '(': y = 4; break;
case ')': y = 5; break;
case '#': y = 6; break;
};
return val[x][y];
}
ElemTypeS calculate(ElemTypeOp op, ElemTypeS s1, ElemTypeS s2) {//两个操作数一个运算符计算值
ElemTypeS result;
switch(op) {
case '+': result = s1 + s2; break;
case '-': result = s1 - s2; break;
case '*': result = s1 * s2; break;
case '/': result = s1 / s2; break;
};
return result;//返回计算结果
}
int polish() {
int i = 0;
InputData input[LEN];//定义一个输入的表达式容器
ElemTypeOp tempOp;//临时的运算符
ElemTypeS tempS1, tempS2;//临时的操作数
Stack s;//定义一个运算要用的双栈
initStack(&s);//一定要初始化
printf("请输入数字小于10的多项式数式,在输入结尾加#字符:\n");
scanf("%s", input);
do {
if(input[i] >= '0' && input[i] <= '9')
{
pushS(&s, int(input[i] - '0'));
i++;
}
else if(valueOperator(getOpTop(&s), input[i]) == -1) {
pushOp(&s, input[i]);
i++;
}
else if(valueOperator(getOpTop(&s), input[i]) == 1) {
popOp(&s, &tempOp);
popS(&s, &tempS1);
popS(&s, &tempS2);
//printf("--------------%d\n", calculate(tempOp, tempS2, tempS1));
pushS(&s, calculate(tempOp, tempS2, tempS1));
}
else if(getOpTop(&s) == '(' && input[i] == ')') {
popOp(&s, &tempOp);
i++;
}
}while(!(getOpTop(&s) == input[i] && getOpTop(&s) == '#' && input[i] == '#')); return getSTop(&s);
}
int main() {
printf("answer: %d\n", polish());
return 0;
}。