后缀表达式求值

合集下载

计算后缀表达式的过程(C#)

计算后缀表达式的过程(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。

逻辑表达式短路求值后缀表达式

逻辑表达式短路求值后缀表达式

逻辑表达式短路求值后缀表达式逻辑表达式短路求值后缀表达式的过程如下:1. 将中缀逻辑表达式转换为后缀表达式。

这个过程可以使用运算符优先级和括号来确定运算符的顺序。

2. 执行后缀表达式的求值过程。

从左到右扫描后缀表达式:- 如果遇到操作数,将其压入栈中。

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

- 重复上述步骤,直到扫描完后缀表达式。

3. 最终栈中剩下的元素就是整个逻辑表达式的求值结果。

例如,对于逻辑表达式 "A && B || C",其后缀表达式为 "A B&& C ||"。

假设 A = true,B = false,C = true,那么短路求值的过程如下:1. 将 A 和 B 压入栈中。

2. 遇到 "&&" 操作符,从栈中弹出 B(false),然后从栈中弹出 A(true)。

将 A && B 的结果(false)压入栈中。

3. 将 C 压入栈中。

4. 遇到 "||" 操作符,从栈中弹出 C(true),然后从栈中弹出A &&B 的结果(false)。

将 (A && B) ||C 的结果(true)压入栈中。

5. 栈中剩下的元素是最终的结果,即 (A && B) || C 的值为 true。

因此,逻辑表达式 "A && B || C" 的短路求值后缀表达式的结果为 true。

后缀表达式求值过程

后缀表达式求值过程

后缀表达式求值过程嘿,朋友!今天咱们来唠唠后缀表达式求值这个超有趣的事儿。

你可能会想,这后缀表达式是啥呀?就像你看到一个神秘的密码,其实只要掌握了方法,求值就像解开密码锁一样简单又好玩。

我先给你说说啥是后缀表达式吧。

咱平常看到的表达式,像“3 + 4”这种中缀表达式,操作符在中间。

而后缀表达式呢,操作符在操作数的后面,就像“3 4 +”。

这看起来有点怪,可它在计算机处理起来可就方便多啦。

那怎么求值呢?咱得有个小工具,那就是栈。

栈就像一个小盒子,不过这个小盒子有点特别,先放进去的东西后拿出来,就像你往一个窄口瓶子里塞东西,先塞进去的在底下,最后才能拿出来。

比如说咱们要计算“4 5 * 6 +”这个后缀表达式的值。

我和我那聪明的小伙伴小明就开始啦。

小明负责操作栈,我来指挥。

首先看到“4”,小明就把4这个数字放到栈里。

这就像把一个小宝贝放进那个神秘的盒子里。

接着看到“5”,小明也把5放进栈里。

现在栈里就有4和5啦,就像两个小伙伴在盒子里安静地待着。

然后看到“*”这个操作符,这时候就像魔法要开始啦。

小明从栈里拿出5和4(注意哦,是先拿5,因为栈的特性),然后计算4乘以5等于20,再把20放进栈里。

哇,这就像把两个小伙伴融合成了一个超级小伙伴呢!再看到“6”,小明又把6放进栈里。

现在栈里有20和6啦。

最后看到“+”,小明又从栈里拿出6和20,计算20加6等于26,这就是最后的结果啦。

是不是感觉很神奇呢?就像一场奇妙的数学之旅。

再来看一个复杂点的例子吧。

像“3 4 + 2 * 5 -”。

我和我的另一个朋友小花来操作这个。

小花可认真啦。

先看到“3”,放进栈里,再看到“4”,也放进栈里。

看到“+”的时候,小花从栈里拿出4和3,计算3加4等于7,把7放进栈里。

这时候就像我们搭建了一个小积木塔的一部分。

接着看到“2”,放进栈里。

看到“*”的时候,小花从栈里拿出2和7,计算7乘以2等于14,再把14放进栈里。

最后看到“5”,放进栈里,看到“ - ”的时候,小花从栈里拿出5和14,计算14减5等于9。

C#算术表达式求值(后缀法),看这一篇就够了

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后缀表达式的求值与转换

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):在栈不为空的前提下(否则报错),读取栈顶的值,但是不把数据拿出去。

中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(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。

C语言实现中缀、后缀、前缀表达式_相互转化并求值

C语言实现中缀、后缀、前缀表达式_相互转化并求值

1.问题描述(1)表达式求值问题表达式是数据运算的基本形式。

人们的书写习惯是中缀式,如:11+22*(7-4)/3。

中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。

表达式还有后缀式(如:22 7 4 - * 3 / 11 +)和前缀式(如:+ 11 / * 22 – 7 4 3)。

后缀表达式和前缀表达式中没有括号,给计算带来方便。

如后缀式计算时按运算符出现的先后进行计算。

本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。

2.数据结构设计(1)表达式求值问题由于表达式中有字符与数字两种类型,故定义结点一个标志域data,标志结点存储的为字符data=2还是数字data=1,再寻找结点中对应的存储位置,读取数字域data1,字符域data2。

而在前缀表达式时,存在表达式逆序,因表达式类型不统一,用栈逆序极不方便,选择构建双向链表,存储表达式。

typedef struct Node //定义存储中缀表达式的结点类型{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2 //定义存储前缀表达式的结点类型{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;3.运行、测试与分析(1)表达式求值问题(1)按提示输入中缀表达式,如图1.1所示。

如输入中缀表达式不正确,提示输入有误,如图1.2,1.3所示。

图1.1图1.2图1.3(2)选择表达式转换并求值方式。

按“1”选择中缀表达式求值,如图1.4所示。

图1.4(3)按“2”选择中缀表达式转变为后缀表达式并求值,如图1.5所示。

图1.5(4)按“3”选择中缀表达式转变为前缀表达式并求值,如图1.6所示。

图1.6附录:源代码(1)表达式求值问题#include<stdio.h>#include<stdlib.h>#define MAXNUM 100typedef struct Node //定义存储中缀表达式的结点类型{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2 //定义存储前缀表达式的结点类型{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;typedef int selemtype1; //定义运算数栈的结点typedef struct //定义运算数栈的类型{selemtype1 *base;selemtype1 *top;}sqstack1;void InitStack1(sqstack1 &s) //新建一个空运算数栈{s.base=(selemtype1 *)malloc(MAXNUM*sizeof(selemtype1)); s.top=s.base;if(!s.base) printf("出错:申请空间失败!\n");}void Push1(sqstack1 &s,selemtype1 &e) //运算数栈,入栈:插入元素e为新的栈顶元素{ if(s.top-s.base>=MAXNUM)printf("出错:表达式过长!1\n");*s.top++ =e;}void GetTop1(sqstack1 s,selemtype1 &e) //运算数栈,用e返回栈顶元素{e=*(s.top-1);}void Popopnd1(sqstack1 &s,selemtype1 &e) //运算数栈,退栈:删除栈顶元素,并用e返回其值{e=*--s.top;}int stackempy1(sqstack1 s) //运算数栈,若为空栈返回1,否则返回0{if(s.top==s.base) return 1;else return 0;}typedef char selemtype2; //定义运算符栈的结点类型typedef struct //定义运算符栈类型{selemtype2 *base;selemtype2 *top;}sqstack2;void InitStack2(sqstack2 &s) //新建一个空运算符栈{s.base=(selemtype2 *)malloc(MAXNUM*sizeof(selemtype2));s.top=s.base;if(!s.base) printf("出错:申请空间失败!\n");}void Push2(sqstack2 &s,selemtype2 &e) //运算符栈,入栈:插入元素e为新的栈顶元素{ if(s.top-s.base>=MAXNUM)printf("出错:表达式过长!2\n");*s.top++ =e;}void GetTop2(sqstack2 s,selemtype2 &e) //运算符栈,用e返回栈顶元素{e=*(s.top-1);}void Popopnd2(sqstack2 &s,selemtype2 &e) //运算符栈,退栈:删除栈顶元素,并用e返回其值{e=*--s.top;}int stackempy2(sqstack2 s) //运算符栈,若为空栈返回1,否则返回0{if(s.top==s.base) return 1;else return 0;}void priority(char c,int &i) //确定运算符优先级{if (c=='*'||c=='/'||c=='%') i=2 ;else if (c=='+'||c=='-') i=1 ;else i=0;}int compare(char a,char b) //比较栈顶元素运算符与外部运算符优先级大小,外部优先级大则返回1,反之返回0{int in,out;priority(a,in);priority(b,out);if(out>in) return 1;else return 0;}void Operat(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num2);Popopnd1(OPND,num1);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}void Operatqianzhui(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num1);Popopnd1(OPND,num2);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}void houzhuiqiuzhi(Lnode *p,int &e) //后缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operat(OPND,OPTR);break;default:printf("结点有误");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void zhongzhui(Lnode *p) //中缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c,c2;Lnode *first;first=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(!stackempy2(OPTR)||p){while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else { switch(c){case '(': Push2(OPTR,c);break;case ')': GetTop2(OPTR,c2);while(c2!='('){Operat(OPND,OPTR);GetTop2(OPTR,c2);}Popopnd2(OPTR,c2);break;default: GetTop2(OPTR,c2);if(compare(c2,c)) Push2(OPTR,c); else { Operat(OPND,OPTR);Push2(OPTR,c);}break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR))Operat(OPND,OPTR);}Popopnd1(OPND,n);p=first->next;while(p){if(p->data==1) printf("%d ",p->data1);if(p->data==2) printf("%c",p->data2);p=p->next;}printf("=%d ",n);}void houzhui(Lnode *p) //中缀表达式转化为后缀表达式{sqstack2 OPTR; //运算符栈Lnode *r,*q,*head;int n;char c,c2;InitStack2(OPTR);p=p->next;q=(Lnode*)malloc(sizeof(struct Node));head=q;while(p){ switch(p->data){case 1:n=p->data1;r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=1;q->data1=n;break;case 2:c=p->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else { switch(c){ case '(': Push2(OPTR,c);break;case ')': Popopnd2(OPTR,c2);while(c2!='('){ r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;}q->next=NULL;q=head->next;while(q){if(q->data==1) printf("%d ",q->data1);if(q->data==2) printf("%c",q->data2);q=q->next;}houzhuiqiuzhi(head,n);printf("=%d ",n);}void qianzhuiqiuzhi(Lnode2 *p,int &e) //前缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;Lnode2 *head;head=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p!=head){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operatqianzhui(OPND,OPTR); break;default:printf("结点有误");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void qianzhui(Lnode *p) //中缀表达式转化为前缀表达式{sqstack2 OPTR; //运算符栈InitStack2(OPTR);int n;char c,c2;Lnode *first;Lnode2 *q,*head,*r,*head2,*s;first=p;p=p->next;q=(Lnode2*)malloc(sizeof(struct Node2)); //建立存中缀表达式的双向循环链表head=q;while(p){r=(Lnode2*)malloc(sizeof(struct Node2));q->next=r;r->prior=q;q=q->next;q->data=p->data;q->data1=p->data1;q->data2=p->data2;p=p->next;}q->next=head;head->prior=q;s=(Lnode2*)malloc(sizeof(struct Node2)); //建立存前缀表达式的双向循环链表head2=s;while(q!=head){switch(q->data){case 1:n=q->data1;r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=1;s->data1=n;break;case 2:c=q->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else{ GetTop2(OPTR,c2);if(c2==')') Push2(OPTR,c);else{ switch(c){ case ')':Push2(OPTR,c);break;case '(': Popopnd2(OPTR,c2);while(c2!=')'){ r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}}break;default:printf("结点有误");break;}q=q->prior;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;}s->next=head2;head2->prior=s;while(s!=head2){if(s->data==1) printf("%d ",s->data1); if(s->data==2) printf("%c",s->data2); s=s->prior;}qianzhuiqiuzhi(head2,n);printf("=%d ",n);}int main(){ char n[10];char c;int i,j,k,a,b,z,y,e;Lnode *p,*q,*first;i=0;e=1;a=0;b=1;z=0;y=0;p=(Lnode*)malloc(sizeof(struct Node));first=p;printf("请输入中缀表达式");do{ c = getchar();if('0'<=c&&c<='9'){ n[i]=c;i++;}else{ switch (c){ case '+':case '-':case '*':case '/':case '%':case '(':case ')':case '\n':{ if(n[0]>'0'&&n[0]<='9'){ q=(Lnode*)malloc(sizeof(struct Node)); p->next=q;p=p->next;for(k=0;k<i;k++){ for(j=0;j<=i-k-2;j++)e=e*10;a=a+(n[k]-'0')*e;e=1;n[k]='0';}p->data=1;p->data1=a;i=0;a=0;}if(c!='\n'){ if(p->data==2){ if(p->data2!=')'&&c!='(')b=0;}q=(Lnode*)malloc(sizeof(struct Node));p->next=q;p=p->next;p->data=2;p->data2=c;if(c=='(') z++;if(c==')') y++;}}default:if(c!='+'&&c!='-'&&c!='*'&&c!='/'&&c!='%'&&c!='\n'&&c!='('&&c!=')') b=0;}}}while (c != '\n');if(z!=y) b=0;p->next=NULL;if(b==0)printf("输入中缀表达式有误");else{printf("输入1中缀表达式求值,输入2后缀表达式求值,输入3前缀表达式求值");scanf("%d",&b);if(b==1) zhongzhui(first);if(b==2) houzhui(first);if(b==3) qianzhui(first);}return 1;}。

【转】中缀表达式转换为后缀表达式

【转】中缀表达式转换为后缀表达式

【转】中缀表达式转换为后缀表达式⼀、后缀表达式求值后缀表达式也叫逆波兰表达式,其求值过程可以⽤到栈来辅助存储。

假定待求值的后缀表达式为:6 5 2 3 + 8 * + 3 + *,则其求值过程如下:1)遍历表达式,遇到的数字⾸先放⼊栈中,此时栈如下所⽰:2)接着读到“+”,则弹出3和2,执⾏3+2,计算结果等于5,并将5压⼊到栈中。

