后缀表达式的计算
计算后缀表达式的过程(C#)
计算后缀表达式的过程(C#)
计算后缀表达式的过程是⼀个很好玩的过程,⽽且很简单哦!这⾥呢,有个计算的技巧,就是:遇到数字直接⼊栈,遇到运算符就计算!
后缀表达式也叫逆波兰表达式,求值过程可以⽤到栈来辅助存储;
假定待求值的后缀表达式为:12 4 + 13 - 6 2 * + =
求计算出最终结果:
(1)⾸先我们看到在第⼀个运算符之前呢,有两个数字,那么我们就先把它放⼊栈中:
注:我们可以看到,下标是从下⽅开始读的,⼀定要注意哦,不要弄反了
(2)读到“+”,则弹出12和4,执⾏相加,12+4,=16,并把16放进栈中:(先弹12,再弹4,顺序不能弄错了!!)
(3)读到数字“13”,则直接把13放⼊栈内:
(4)读到运算符“-”,则弹出16和13,执⾏相减,那么16-13=3,并把3放⼊到栈中:
注:在这⾥我们可以看到,如果我们把弹出的顺序弄反了,那么得到的数字就会完全不同,那后⾯的结算也会完全不⼀样,所以,弹出的顺序不能弄反了
(5)读到数字“6”,直接⼊栈:
(6)读到数字“2”,直接⼊栈:
(7)读到运算符“*”,弹出6和2,执⾏相乘,6*2=12,并把12放⼊到栈中:
(8)读到运算符“+”,则弹出3和12,执⾏相加,3+12=15,并把15放⼊栈中:
(9)到了这⾥,我们已经把后缀表达式都已经执⾏了⼀遍,那么得到的最后结果为15,故:
12 4 + 13 - 6 2 * + = 15
这就是运算过程,是不是很简单
END。
后缀式计算过程
后缀式计算过程
嘿,朋友们!今天咱就来讲讲这后缀式计算过程。
啥是后缀式呢?简单来说,就是一种特别的计算表达方式。
咱平常做算术,都是先加减后乘除对吧,但后缀式可不一样。
就好比咱去超市买东西排队结账。
平常的计算方式就像是大家按先来后到排队,一个一个来。
而后缀式呢,就像是把这些商品和计算符号都扔到一个大框里,最后再一起算。
比如说,平常我们算 3 加 5 乘 2,得先算 5 乘 2 等于 10,再加上 3 得13。
但后缀式呢,就变成了3 5 2 * +。
先把3、5、2 放进去,看到乘号就先算 5 乘 2,得到 10,再看到加号,就把 3 和 10 加起来,还是13。
这可有意思了吧!那后缀式有啥好处呢?它能让计算更清晰,不容易出错呀。
我记得有一次,我给小侄子辅导数学作业,那算式写得密密麻麻,他看得晕头转向。
我就想,要是用后缀式,不就简单多了嘛。
于是我给他讲了后缀式,嘿,他一下子就明白了。
再比如说,我们在电脑编程里也常用到后缀式呢。
电脑可不像咱人脑,它得按照特定的规则来计算。
而后缀式就能让电脑的计算更准确、更高效。
其实呀,这后缀式就像一把特别的钥匙,能打开计算世界里的一扇新门。
让我们能从不同的角度去看计算,发现它的奇妙之处。
在生活中,我们也可以多试试用后缀式的思维去想问题。
有时候,换个角度,也许就能找到新的解决办法。
所以呀,朋友们,不妨多了解了解这后缀式计算过程,说不定哪天就能派上大用场呢!它能让我们的计算变得更有趣、更轻松。
试试吧,你会发现一个不一样的计算天地!。
后缀表达式计算过程
后缀表达式计算过程
嘿,小伙伴们!今天咱们来唠唠后缀表达式的计算过程。
这东西乍一听可能有点唬人,不过只要跟着来,没那么难的。
首先呢,咱们得有个后缀表达式对吧。
比如说像“3 4 + 2 ”这样的式子。
那怎么开始计算呢?咱们得找个地儿来存放中间结果,我一般就想象有个小盒子专门放这些数,哈哈。
接下来,就从左到右开始看这个表达式。
要是碰到数字呢,就直接把这个数字放到咱们那个小盒子里。
像前面这个例子,看到3和4,那就都放进去呗。
这一步超简单的,对吧?
然后呢,要是碰到运算符了,这时候就要小心喽!这个环节可以根据实际情况自行决定一些小细节哦。
像我们看到“+”,那就要把小盒子里最上面的两个数字拿出来,就是3和4啦,然后做加法,得到7再放回小盒子里。
我觉得这一步可以更灵活一点,要是你觉得心里没底,多核对几遍数字也没错。
继续往后看表达式,又碰到数字2了,那没说的,放进小盒子里。
再接着看到“”这个运算符了。
这时候呢,又要从小盒子里拿出最上面的两个数,现在小盒子里是7和2,拿出来做乘法,得到14再放回去。
不过呢,有时候可能会搞混顺序啥的。
步骤一其实很简单,但最好做一下步骤二,哦不对,还是按顺序来比较好。
刚开始可能会觉得麻烦,但习惯了就好了!
希望大家都能顺利掌握后缀表达式的计算过程呀!加油哦!。
后缀表达式求值的算法及代码
#include<stdlib.h>#include<stdio.h>struct node // 栈结构声明{int data; // 数据域struct node *next; // 指针域};typedef struct node stacklist; // 链表类型typedef stacklist *link; // 链表指针类型link operand=NULL; // 操作数栈指针link push(link stack,int value) // 进栈{link newnode; // 新结点指针newnode=new stacklist; // 分配新结点if (!newnode){printf("分配失败!");return NULL;}newnode->data=value; // 创建结点的内容newnode->next=stack;stack=newnode; // 新结点成为栈的开始return stack;}link pop(link stack,int *value) // 出栈{link top; // 指向栈顶if (stack !=NULL){top=stack; // 指向栈顶stack=stack->next; // 移动栈顶指针*value=top->data; // 取数据delete top; // 吸收结点return stack; // 返回栈顶指针}else*value=-1;}int empty(link stack) // 判栈空{if (stack!=NULL)return 1;elsereturn 0;}int isoperator(char op) // 判运算符{switch (op){case'+':case'-':case'*':return 1; // 是运算符,返回1case'/':return 0; // 不是运算符,返回0}}int getvalue(int op,int operand1,int operand2) // 计算表达式值{switch((char)op){case'*':return(operand1*operand2);case'/':return(operand1/operand2);case'+':return(operand1+operand2);case'-':return(operand1-operand2);}}void main() // 主函数{char exp[100];int operand1=0; // 定义操作数1int operand2=0; // 定义操作数2int result=0; // 定义操作结果int pos=0;printf("\t\n 请输入后缀表达式:");gets(exp); // 读取表达式printf("\t\n\n 后缀表达式[%s]的计算结果是:",exp);while (exp[pos] !='\0' && exp[pos] !='\n') // 分析表达式字符串{if (isoperator(exp[pos])) // 是运算符,取两个操作数{operand=pop(operand,&operand1);operand=pop(operand,&operand2);operand=push(operand,getvalue(exp[pos],operand1,operand2));// 计算结果入栈}elseoperand=push(operand,exp[pos]-48); // 是操作数,压入操作数栈pos++; // 移到下一个字符串位置}operand=pop(operand,&result); // 弹出结果printf("%d\n",result); // 输出}。
C++:后缀表达式
C++:后缀表达式1.基本概念后缀表⽰法也叫逆波兰表⽰法(前缀就是波兰表⽰法),由于所有的操作符都在操作数的后⾯,所以被称为后缀表⽰法。
中缀表⽰法的操作符在操作数之间,也是最符合⼈的逻辑。
前缀表⽰法的操作符在操作数之前,它和后缀表⽰法⼀样,都是为了⽅便计算机计算,因为在后缀或前缀中没有括号,也不存在优先级处理的问题,直接利⽤栈进⾏计算。
⽰例:中缀:5+(1+2)*4-3后缀:512+4*+3-2.中缀表⽰转后缀表⽰中缀转后缀可以从左向右扫描表达式,然后按照规则进⾏处理,对于中缀表达式a+(b+c)*d-e的转换步骤:(1). ⾸先初始化两个栈:输出栈rpn_和操作符栈rpn_stack(2). 从左⾄右扫描表达式,遇到操作数则直接压⼊输出栈,在遇到a时,由于是操作数,将"a"压⼊rpn_(3). 继续扫描,遇到操作符时,如果该操作符优先级⾼于rpn_stack栈顶的操作符,则直接压⼊rpn_stack,如果同级或低于栈顶操作符,则将栈中操作符依次弹出(同时压⼊输出栈)直到遇到⽐当前操作符优先级低的(或者遇到了"("),然后压⼊操作符。
(注意,对于操作符"(",只有")"才能将其弹出,其他情况不弹出"(")。
现在我们扫描到了"+",由于当前的操作符栈空,直接压⼊。
(4). 然后读取到"(",由于它的优先级是最⾼的,只要遇到就直接压⼊栈。
(5). 然后读取到操作数"b",压⼊输出栈 rpn_。
(6). 继续读取到 "+" ,当前操作符栈的栈顶是"(",因为只有")"才能将其弹出,所以"+"⼊栈。
(7). 读取的"c"压⼊输出栈。
(8). 读取到了")",此时开始将操作符栈的操作符依次弹出(同时压⼊输出栈),直到遇到第⼀个"(",将"("弹出。
C#算术表达式求值(后缀法),看这一篇就够了
C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。
⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。
1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。
因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。
⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。
⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。
举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。
2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。
在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。
3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。
他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。
因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。
因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。
VCB-Studio教程21后缀表达式的求值与转换
VCB-Studio教程21: 后缀表达式的求值与转换本教程旨在讲述后缀表达式的求值与设计1. 后缀表达式简介我们平时使用的表达式,叫做中缀表达式(infix notation),表现为1+1这样:算数算符算数而计算机程序中的表达式多采用后缀表达式(suffix noation/inverse polish notation),表现为:1 1 +,算数,算数,算符。
为了方便起见,我们先简化假设,所有运算,都是只有两个算数参与,比如常见的四则运算。
中缀表达式是依赖括号,以及既定的运算优先度来决定运算顺序。
比如说5+4*(3+2)3,最先运算的是3+2=5,接着运算53=125,再算4*125=500,最后算5+500=505。
这些看上去很自然的小学数学题,加了各种扩展(各种高级函数和自定义运算符),到了计算机里面就不是那么自然了。
麻烦点主要是括号的处理,以及不同优先级的定义。
为了解决这个,计算机普遍使用的是后缀表达式。
后缀表达式没有优先级和括号,通过表达式本身的组合来决定运算规则。
将上述表达式用后缀表达式写出来(假设pow代表乘方),效果是:5 4 3 2 + 3 pow * +如何解析并计算一个后缀表达式,如何将后缀表达式与中缀表达式互转,我们首先需要了解一下计算机中常用的数据结构——堆栈(stack)的概念2. 堆栈(stack)堆栈是计算机科学里面一种常见的数据结构,它可以看作一个薯片桶,内部数据呈线性排列,所有数据操作都只能在桶顶部进行:你能够对栈做这些操作:初始化(init):创造一个空的栈。
判断是否为空(isEmpty):判断这个栈里面有无东西,如果没有,则为空栈。
入栈(push):把一个数据丢入这个栈里面,只不过你只能丢到最顶端。
出栈(pop):在栈不为空的前提下(否则报错),读取栈顶的值,并且把这个数据从栈里拿出去。
读取(top):在栈不为空的前提下(否则报错),读取栈顶的值,但是不把数据拿出去。
算法笔记--中缀表达式转后缀表达式后缀表达式计算
算法笔记--中缀表达式转后缀表达式后缀表达式计算中缀表达式转后缀表达式规则中缀表达式a + b*c + (d * e + f) * g,转换成后缀表达式则为a b c * + d e * f + g * +转换过程需要⽤到栈,具体过程如下:1 如果遇到操作数,我们就直接将其输出。
2 如果遇到操作符,则我们将其放⼊到栈中,遇到左括号时我们也将其放⼊栈中。
3 如果遇到⼀个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为⽌。
注意,左括号只弹出并不输出。
4 如果遇到任何其他的操作符,如+, *, (等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为⽌。
弹出完这些元素后,才将遇到的操作符压⼊到栈中。
有⼀点需要注意,只有在遇到 )的情况下我们才弹出( ,其他情况我们都不会弹出( 。
即:若操作符op的优先级⾼于栈顶操作符的优先级,则压⼊操作符栈若操作符op的优先级⼩于等于栈顶操作符的优先级,则将操作栈的操作符不断弹出到后缀表达式中,直到op的优先级⾼于栈顶操作符的优先级5 如果我们读到了输⼊的末尾,则将栈中所有元素依次弹出。
实例a +b *c + (d *e + f) * g1. ⾸先读到a,直接输出。
2. 读到“+”,将其放⼊到栈中。
3. 读到b,直接输出。
此时栈和输出的情况如下:4. 读到“*”,因为栈顶元素"+"优先级⽐" * " 低,所以将" * "直接压⼊栈中。
5. 读到c,直接输出。
此时栈和输出情况如下:6. 读到" + ",因为栈顶元素" * "的优先级⽐它⾼,所以弹出" * "并输出,同理,栈中下⼀个元素" + "优先级与读到的操作符" + "⼀样,所以也要弹出并输出。
然后再将读到的" + "压⼊栈中。
后缀表达式
编写Java程序时,我们可能会碰到解释数学表达式的问题,例如,输入字符串“(5+4)*10”,求出其算术结果,对于这个问题,可以通过后缀表达式来解决。
首先,让我们看看后缀表达式的算法:1) 将中缀表达式转换为后缀表达式:•当读到数字直接送至输出队列中;•当读到运算符t时:a.将栈中所有优先级高于或等于t的运算符弹出,送到输出队列中;b.t进栈;•读到左括号时总是将它压入栈中;•读到右括号时,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号;•中缀表达式全部读完后,若栈中仍有运算符,将其送到输出队列中。
2) 运用后缀表达式进行计算:•建立一个栈S;•从左到右读后缀表达式,读到数字就将它转换为数值压入栈S中,读到运算符则从栈中依次弹出两个数分别到Y和X,然后以“X 运算符Y”的形式计算机出结果,再压加栈S中;•如果后缀表达式未读完,就重复上面过程,最后输出栈顶的数值则为结束。
以下是代码实现:package wenly.util;import java.util.Stack;import java.util.regex.*;public class StringToArithmetic {private StringToArithmetic() {}/*** 给出一个算术表达式,返回结果。
例如(5+8+10)*1,返回23** @param string*/public static double stringToArithmetic(String string) { return postfixExprToArithmetic(prefixExprToPostfixExpr(string)); }/*** 中缀表达式转后缀表达式** @param String* prefix* @return String*/private static String prefixExprToPostfixExpr(String prefix) { Stack<Character> stack = new Stack<Character>();String postfix = "";int length = prefix.length();for(int i = 0; i < length; i++) {Character temp;char c = prefix.charAt(i);switch(c) {// 忽略空格case' ':break;// 碰到'(',push到栈case'(':stack.push(c);break;// 碰到'+''-',将栈中所有运算符弹出,送到输出队列中case'+':case'-':while(stack.size() != 0) {temp = stack.pop();if(temp == '(') {stack.push('(');break;}postfix += " " + temp;}stack.push(c);postfix += " ";break;// 碰到'*''/',将栈中所有乘除运算符弹出,送到输出队列中case'*':case'/':while(stack.size() != 0) {temp = stack.pop();if(temp == '(' || temp == '+' || temp == '-') {stack.push(temp);break;} else{postfix += " " + temp;}}stack.push(c);postfix += " ";break;// 碰到右括号,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号case')':while(stack.size() != 0) {temp = stack.pop();if(temp == '(')break;elsepostfix += " " + temp;}postfix += " ";break;default:postfix += c;}}while(stack.size() != 0)postfix += " " + stack.pop();return postfix;}/*** 通过后缀表达式求出算术结果** @param String* postfix* @return double*/private static double postfixExprToArithmetic(String postfix) { Pattern pattern = pile("/d+||/d+/./d*"); // 匹配数字String strings[] = postfix.split(" ");for(int i = 0; i < strings.length; i++)strings[i].trim();Stack<Double> stack = new Stack<Double>();for(int i = 0; i < strings.length; i++) {if(strings[i].equals(""))continue;if((pattern.matcher(strings[i])).matches()) {stack.push(Double.parseDouble(strings[i]));} else{double y = stack.pop();double x = stack.pop();stack.push(caculate(x, y, strings[i]));}}return stack.pop();}private static double caculate(double x, double y, String simble) { if(simble.trim().equals("+"))return x + y;if(simble.trim().equals("-"))return x - y;if(simble.trim().equals("*"))return x * y;if(simble.trim().equals("/"))return x / y;return0;}}。
【Java数据结构】中缀表达式转后缀表达式,后缀表达式的计算(多位数)
【Java数据结构】中缀表达式转后缀表达式,后缀表达式的计算(多位数)中缀表达式转后缀表达式,后缀表达式的计算(多位数)中缀表达式转后缀表达式思路(1)初始化两个栈stack1与stack2,分别存储数和操作符(2)从左到右扫描中缀表达式(3)遇到数字时,直接将其压⼊stack1中(4)遇到操作符时,先进性⽐较优先级,如果优先级⽐栈顶元素的⾼,则直接⼊栈如果优先级⽐栈顶元素的低,则将栈顶元素弹出压⼊数栈,再将操作符与栈顶重复⽐较,直到可以⼊栈如果符号栈为空或者栈顶是左括号(,则直接⼊栈如果操作符是右括号),则将操作符依次出栈放⼊数栈中,直到遇到左括号,⼆者直接丢弃(5)扫描完成,将操作符栈stack2依次出栈并压⼊stack1中后缀表达式计算器思路(1)初始化⼀个栈(2)遇到数字时,直接将数字压⼊栈(3)遇到运算符时,将栈顶的两个数弹出,并且计算,将结果⼊栈Java代码如下1import java.util.ArrayList;2import java.util.Deque;3import java.util.LinkedList;4import java.util.List;56public class Main {7public static void main(String[] args) {8 String str ="11+(2*4)+3*(61-1)";//结果为11+8+180=1999//将字符串转成list10 List<String> List = toInfixExpressionList(str);11 System.out.println(List);12//中缀表达式转后缀表达式13 List<String> suffixList = prefixToSuffix(List);14 System.out.println(suffixList);15//计算后缀表达式的结果16 System.out.println("后缀表达式的计算结果为:"+toCalculation(suffixList));17 }1819/**20 * 将表达式每⼀个部分转换成list21 * @param str 计算表达式22 * @return List23*/24public static List<String> toInfixExpressionList(String str){25 List<String> list = new ArrayList<>(str.length());26int i = 0;//⽤于遍历表达式的指针27char c;//⽤于存储每⼀个遍历到的字符28 StringBuilder s;//⽤于多位数的拼接29while (i<str.length()){30 c = str.charAt(i);31//如果是⾮数字,直接加⼊到list32if(c < 48 || c > 57){33 list.add(""+c);34 i++;35 }else {36 s = new StringBuilder();37while (c >= 48 && c <= 57){38 s.append(c);39 i++;40 c = str.charAt(i);41 }42 list.add(s.toString());43 }44 }45return list;46 }4748/**49 * 计算后缀表达式50 * @return计算结果51*/52public static Integer toCalculation(List<String> list){53 Deque<String> stack = new LinkedList<>();54for(String item: list){55if(isNumeric(item)){56 stack.push(item);57 }else {58int x = Integer.parseInt(stack.pop());59int y = Integer.parseInt(stack.pop());60switch (item){61case "+":62 stack.push((y+x)+"");63break;64case "-":65 stack.push((y-x)+"");66break;67case "*":68 stack.push((y*x)+"");69break;70case "/":71 stack.push((y/x)+"");72break;73default:74throw new RuntimeException("输⼊错误!");75 }76 }77 }78return Integer.parseInt(stack.pop());79 }8081/**82 * 中缀表达式转后缀表达式83 * @return List84*/85public static List<String> prefixToSuffix(List<String> list){86//初始化两个栈,stack1为数栈,stack2为操作符栈87 List<String> stack1 = new ArrayList<>();88 Deque<String> stack2 = new LinkedList<>();89for(String item: list){90if(isNumeric(item)){91//数字直接⼊栈92 stack1.add(item);93 }else if(item.equals("(")) {94//左括号或者空直接⼊栈95 stack2.push(item);96 }else if(item.equals(")")){97//右括号将符号栈中左括号前的所有符号⼊数栈98while (!stack2.peek().equals("(")){99 stack1.add(stack2.pop());100 }101 stack2.pop();//清除括号102 }else if(stack2.peek()==null||judgePriority(item)>judgePriority(stack2.peek())){ 103//优先级⽐栈顶元素⾼,直接⼊栈104 stack2.push(item);105 }else {106//优先级⽐栈顶元素低或者相等,将栈顶优先级⾼的⼊数栈107while (stack2.peek()!=null&&judgePriority(stack2.peek())<=judgePriority(item)){ 108 stack1.add(stack2.pop());109 }110 stack2.push(item);111 }112 }113while (stack2.peek()!=null){114 stack1.add(stack2.pop());115 }116117return stack1;118 }119120/**121 * 返回运算符优先级,加减为1,乘除为2122 * @param str 运算符123 * @return优先级124*/125public static int judgePriority(String str){126switch (str){127case "+":128return 1;129case "-":130return 1;131case "*":132return 2;133case "/":134return 2;135case "(":136return 0;137case ")":138return 0;139default:140throw new RuntimeException("输⼊有误!"+str); 141 }142 }143144/**145 * 判断字符串是否是正整数146 * @param str 字符串147 * @return boolean148*/149public static boolean isNumeric(String str){150for (int i = str.length();--i>=0;){151if (!Character.isDigit(str.charAt(i))){152return false;153 }154 }155return true;156 }157 }。
后缀表达式计算规则
后缀表达式计算规则
后缀表达式的计算规则是:
1. 当遇到操作数(数字)时,将其入栈。
2. 当遇到操作符时,取出栈顶的两个元素,根据当前操作符进行计算,将计算结果再压入栈顶。
3. 如果表达式是规整的表达式,在整个表达式扫描完成之后,栈顶将只有一个数字,该数据即为计算结果。
4. 不包含括号,运算符放在两个运算对象的后面。
所有计算均按运算符出现的顺序(不再考虑乘除优先于加减这种运算符的优先规则),严格从左向右进行。
按照以上步骤进行计算,就可以得出最终结果。
中缀、前缀、后缀表达式的运算
中缀、前缀、后缀表达式的运算 中缀表达式,就是在表达式中,操作符在操作数的中间,⽐如 (1+2)*3,+和*在1, 2, 3的中间。
前缀表达式,就是操作符在操作数的前⾯,⽐如 +12,+在1, 2的前⾯。
后缀表达式,就是操作符在操作数的后⾯,⽐如 12+,+在1, 2的后⾯。
为什么会有这么多表达式呢?它们⽬的不同。
中缀表达式,便于我们书写,也符合我们的阅读习惯,在计算机程序中,都是写中缀表达式,但它却不利于计算机进⾏算术计算,因为涉及到优先级和括号。
前缀表达式和后缀表达式中没有括号,并且运算符的优先级也通过它们在表达式中的顺序体现出来了,有利于计算机进⾏算术运算。
前缀表达式也叫波兰表达式,因为它是由⼀个波兰⼈发明的,相应的,后缀表达式也称为逆波兰表达式。
举个例⼦来说明⼀下三者的运算过程,假设计算(3+4)*5-6 使⽤中缀表达式进⾏计算 1,创建两个栈,⼀个是数字栈,⽤来存放操作数,⼀个是字符栈,⽤来存放操作符。
2,算术表达式是⼀个字符串,从左到右循环遍历表达式,依次取出每⼀个字符。
当取出的字符是操作数时,⼊数字栈。
当取出的字符是操作符时,这时还要看操作符的优先级和字符栈是否为空 如果字符栈为空,直接把取出的字符放⼊到字符栈中。
如果字符栈不为空,则要⽐较字符的优先级 如果取出的字符的优先级⼤于等于字符栈中栈顶的字符的优先级,直接把取出的字符放⼊到字符栈中。
如果取出的字符的优先级⽐字符栈中栈顶的字符的优先级低,则要循环进⾏如下操作,直到取出的字符的优先级⼤于等于字符栈中栈顶字符的优先级或者栈为空,此时,把取出的字符放⼊到字 符栈中。
如下操作就是: 1,从字符栈中弹出操作符 2,从数字栈中弹出两个操作数。
3,操作数结合操作符进⾏计算,要注意操作数顺序,后⾯pop出的数在求值的表达式中是前⾯的操作数,尤其是在做减法的时候 4,计算出的值放⼊到数字栈。
为什么要⽐较操作符的优先级呢?因为要确定操作数属于哪个操作符,相邻两个操作符之间的数字是共享的。
C语言后缀表达式计算
一、设计思想计算算数表达式并求值,采取的共有两种方法:1.先将算数表达式转化为后缀表达式,然后对后缀表达式进行计算。
2.对算数表达式进行直接的计算。
第一种算法这种解决方案又分为两步:1.将表达式先转化为后缀表达式的字符串数组2.利用后缀表达式进行计算在转化过程中,第一,建立一个存符号的栈,和一个字符串数组,用来存放转化以后的表达式然后,对于得到的用户输入的字符串进行逐个的扫描,如果是数组或者小数点,则直接存放到数组中,并且在后面加入一个分隔符,如果是操作符,则和栈中的已存的进行比较,如果比栈中的操作符的优先级高,则直接入栈,如果优先级低或相等,则栈中元素出栈,存到字符串中,然后再次检查栈顶,直到栈中元素的优先级低于扫描操作符,则此操作符入栈,然后扫描下一个字符,直到遇到字符串的结束符号\0,扫描结束。
数组中存的就是后缀表达式。
得到后缀表达式后,进行计算,要用到数值栈。
首先要将字符表示的数字转化为浮点小数,然后进行扫描,遇到数值,放入栈中,遇到操作符,就从栈中取出两个数,进行计算后再放入栈中,扫描下一个,最后的计算结果就存到了栈中,直接取出栈内元素,就是计算的最后结果。
第二种算发首先要建立两个栈,一个用来存放操作符,一个用来存放数值。
开始对用户输入的字符串进行扫描,如果是数字字符或者小数点,则将字符转化为浮点数存到数栈里,如果是操作符,则观察符号栈,如果栈顶元素的优先级低于观察的操作符,则操作符入栈,如果栈顶元素的优先级高于或者等于观察的操作符,则从数值栈中取出两个浮点数,从符号栈中取出栈顶的操作符,然后进行相应的数值计算,所得的结果再存到数值栈中,重复这样的操作,直到符号栈中栈顶元素的优先级低于观察的操作符,则此操作符入栈,然后对下一个字符进行扫描。
如果是左括号,则不进行优先级的比较,直接入栈,入栈后优先级为-1。
如果是右括号,则从数值栈中取两个操作数,符号栈中取出一个符号,然后进行计算后得数放入数栈中,不断进行此类操作,直到从栈中取出的是左括号为止,左括号去掉,扫描下一个。
图解后缀表达式的计算过程
图解后缀表达式的计算过程
为了解释后缀表达式的好处,我们先来看看,计算机如何应⽤后缀表达式计算出最终的结果20的。
后缀表达式:9 3 1-3*+ 10 2/+
规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进⾏运算,运算结果进栈,⼀直到最终获得结果。
下⾯是详细的步骤:
1. 初始化⼀个空栈。
此桟⽤来对要运算的数字进出使⽤。
2. 后缀表达式中前三个都是数字,所以9、3、1进栈。
3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。
4. 接着是数字3进栈。
5. 后⾯是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。
6. 下⾯是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。
7. 接着是10与2两数字进栈。
8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。
9. 最后⼀个是符号“+”,所以15与5出找并相加,得到20,将20进栈。
10. 结果是20出栈,栈变为空。
后缀表达式的算法和实现
数据结构—中缀表达式转后缀表达式算法及实现—栈的应用—计算表达式(C++代...理论:(这部分很重要,看明白了,可以写出实现算法)表达式的表示形式有中缀、前缀和后缀3中形式。
中缀表达式按操作符的优先级进行计算(后面代码实现只包括+、-、*、\,小括号),即数学运算。
后缀表达式中只有操作数和操作符。
操作符在两个操作数之后。
它的计算规则非常简单,严格按照从左到右的次序依次执行每一个操作。
每遇到一个操作符,就将前面的两个数执行相应的操作。
由后缀表达式计算中缀表达式原理:计算机处理后缀表达式求值问题是比较方便的,即将遇到的操作数暂存于一个操作数栈中,凡是遇到操作数,便从栈中pop出两个操作数,并将结果存于操作数栈中,直到对后缀表达式中最后一个操作数处理完,最后压入栈中的数就是后最表达式的计算结果。
中缀表达式转换为等价的后缀表达式中缀表达式不方便与计算机处理,通常要讲中缀表达式转换为一个与之等价的后缀表达式。
等价是指两个表达式的计算顺序和计算结果完全相同。
中缀表达式:0.3/(5*2+1)#的等价后缀表达式是:0.3 5 2 * 1 + /#仔细观察这两个等价的表达式可知,操作数的出现次序是相同的,但运算符的出现次序是不同的。
在后缀表达式中,运算符的出现次序是实际进行操作的次序;在中追表达式中,由于受到操作符的优先级和括号的影响,操作符出现次序与实际进行操作的次序很可能是不一样的。
算法描述:将中缀表达式转换为等价的后缀表达式的过程要使用一个栈放“(”,具体可以按照下面的方式进行。
(1)从左到右一次扫描中缀表达式的每一个字符,如果是数字字符和圆点“.”则直接将它们写入后缀表达式中。
(2)如果遇到的是开括号“(”,则将它们压入一个操作符栈(不需要与栈顶操作符相比较),它表明一个新的计算层次的开始,在遇到和它匹配的闭括号“)”时,将栈中的元素弹出来并放入后缀表达式中,直到栈顶元素为“(”时,将栈顶元素“(”弹出(不需要加入后缀表达式),表明这一层括号的操作处理完毕。
数据结构实验四后缀表达式的计算
实验四后缀表达式的计算实验目的:熟练掌握栈和队列的存储结构设计及基本操作的实现;学会分析实际问题中具有栈特点的数据结构;了解表达式的前缀、中缀、后缀等计算机内表示形式。
实验内容与要求:按常规形式输入算术表达式(例如:输入2*(6-4)+8/4),要求能够:(1)基于表达式的中缀表示,对该表达式求值;(2)生成表达式的后缀表示,并输出;(3)基于表达式的后缀表示,对该表达式求值;(4)编写一个主程序对中序和后序表达式求值函数进行测试。
源程序:#include<stdio.h>#include<string.h>#include<stdlib.h>char s1[20],s2[20],a;int x,y,z,n,m,i,j=0;typedef struct node //数据结构常用类型{char data;int num;struct node *next;}sqstack;sqstack *InitSqStack()//创建栈并实现输入{sqstack *top;top=(sqstack *)malloc(sizeof(sqstack));top->data='#';top->num=0;top->next=NULL;return top;}sqstack *Push(sqstack *s)//实现表达式的后序表达{sqstack *p,*top;top=s;gets(s1);m=strlen(s1);for(i=0;i<=m;i++){a=s1[i];if('0'<=s1[i]&&s1[i]<='9'){s2[j]=s1[i];j++;} else{switch(a){case '(':{p=(sqstack *)malloc(sizeof(sqstack));p->data=a;p->next=top;top=p;break;}case '*':case '/':s2[j]=' ';j++;if((top->data=='*')||(top->data=='/')){s2[j]=top->data;j++;top->data=a;break;} else{p=(sqstack *)malloc(sizeof(sqstack));p->data=a;p->next=top;top=p;break;}case '+':case '-':{s2[j]=' ';j++;if(top->data=='+'||top->data=='-'||top->data=='*'||top->data=='/'){s2[j]=top->data;j++;top->data=a;break;} else{p=(sqstack *)malloc(sizeof(sqstack));p->data=a;p->next=top;top=p;break;}}case ')':{s2[j]=' ';j++;if(top->data=='#'){printf("input error");break;}while(top->data!='('){s2[j]=top->data;j++;p=top;top=top->next;free(p);}p=top;top=top->next;free(p);break;}}}}while(top->data!='#')//外部加入的输出函数{s2[j]=top->data;j++;p=top;top=top->next;free(p);}s2[j]='#';printf("后缀表达式为:%s\n",s2);return top;}sqstack *Calcolate(sqstack *s)//中序求值法{sqstack *top,*p;char *q;top=s;for(i=0;i<=j;i++){if(s2[i]>='0'&&s2[i]<='9'){q=&s2[i];z=atoi(q);for(n=i;s2[n]>='0'&&s2[n]<='9';n++)p=(sqstack *)malloc(sizeof(sqstack));p->num=z;p->next=top;top=p;i=n-1; elseif(s2[i]=='#')printf("表达式求值结果为:%d\n",top->num); else{if(s2[i]==' ') else{y=top->num;p=top;top=top->next;free(p);x=top->num;p=top;top=top->next;free(p);switch(s2[i]){case '+':{z=x+y;p=(sqstack *)malloc(sizeof(sqstack));p->num=z;p->next=top;top=p;break;}case '-':{z=x-y;p=(sqstack *)malloc(sizeof(sqstack));p->num=z;p->next=top;top=p;break;}case '*':{z=x*y;p=(sqstack *)malloc(sizeof(sqstack));p->num=z;p->next=top;top=p;break;}case '/':{z=x/y;p=(sqstack *)malloc(sizeof(sqstack));p->num=z;p->next=top;top=p;break;}}}}}return 0;}void main()//主函数部分{sqstack *top,*head;top=InitSqStack();printf("请输入表达式:");head=Push(top);Calcolate(head);}测试结果:心得体会:这个程序极为复杂,算法都不会,没有写出来,这个程序是根据同学的程序改了一些形式而已,没有内部算法的改动,盯着电脑看了一整天大致看懂了。
中缀表达式转后缀表达式并计算结果
中缀表达式转后缀表达式并计算结果⽬录1 栈的概念容器,先进后出规则;如图为表达式:a+(b*c) 逐个操作符、操作数⼊栈过程;出栈为该过程逆序2 何谓中缀表达式型如:a - b + c 的普通算术表达式,我们称之为中缀表达式。
3 后缀表达式(逆波兰)3.1 概念以及案例中缀表达式:a - b + c ,转化为后缀表达式:ab-c+;后缀表达式运算规则:1. 遇到操作数直接⼊栈,遇到操作符,从栈顶弹出两个操作数,并计算如下表达式结果压栈,直⾄最终弹出栈中最后⼀个数即停⽌算法,该记法的表达式称为后缀表达式后出栈操作数(两数中更靠近栈底者) (操作符[+_*/])先出栈操作数(栈顶)2. ab-c+计算过程如下图:3.2 求解⽅法⼊栈优先级{ [ ( > 乘= 除> 加= 减3.2.1 流程图弹出案例:扫描位优先级较⼩,扫描位为 " - "。
左括号虽然优先级⼤,但是左括号只在碰到,匹配的右括号时弹出3.2.2 推导相等优先级为何弹出栈顶只关注相同有优先级下是否弹出栈顶先加,后加减中缀表达式后缀表达式a +b +c abc++ 或 ab+c+a +b -c ab+c- 或 abc-+中缀表达式后缀表达式此例中,当需要判断操作符间优先级:栈顶为:+(加),栈外判断位:+ 或 - 。
此时若优先级相等,既可弹出栈顶操作符,也可不弹直接当前位压栈。
先减,后加减中缀表达式后缀表达式a -b +c ab-c+a -b -c ab-c-此例中,当需要判断操作符间优先级:栈顶为:-(减),栈外判断位:+ 或 - 。
此时若优先级相等,则只能弹出当前栈顶操作符。
先乘,后乘除中缀表达式后缀表达式a *b *c abc** 或 ab ca *b /c ab c/ 或 abc/此例中,当需要判断操作符间优先级:栈顶为:(乘),栈外判断位:或 / 。
此时若优先级相等,既可弹出栈顶操作符,也可不弹直接当前位压栈。
c语言后缀表达式计算
c语言后缀表达式计算C语言是一门面向过程的编程语言,它能够处理各种不同的计算需求,包括后缀表达式的计算。
所谓后缀表达式,也叫做逆波兰表达式,是一种使用后缀符号(如“+”、“-”、“*”、“/”等)表示数学表达式的方法。
与中缀表达式相比,后缀表达式的计算更加高效和简单。
下面,我们就来一步步介绍C语言如何计算后缀表达式。
步骤一:将后缀表达式转换为栈要实现后缀表达式的计算,首先需要将后缀表达式对应的字符串转换为栈。
在这个过程中,需要分别处理操作数和操作符。
对于操作数,可以使用变量num来保存其值,并将其推入栈中。
对于操作符,可以利用switch语句来处理,如果遇到“+”或“-”或“*”或“/”等操作符,则需要从栈中弹出两个操作数进行计算,并将结果推入栈中。
示例代码如下:```c#include <stdio.h>#include <string.h>#include <stdlib.h>#define MAX_STACK_SIZE 100double stack[MAX_STACK_SIZE];int top = -1;void push(double num) {if (top >= MAX_STACK_SIZE - 1) {printf("Stack overflow.\n");return;}stack[++top] = num;}double pop() {if (top < 0) {printf("Stack underflow.\n");return 0;}return stack[top--];}int isOperator(char *token) {return (strcmp(token, "+") == 0 || strcmp(token, "-") == 0 ||strcmp(token, "*") == 0 || strcmp(token, "/") == 0);}void calculate(char *operator) {double num1 = pop();double num2 = pop();double result;switch (operator[0]) {case '+':result = num2 + num1;break;case '-':result = num2 - num1;break;case '*':result = num2 * num1;break;case '/':result = num2 / num1;break;}push(result);}int main() {char expression[100];printf("Enter the expression: ");gets(expression);char *token = strtok(expression, " ");while (token != NULL) {if (!isOperator(token)) {push(atof(token));} else {calculate(token);}token = strtok(NULL, " ");}printf("Result: %lf\n", pop());return 0;}```步骤二:读入后缀表达式完成栈的转换之后,就可以开始读入后缀表达式了。
栈应用之后缀表达式计算(python版)
栈应⽤之后缀表达式计算(python版)栈应⽤之后缀表达式计算(python 版)后缀表达式特别适合计算机处理1. 中缀表达式、前缀表达式、后缀表达式区别 中缀表达式:(3 - 5) * (6 + 17 * 4) / 3 17 * 4 + 6前缀表达式:/ * - 3 5 + 6 * 17 4 3 * 17 4 + 6后缀表达式:3 5 - 6 17 4 * + * 3 / 17 4 * 6 +2. 算法核⼼ 假定 st 是⼀个栈(栈的特点:后进先出 LIFO) ⽐如【3 / 5】即【3 5 / 】; 3 先压⼊栈,⽽后 5 出栈; 元素在栈⾥⾯的顺序应该是【5,3】; 5 先出栈,⽽后 3 出栈。
所以第⼆个运算对象先出栈,第⼀个运算对象后出栈。
1# 扩充栈的⽅法计算栈元素个数2class ESStack(SStack):3"""docstring for ESS"""4def depth(self):5return len(self._elems)1def auf_exp_evaluator(exp):2 operatora = '+-*/'3 st = ESStack() # 扩充功能的栈,可⽤depth()检查元素个数45for x in exp:6if x not in operatora:7 st.push(flaot(x))8continue# 跳过本次for循环910if st.depth() < 2 :11raise SyntaxError{"Short of operand(s)"}12 a = st.pop() # 取出第⼆个运算对象13 b = st.pop() # 取出第⼀个运算对象1415if x == "+":16 c = b + a17elif x == "-":18 c = b - a19elif x == "*":20 c = b * a21elif x == "/" : # 这⾥可能引发异常 ZeroDivisionError22 c = b / a23else :24break# 这⼀步不可能出现,只是为了⽅便看、理解2526 st.push(c) # 将本次运算结果压⼊栈2728if st.depth() == 1 # 如果栈⾥⾯只有⼀个元素,表⽰计算完成29return st.pop()30raise SyntaxError{"Extra operand(s) ."}。
递归版 后缀表达式
后缀表达式也称为逆波兰表达式,使用递归可以比较简便地进行计算。
具体的后缀表达式计算递归算法如下:1. 定义一个栈,用于存储操作数。
2. 从左到右扫描后缀表达式,每次取出一个操作符或操作数。
3. 如果是操作数,则将其压入栈中。
4. 如果是操作符,则从栈中取出两个操作数,将操作符应用于这两个操作数,并将计算结果压入栈中。
5. 重复上述步骤,直到扫描完整个后缀表达式。
6. 最后栈中存放的就是表达式的计算结果。
下面是一个使用递归计算后缀表达式的示例Python 代码:```pythondef calculate(expression):# 定义操作符映射表operators = {'+': lambda x, y: x + y,'-': lambda x, y: x - y,'*': lambda x, y: x * y,'/': lambda x, y: x / y}# 定义递归函数def helper(stack):# 取出栈顶元素item = stack.pop()if item in operators:# 如果是操作符,递归计算出栈顶的两个操作数y = helper(stack)x = helper(stack)# 计算结果,并压入栈中stack.append(operators[item](x, y))else:# 如果是操作数,直接压入栈中stack.append(float(item))# 返回栈顶元素return stack[-1]# 将表达式按照空格划分为单词tokens = expression.split()# 创建一个空栈,递归计算表达式的值value = helper(tokens)# 返回计算结果return value```。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for (int i = 0;i < v.size();i++)
{
cout<<v[i];
}
cout<<endl;
if (compute(v,res))
{
cout<<res<<endl;
}
else
cout<<"输入错误"<<endl;
return 0;
}
测试数据
1+2*(3+4)-2*(3-2)
switch(s[i])
{
case '+':
stk.push(b+a);
break;
case '-':
stk.push(b-a);
break;
case '*':
stk.push(b*a);
break;
case '/':
stk.push(b/a);
break;
}
i++;
}
}
if (stk.empty())
{
v.push_back(s[i]);
v.push_back(' ');
}
else if (s[i] == '(')
{
stk.push(s[i]);
}
else if (s[i] == ')')
{
while(stk.top() != '(')
{
v.push_back(stk.top());
v.push_back(' ');
{
int i = 0,num;
int len = s.size();
stack<int> stk;
while(i < len)
{
if (s[i] == ' ')
{
i++;
continue;
}
if (s[i] >= '0' && s[i] <= '9')
{
num = 0;
while(s[i] >= '0' && s[i] <= '9')
break;
case '+':
case '-':
return 1;
break;
case '*':
case '/':
return 2;
break;
default:
return -1;
break;
}
}
bool IsOperator(char op)//是否为运算符
{
if (op == '+' || op == '-' || op == '*' || op == '/')
v.push_back(' ');
stk.pop();
}
}
stk.push(s[i]);
}
i++;
}
while(!stk.empty())
{
v.push_back(stk.top());
v.push_back(' ');
stk.pop();
}
}
bool compute(vector<char> s,int &res)//计算后缀表达式的值
stk.pop();
}
stk.pop();
}
else if (IsOperator(s[i]))
{
if (!stk.empty())
{
while(!stk.empty() && priority(s[i]) <= priority(stk.top()))
{
v.push_back(stk.top());
return false;
res = stk.top(); stk.pop();
if (!stk.empty())
return false;
return true;
}
int main()
{
char s[100];
int res;
vector<char> v;
gets(s);
inTOpost(s,v);
输出
13
#include <iostream>
#include <stack>
#include <vector>
#include <string.h>
using namespace std;
int priority(char op)//运算符的优先级
{
switch(op)
{
case '(':
return 0;
{
num = num * 10 + s[i] - '0';
i++;
}
stk.push(num);
ty())
return false;
int a = stk.top(); stk.pop();
if (stk.empty())
return false;
int b = stk.top(); stk.pop();
{
return true;
}
return false;
}
void inTOpost(char s[],vector<char> &v)//转为后缀表达式
{
stack<char> stk;
int i = 0,len = strlen(s);
while(i < len)
{
if(s[i] >= '0' && s[i] <= '9')