3)读到8,将其直接放⼊栈中。

4)读到“*”,弹出8和5,执⾏8*5,并将结果40压⼊栈中。

⽽后过程类似,读到“+”,将40和5弹出,将40+5的结果45压⼊栈...以此类推。

最后求的值288。

⼆、中缀表达式转后缀表达式2.1)规则中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。

转换过程需要⽤到栈,具体过程如下:1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放⼊到栈中,遇到左括号时我们也将其放⼊栈中。

3)如果遇到⼀个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为⽌。

注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为⽌。

弹出完这些元素后,才将遇到的操作符压⼊到栈中。

有⼀点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

5)如果我们读到了输⼊的末尾,则将栈中所有元素依次弹出。

2.2)实例规则很多,还是⽤实例⽐较容易说清楚整个过程。

以上⾯的转换为例,输⼊为a + b * c + (d * e + f)*g,处理过程如下:1)⾸先读到a,直接输出。

2)读到“+”,将其放⼊到栈中。

3)读到b,直接输出。

此时栈和输出的情况如下:4)读到“*”,因为栈顶元素"+"优先级⽐" * " 低,所以将" * "直接压⼊栈中。

后缀表达式求值

后缀表达式求值
;Stack overflow!"<<endl;
exit(1);
}
top++;
stacklist[top]=item;
}
template<class T>
T Stack<T>::Pop()
{ T temp;
if(StackEmpty())
{
cerr<<"Attempt to pop an empty stack!"<<endl;
实际上,后缀表达式求值时,与数据类型有关系,所以使用模板来实现。
2
图2-1后缀表达式求值功能图
2.2 类的设计说明
图2-2 Stack类的完整表示
图2-3 Calculator类的完整表示
2.3 主要算法流程图
Y
N
N
N
N
Y
图2-4总体算法流程图
3
//这是一个标准的堆栈模板程序,因为使用模板,所以定义在一个文件里。
exit(1);
}
temp=stacklist[top];
top--;
return temp;
}
template<class T>
void Stack<T>::ClearStack(void)
{
top=-1;
}
template<class T>
T Stack<T>::Peek(void) const
result=GetTwoOperands(operand1,operand2); //若成功取到,则计算本次运算值,否则将栈清空
if(result==true)

数据结构中缀式中缀表达式改后缀表达式并求值

数据结构中缀式中缀表达式改后缀表达式并求值

《数据结构》课程设计报告课程设计题目:中缀表达式改后缀表达式并求值一. 实验目的·掌握栈的特征及基本操作,如入栈、出栈等,栈的顺序存储结构和链式存储结构的实现,以便在实际问题中灵活应用。

·掌握栈的典型应用——中缀表达式转后缀表达式,并利用后缀表达式求值。

二. 实验内容(一)中缀表达式转后缀表达式的方法:1.遇到操作数:直接输出(添加到后缀表达式中)2.栈为空时,遇到运算符,直接入栈3.遇到左括号:将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。

5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈6.最终将栈中的元素依次出栈,输出。

(二)三. 实验分析程序源码(要求对每个函数及主要代码加上注释语句),源码出处。

//// main.c// 后缀表达式求值//// Created by 颜彦闻on 14/12/2.// Copyright (c) 2014年颜彦闻. All rights reserved.//#include <stdio.h>#include <stdlib.h>#define StackSize 100#define QueueSize 100typedef char DataType;typedef struct{char data[100];int front,rear;}SeqQueue; //定义队列类型void InitQueue(SeqQueue *Q) //初始化队列{Q->front=0;Q->rear=0;}int QueueEmpty(SeqQueue Q) //判空{return Q.rear==Q.front;}void EnQueue(SeqQueue *Q,DataType x) //元素入队列函数{if((Q->rear+1)%QueueSize==Q->front)printf("Queue overflow");else{Q->data[Q->rear]=x;Q->rear=(Q->rear+1)%QueueSize;}}DataType DeQueue(SeqQueue *Q){char x;if(QueueEmpty(*Q))return0;else{x=Q->data[Q->front];Q->front=(Q->front+1)%QueueSize;return x;}}//栈的相关操作typedef struct{DataType data[100];int top;}SeqStack;void InitStack(SeqStack *S) //栈的初始化{S->top=-1;}void Push(SeqStack *S,DataType x) //进栈函数{if(S->top==StackSize-1)printf("stack overflow");else{S->top=S->top+1;S->data[S->top]=x;}}DataType Pop(SeqStack *S) //退栈顶指针函数{if(S->top==-1){printf("stack underflow");return0;}elsereturn S->data[S->top--];}DataType GetTop(SeqStack S) //取栈顶元素{if(S.top==-1){printf("stack empty");return0;}elsereturn S.data[S.top];}int Priority(DataType op) //求运算符优先级函数{switch(op){case'(':case'#':return0;case'-':case'+':return1;case'*':case'/':return2;}return -1;}void CTPostExp(SeqQueue *Q){SeqStack S;char c,t;InitStack(& S);Push(&S,'#');do{c=getchar();switch(c){case' ':break;case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':EnQueue(Q ,c);break;case'(':Push(&S,c);break;case')':case'#':{do{t=Pop(&S);if(t!='('&&t!='#')EnQueue(Q ,t);}while(t!='('&&S.top!=-1);break;}case'+':case'-':case'*':case'/':while(Priority(c)<=Priority(GetTop(S))){t=Pop(&S);EnQueue(Q,t);}Push(&S,c);break;}}while(c!='#');}DataType CPostExp(SeqQueue Q){SeqStack S;char ch;int x,y;InitStack(&S);while(!QueueEmpty(Q)){ch=DeQueue(&Q);if(ch>='0'&&ch<='9')Push(&S,ch);else{y=Pop(&S)-'0';x=Pop(&S)-'0';switch(ch){case'+': Push(&S,(char)(x+y+'0'));break;case'-': Push(&S,(char)(x-y+'0'));break;case'*': Push(&S,(char)(x*y+'0'));break;case'/': Push(&S,(char)(x/y+'0'));break;}}}return GetTop(S);}int main(int argc, char *argv[]){SeqQueue Q;InitQueue(&Q);printf("输入表达式:\n");CTPostExp(&Q);printf("结果:%c\n",CPostExp(Q));printf("后缀表达式:");while(!QueueEmpty(Q))printf("%2c",DeQueue(&Q));printf("\n");system("PAUSE");return0;}四. 算法时间复杂度。

后缀算术表达式求值

后缀算术表达式求值

实验名称:后缀算术表达式求值背景描述:表达式求值是程序设计语言编译中的一个最基本的问题。

因为任何程序设计语言都必须具有表达式求值的功能,同时表达式的计算应用也相当广泛,比如电力调度系统中的计算遥测、车站票务系统中的票价类型计算公式等。

通常,我们所说的表达式是由运算符、操作数、界限符所组成。

而算术表达式中最常见的表示法形式有中缀、前缀和后缀表示法。

中缀表示法是书写表达式的常见方式,而前缀和后缀表示法主要用于计算机科学领域。

一、表达式表示法1、中缀表达式---将运算符放在两操作数的中间。

在运算中存在运算符的优先权与结合性的问题。

例如运算:a*b+(c-d/e)*f 时,编译器即自左向右逐一检查,当检查到第一个运算符"*"时还无法知道是否执行;待检查到第二个运算符" + "时,因为知道"*"的优先级别高于" + "时,才知道执行"a*b";当继续检查到" ( "时,可知道先执行括号以内部分等。

2、前缀表达式---将运算符放在两操作数的前面。

这种表示法经常用于计算机科学,特别是编译器设计方面。

为纪念其发明家-Jan Lukasiewicz,这种表示法也称波兰表示法。

3、后缀表达式---将运算符放在两操作数的后面。

后缀表达式也称逆波兰表达式,因其使表达式求值变得轻松,所以被普遍使用。

前缀和后缀表示法有三项公共特征:(1)操作数的顺序与等价的中缀表达式中操作数的顺序一致;(2)不需要括号;(3)操作符的优先级不相关。

问题描述:读入一个后缀表达式表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。

输入输出格式:第一种方式:输入:在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。

以"#"表示结束。

输出:如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示。

后缀表达式把每个运算符移到它的两个运算对象的后面汇总

后缀表达式把每个运算符移到它的两个运算对象的后面汇总
例2:后缀表达式的求值 后缀表达式:把每个运算符移到它的两个运 算对象的后面,删除所有括号。 中缀表达式 3/5+6 16 – 9 * ( 4 + 3 ) 2 * ( x + y ) / ( 1- x ) 后缀表达式 35/6+ 16 9 4 3 + * – 2 x y + * 1 x - /
分析:栈S用来存放原始数据、中间结果和最终结 果。将后缀表达式以@结束存入字符数组,且每个 数据后面加一个空格。扫描中,数据入栈,遇到运 算符,就依次弹出两个操作数进行运算,运算结果 入栈。遇到字符@结束,栈顶的值就是算式的结果。
function pop(var s:stack): real;{出栈} begin pop:=s.data[s.top]; s.top:=s.top -1; end;
程序:
procedure push(var s:stack;x:real); {入栈} begin s.top:=s.top+1; s.data[s.top]:=x end; begin {主程序} i:=0; repeat i:=i+1; read(a[i]); {将表达式存入数组a} until a[i]=’@’; s.top:=0; {清空栈} i:=1; {i为a数组的下标} ch:=a[i];
后缀表达式16 9 4 3 + * – 在字符数组A中的形式为:
gram p2(input,output); type stack=record data:array[1 . . 100] of real;{存放实型数} top:0 . . 100; end; var s:stack;ch:char;i:integer;x:real; a:array[1..30] of char;

C语言后缀表达式计算

C语言后缀表达式计算

一、设计思想计算算数表达式并求值,采取的共有两种方法:1.先将算数表达式转化为后缀表达式,然后对后缀表达式进行计算。

2.对算数表达式进行直接的计算。

第一种算法这种解决方案又分为两步:1.将表达式先转化为后缀表达式的字符串数组2.利用后缀表达式进行计算在转化过程中,第一,建立一个存符号的栈,和一个字符串数组,用来存放转化以后的表达式然后,对于得到的用户输入的字符串进行逐个的扫描,如果是数组或者小数点,则直接存放到数组中,并且在后面加入一个分隔符,如果是操作符,则和栈中的已存的进行比较,如果比栈中的操作符的优先级高,则直接入栈,如果优先级低或相等,则栈中元素出栈,存到字符串中,然后再次检查栈顶,直到栈中元素的优先级低于扫描操作符,则此操作符入栈,然后扫描下一个字符,直到遇到字符串的结束符号\0,扫描结束。

数组中存的就是后缀表达式。

得到后缀表达式后,进行计算,要用到数值栈。

首先要将字符表示的数字转化为浮点小数,然后进行扫描,遇到数值,放入栈中,遇到操作符,就从栈中取出两个数,进行计算后再放入栈中,扫描下一个,最后的计算结果就存到了栈中,直接取出栈内元素,就是计算的最后结果。

第二种算发首先要建立两个栈,一个用来存放操作符,一个用来存放数值。

开始对用户输入的字符串进行扫描,如果是数字字符或者小数点,则将字符转化为浮点数存到数栈里,如果是操作符,则观察符号栈,如果栈顶元素的优先级低于观察的操作符,则操作符入栈,如果栈顶元素的优先级高于或者等于观察的操作符,则从数值栈中取出两个浮点数,从符号栈中取出栈顶的操作符,然后进行相应的数值计算,所得的结果再存到数值栈中,重复这样的操作,直到符号栈中栈顶元素的优先级低于观察的操作符,则此操作符入栈,然后对下一个字符进行扫描。

如果是左括号,则不进行优先级的比较,直接入栈,入栈后优先级为-1。

如果是右括号,则从数值栈中取两个操作数,符号栈中取出一个符号,然后进行计算后得数放入数栈中,不断进行此类操作,直到从栈中取出的是左括号为止,左括号去掉,扫描下一个。

后缀表达式求值

后缀表达式求值

数据结构实验报告知识范畴:栈与队列完成日期:2017年4月03日实验题目:后缀表达式求值实验内容及要求:从键盘输入后缀表达式(运算符和操作数建议以字符串形式输入,空格作为分隔符),计算并输出后缀表达式的求值结果。

基本要求:实现 +, -, *, /四个二元运算符;实现+, -两个一元运算符(即正、负号);操作数用整数表示。

提高要求:输出对应的前缀表达式。

每位同学可必须实现基本要求,可选择实现提高要求;程序可不处理表达式语法错误。

实验目的:掌握堆栈在表达式求值中的应用。

数据结构设计简要描述:序言:这是本学期第三个实验,这个实验比较的基本要求是要我们求出一个已经按后缀表达式形式输入的值,除了之前的堆栈部分,新增了一部分就是判断操作数和运算符,并将操作数入栈,将运算符进行对应的操作数功能实现,并将结果入栈。

数据结构简要设计:本实验主要可分为两个大的模块,一个是堆栈操作,另外一个就是后缀表达式求值操作。

堆栈操作:用结构体类型名来创建用于保存操作数的堆栈,并实现判断栈空、栈满、栈初始化、入栈以及退栈等操作;后缀表达式求值操作:用string类型定义一个字符串,并对其进行判断,是操作数就入栈,是运算符就进行运算,并保存结果。

算法设计简要描述:后缀表达式求值算法:用string类型定义一个字符串,并用一个switch来实现运算符的操作和操作数的入栈,再用一个while来进行循环遍历整个字符串,直到字符串的末尾为止。

最后将算得最终结果退栈,并打印到屏幕上即可。

输入/输出设计简要描述:输入:从键盘上输入一个已经排好序的后缀表达式,如12-82-74-/*输出:屏幕上将输出后缀表达式的值,如上面表达式的值为6编程语言说明:1,编程软件,CodeBlocks 16.0;2,代码均用C++语言实现;3,输入输出采用C++语言的cout和cin函数;4,程序注释采用C/C++规范;主要函数说明:void InitStack(Stack *s);//栈的初始化int EmptyStack(Stack *s);//判断栈空int full(Stack *s);//判断栈满int push(Stack *s,elemtype x);//入栈操作int pop(Stack *s,elemtype &x);//退栈操作int result(string s);//后缀表达式求值程序测试简要报告:见截图:1,2,源程序代码:#include<iostream>#include<malloc.h>using namespace std;typedef int elemtype;//整数型数据类型typedef struct{elemtype *elem;int length;int top;} Stack;//函数声明void InitStack(Stack *s);//栈的初始化int EmptyStack(Stack *s);//判断栈空int full(Stack *s);//判断栈满int push(Stack *s,elemtype x);//入栈操作int pop(Stack *s,elemtype &x);//退栈操作int result(string s);//后缀表达式求值//函数具体实现//顺序存储的栈结构,以及其相应算法void InitStack(Stack *s){s->length = 100;s->elem = (elemtype *)malloc((sizeof(elemtype)*s->length));s->top = -1;}//判断栈是否为空int EmptyStack(Stack *s){return s->top == -1;}//判断栈满int full(Stack *s){return s->top>=s->length-1;}//入栈int push(Stack *s,elemtype x){if(full(s)){return 0;}s->elem[++s->top] = x;return 1;}//退栈int pop(Stack *s,elemtype &x){if(EmptyStack(s)){return 0;}x = s->elem[s->top--];return 1;}//后缀表达式求值函数int result(string s){int Result;//定义一个保存输出结果的值Stack *p;//建栈p = (Stack *)malloc(sizeof(Stack));//为新建的栈分配内存空间InitStack(p);//初始化刚建的栈,这一步不进行的话,入栈将不能进行,之前这个问题将我难到了好久int i = 0;//定义一个字符串下标,用来循环判断字符串中的内容elemtype a,b,d;//定义三个elemtype类型变量,用来进行操作数的实现while(1){if(i>s.length()-1)break;switch(s[i]){case '+'://加号则退两个,并相加将结果保存在栈中 pop(p,a);pop(p,b);d = a + b;push(p,d);break;case '-'://加号则退两个,并相减将结果保存在栈中 pop(p,a);pop(p,b);d = b - a;push(p,d);break;case '*'://加号则退两个,并相乘将结果保存在栈中 pop(p,a);pop(p,b);d = a*b;push(p,d);break;case '/'://加号则退两个,并相除结果保存在栈中 pop(p,a);pop(p,b);d = b/a;push(p,d);break;default://是数字就转换为数字后入栈 d = s[i] - '0';push(p,d);break;}i++;//字符串自增一进行遍历}pop(p,Result);//将计算后的结果退栈cout<<Result<<endl;//输出最后的结果return 0;}int main(){string s;cout<<"请输入一个后缀表达式:\n";cin>>s;cout<<"后缀表达式的值为:\n";result(s);return 0;}。

表达式求值(后缀表达式求值)

表达式求值(后缀表达式求值)

表达式求值(后缀表达式求值)表达式求值时间限制:3000 ms | 内存限制:65535 KB难度:4描述ACM队的mdd想做⼀个计算器,但是,他要做的不仅仅是⼀计算⼀个A+B的计算器,他想实现随便输⼊⼀个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。

⽐如输⼊:“1+2/4=”,程序就输出1.50(结果保留两位⼩数)输⼊第⼀⾏输⼊⼀个整数n,共有n组测试数据(n<10)。

每组测试数据只有⼀⾏,是⼀个长度不超过1000的字符串,表⽰这个运算式,每个运算式都是以“=”结束。

这个表达式⾥只包含+-*/与⼩括号这⼏种符号。

其中⼩括号可以嵌套使⽤。

数据保证输⼊的操作数中不会出现负数。

数据保证除数不会为0输出每组都输出该组运算式的运算结果,输出结果保留两位⼩数。

样例输⼊21.000+2/4=((1+2)*5+1)/4=样例输出1.504.00题解:求后缀表达式,⽤后缀表达式,求解;AC代码:#include<cstdio>#include<iostream>#include<cmath>#include<algorithm>#include<cstring>#include<queue>#include<stack>using namespace std;const int INF=0x3f3f3f3f;#define mem(x,y) memset(x,y,sizeof(x))#define SI(x) scanf("%d",&x)#define PI(x) printf("%d",x)typedef long long LL;const int MAXN=1010;char s[MAXN];char work(char a,char b){if(a=='#')return'<';if(a=='+'||a=='-'){if(b=='*'||b=='/'||b=='(')return'<';else return'>';}if(a=='*'||a=='/'){if(b=='(')return'<';else return'>';}if(a=='('||a=='='){if( (a=='('&&b==')')||(a=='='&&b=='=') ) return'=';else return'<';}}int main(){int T;SI(T);while(T--){double temp,p,a,b;scanf("%s",s);stack<char>S;stack<double>s2;S.push('#');for(int i=0;s[i];){// printf("%c\n",s[i]);if(isdigit(s[i])||s[i]=='.'){temp=0,p=10;while(isdigit(s[i])||s[i]=='.'){if(s[i]=='.'){p=0.1;i++;continue;}if(p==10)temp=temp*p+s[i]-'0';else temp=temp+(s[i]-'0')*p,p*=0.1;i++;}// printf("%lf\n",temp);s2.push(temp);}//s2.push(s[i++]);else{switch(work(S.top(),s[i])){case'<':S.push(s[i]);i++;break;case'>':a=s2.top();s2.pop();b=s2.top();s2.pop();if(S.top()=='+')s2.push(a+b);else if(S.top()=='-')s2.push(b-a);else if(S.top()=='*')s2.push(a*b);else s2.push(b/a);//printf("%lf\n",s2.top());S.pop();break;case'=':S.pop();i++;break;}}}//printf("%d %d %lf\n",S.size(),s2.size(),s2.top()); printf("%.2lf\n",s2.top());}return0;}。

实验3 后缀表达式求值

实验3 后缀表达式求值

1、实验题目(1)掌握栈“后进先出”的特点。

(2)掌握栈的典型应用——后缀表达式求值。

2、实验内容(1)用键盘输入一个整数后缀表达式(操作数的范围是0~9,运算符只含+、-、*、/,而且中间不可以有空格),使用循环程序从左向右读入表达式。

(2)如果读入的是操作数,直接进入操作数栈。

(3)如果读入的是运算符,立即从操作数栈取出所需的操作数,计算操作数运算的值,并将计算结果存回操作数栈。

(4)检验程序运行结果。

3、实验要求(1)分析后缀表达式求值的算法思想,用C(或C++)语言设计程序。

(2)上机调试通过实验程序。

(3)给出具体的算法分析,包括时间复杂度和空间复杂度。

(4)撰写实验报告。

(5)本程序调试通过以后,添加到原教材验证性实验3的菜单中去。

4、实验步骤与源程序⑴实验步骤1、首先进行栈结构声明struct node,包含 data,*next。

2、然后分别编写进栈,出栈程序:link push,link pop;3、编写主函数。

#include<stdio.h>#define Maxlen 88typedef struct{ char data[Maxlen];int top;}opstack;typedef struct{ float data[Maxlen];int top;}stack;void trans(char str[],char exp[]) // 求后缀表达式{ opstack op;char ch;int i=0,t=0;op.top=-1;ch=str[i];i++;while(ch!='\0'){ switch(ch){ case'(':op.top++;op.data[op.top]=ch;break;case')':while(op.data[op.top]!='('){ exp[t]=op.data[op.top];op.top--;t++;}op.top--;break;case'+':case'-':while(op.top!=-1 && op.data[op.top]!='(') { exp[t]=op.data[op.top];op.top--;t++;}op.top++;op.data[op.top]=ch;break;case'*':case'/':while(op.top=='/'||op.top=='*'){ exp[t]=op.data[op.top];op.top--;t++;}op.top++;op.data[op.top]=ch;break;case' ': // 输入为空格,则跳过 break;default:while(ch>='0' && ch<='9'){ exp[t]=ch;t++;ch=str[i];i++;}i--;exp[t]=' ';t++;}ch=str[i];i++;}while(op.top!=-1){ exp[t]=op.data[op.top];t++;op.top--;}exp[t]='\0';}float compvalue(char exp[]) // 后缀表达式求值{ stack st;float d;char ch;int t=0;st.top=-1;ch=exp[t++];while(ch!='\0'){ switch(ch){ case'+':st.data[st.top-1]=st.data[st.top-1]+st.data[st.top]; st.top--;break;case'-':st.data[st.top-1]=st.data[st.top-1]-st.data[st.top]; st.top--;break;case'*':st.data[st.top-1]=st.data[st.top-1]*st.data[st.top]; st.top--;break;case'/':if(st.data[st.top]!=0){ st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];st.top--;}elseprintf("\n\t 表达式中有除数为零,本次计算无效!\n ");break;default:if(ch>='0' && ch<='9'){d=ch-'0';st.top++;st.data[st.top]=d;}}ch=exp[t++];}return st.data[st.top];}int main(){char str[Maxlen],exps[Maxlen];printf("\n请输入一个整数算术(只包含+,-,*,/和括号)表达式: ");gets(str);printf("\n原算术表达式为: %s\n",str);trans(str,exps);printf("\n其后缀表达式为: %s\n",exps);printf("\n其运算的结果为: %g\n\n",compvalue(exps));}5、测试数据与实验结果输入一个整数算数表达式,运算符只含+、-、*、/,而且中间不可以有空格,表达式及结果如下截图所示:6、结果分析与实验体会结果分析:由实验可知此程序需实现用键盘输入一个整数后缀表达式(操作数的范围是0~9,运算符只含+、-、*、/,而且中间不可以有空格),使用循环程序从左向右读入表达式。

后缀表达式求值

后缀表达式求值

后缀表达式求值任务描述本关任务:熟练掌握STL模板库中栈stack的基本操作,并利⽤栈实现后缀表达式求解。

相关知识为了完成本关任务,你需要掌握:1.后缀表达式求解。

后缀表达式求解算法思想:从左⾄右扫描表达式,遇到数字时,将数字压⼊栈,遇到运算符时,弹出栈顶的两个数,⽤运算符对它们做相应的计算(次顶元素 - 运算符 - 栈顶元素),并将结果⼊栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。

例如后缀表达式2 1 3 + * 4 -:编程要求本关的编程任务是补全右侧代码⽚段main中Begin⾄End中间的代码,具体要求如下:读取后缀表达式,并基于栈的插⼊、删除等基本操作实现后缀表达式求解,表达式中所有的操作数为单⼀的数字:0~9,运算符仅包含:+ -* ( )。

输⼊输出说明本任务的输⼊为单个测试⽤例,输⼊长度不超过100,且操作数仅为0~9之间的整数,操作符只包含“+-*/”等算数运算符的中缀表达式,输出为该中缀表达式的计算结果。

以下是平台的测试样例:测试输⼊:123+4*+5- 预期输出:16输⼊格式:后缀表达式输出格式:运算结果,末尾换⾏\n#include<iostream>#include<stack>#include<string.h>#include<string>using namespace std;int main() {string s;cin>>s;stack<int>st;for(int i=0;i<s.size();i++){if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){int num1=st.top();st.pop();int num2=st.top();st.pop();if(s[i]=='+')st.push(num2+num1);if(s[i]=='-')st.push(num2-num1);if(s[i]=='*')st.push(num2*num1);if(s[i]=='/')st.push(num2/num1);}else{char ch=s[i];string s2;char s1[2]={ch,0};s2=s1;st.push(stoi(s2));}}cout<<st.top();}。

实验二 后缀表达式求值

实验二 后缀表达式求值

韶关学院
学生实验报告册
实验课程名称:数据结构与算法
实验项目名称:实验二后缀表达式求值
实验类型(打√):(基础、综合、设计√)
院系:计算机科学学院专业:计算机科学技术姓名:*** 学号:*****
指导老师:***
韶关学院教务处编制
一、实验预习报告内容
二、实验原始(数据)记录
实验时间:2011 年9 月21 日(星期三第7,8 节)
实验同组人:
【程序运行结果】
通过分析输入数据和运行结果,证明程序顺利完成实验内容和要求。

指导教师
批阅及签名签名:年月日
三、实验报告内容
2011年9 月21 日
注:1、如有个别实验的实验报告内容多,实验报告册页面不够写,或有识图,画图要求的,学生应根据实验指导老师要求另附相同规格的纸张并粘贴在相应的“实验报告册”中。

2、实验报告册属教学运行材料,院系(中心)应按有关规定归档保管。

后缀式求值——精选推荐

后缀式求值——精选推荐

后缀式求值# include <stdio.h># include <string.h>struct node{int top;int a[1000];}p;int main(){char ch[100];gets(ch);p.top=0;for(int i=0 ; ch[i]!='#' ;i++){if(ch[i]>='0' && ch[i]<='9')p.a[p.top++]=ch[i]-48;else if(ch[i] == '*'){p.a[p.top-2]=p.a[p.top-1]*p.a[p.top-2];p.top=p.top-1;}else if(ch[i] == '/'){p.a[p.top-2]=p.a[p.top-2]/p.a[p.top-1];p.top=p.top-1;}else if(ch[i] == '+'){p.a[p.top-2]=p.a[p.top-1]+p.a[p.top-2];p.top=p.top-1;}else if(ch[i] == '-'){p.a[p.top-2]=p.a[p.top-2]-p.a[p.top-1];p.top=p.top-1;}}printf("%d\n",p.a[--p.top]);return0;}View Code算法解释:1 后缀表达式的求值将中缀表达式转换成等价的后缀表达式后,求值时,不需要再考虑运算符的优先级,只需从左到右扫描⼀遍后缀表达式即可。

具体求值步骤为:从左到右扫描后缀表达式,遇到运算符就把表达式中该运算符前⾯两个操作数取出并运算,然后把结果带回后缀表达式;继续扫描直到后缀表达式最后⼀个表达式。

例如,后缀表达式(abc*+def*/-) 的求值2 后缀表达式的求值的算法设置⼀个栈,开始时,栈为空,然后从左到右扫描后缀表达式,若遇操作数,则进栈;若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,运算后的结果再进栈,直到后缀表达式扫描完毕。

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

一、设计思想
首先,将中缀表达式转换为后缀表达式。

转换算法思路:设中缀表达式已存入数组E[n];由于后缀表达式中操作数的次序与中缀表达式一致,故扫描到中缀表达式操作数时直接输出到B[n]即可;对于运算符,视其优先级别,优先级高的运算符先输出;设一存放运算符的栈s,先将s置空;依次扫描E[n]中各分量E[i]送x:
若x=“”(结束符),依次输出栈s中运算符,转换结束;
若x=操作数,直接输出x到B[n]中;
若x=‘)’,反复退栈输出栈s中子表达式运算符,直到栈顶符=‘(’,并退掉栈顶的‘(’;
若x=操作符,反复退栈输出栈s中运算符,直到栈顶符<X为止。

然后,对后缀表达式求值:定义一个栈s,用来存放后缀表达式的中间计算结果和操作数。

设B[n]存放后缀表达式,栈s存放操作数,依次扫描B[n]中各分量B[i]送x:若x=操作数,直接进栈;
若x=运算符,出栈:b=pop(s),a=pop(s),做a、b关于x的运算,结果在进栈;
若x=“”,算法结束,输出栈顶,即表达式的结果。

二、算法流程图
后缀表达式求值算法流程图简单说明:
先将中缀表达式转换为后缀表达式:如果是数字,则直接进入后缀表达式数组,如果是操作符,比较操作符跟栈顶元素的优先级,如果大于栈顶,则直接入后缀表达式数组里,如果小于则将弹栈,直到栈顶元素的优先级小于读取的操作符。

如果是(,直接进入栈,如果是),将弹栈,直到遇到(为止。

三、源代码
下面给出的是用后缀表达式求值算法实现的程序的源代码:
#include<stdio.h>
#include<malloc.h>
#define MaxSize 50
struct
{
char data[MaxSize];
int top;
} op;//定义栈;
struct
{
float data[MaxSize];
int top;
} st;
//中缀转换为后缀
void trans(char*exp,char*postexp)
{
int i=0;
op.top=-1;
while(*exp!='\0')
{
switch(*exp)
{
case'(':
op.top++;op.data[op.top]=*exp;
exp++;break;
case')':
while(op.data[op.top]!='(')
{
postexp[i++]=op.data[op.top];
op.top--;
}
op.top--;exp++;break;
case'+':
case'-':
while(op.top!=-1&&op.data[op.top]!='(')
{
postexp[i++]=op.data[op.top];
op.top--;
}
op.top++;op.data[op.top]=*exp;exp++;break;
case'*':
case'/':
while(op.data[op.top]=='*'||op.data[op.top]=='/')
{
postexp[i++]=op.data[op.top];
op.top--;
}
op.top++;op.data[op.top]=*exp;exp++;break;
case' ':break;
default:
while(*exp>='0'&&*exp<='9')
{
postexp[i++]=*exp;
exp++;
}
postexp[i++]='#';
}
}
while(op.top!=-1)
{
postexp[i++]=op.data[op.top];
op.top--;
}
postexp[i]='\0';
}
//进行运算
float compvalue(char*postexp)
{
float a,b,c,d;
st.top=-1;
while(*postexp!='\0')
{
switch(*postexp)
{
case'+':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
c=b+a;
st.top++;
st.data[st.top]=c;
break;
case'-':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
c=b-a;
st.top++;
st.data[st.top]=c;
break;
case'*':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
c=b*a;
st.top++;
st.data[st.top]=c;
break;
case'/':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
if(a!=0)
{
c=b/a;
st.top++;
st.data[st.top]=c;
}
else
{
printf("\n\t除零错误!\n");
}
break;
default:
d=0;
while(*postexp>='0'&&*postexp<='9')
{
d=10*d+*postexp-'0';
postexp++;
}
st.top++;
st.data[st.top]=d;
break;
}
postexp++;
}
return st.data[st.top];
}
int main()
{
char exp[MaxSize],postexp[MaxSize];
printf("输入表达式,回车符结束;");
while(scanf("%s",&exp)!=EOF)
{
trans(exp,postexp);
printf("zhongzhuibiaodashi: %s\n",exp);
printf("houzuibiaodashi: %s\n",postexp);
printf("zhi: %g\n",compvalue(postexp));
}
}。

相关文档
最新文档