数据结构实验报告 逆波兰表达式

合集下载

逆波兰表达式、波兰表达式【数据结构与算法】

逆波兰表达式、波兰表达式【数据结构与算法】

逆波兰表达式、波兰表达式【数据结构与算法】逆波兰表达式、波兰表达式【数据结构与算法】1.前缀表达式⼜称波兰式,前缀表达式的运算符位于操作数之前。

⽐如:- × + 3 4 5 62.中缀表达式就是常见的运算表达式,如(3+4)×5-63.后缀表达式⼜称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后,⽐如:3 4 + 5 × 6 -⼈类最熟悉的⼀种表达式1+2,(1+2)3,3+42+4等都是中缀表⽰法。

对于⼈们来说,也是最直观的⼀种求值⽅式,先算括号⾥的,然后算乘除,最后算加减,但是,计算机处理中缀表达式却并不⽅便。

然后我们还需明确⼀些概念,下⾯通过我们最熟悉的中缀表达式画出⼀棵语法树来直观认识⼀下前后缀表达式的⽣成。

以A+B*(C-D)-E*F为例:中缀表达式得名于它是由相应的语法树的中序遍历的结果得到的。

上⾯的⼆叉树中序遍历的结果就是A+B*(C-D)-E*F。

前缀表达式是由相应的语法树的前序遍历的结果得到的。

上图的前缀表达式为- + A * B - C D * E F后缀表达式⼜叫做逆波兰式。

它是由相应的语法树的后序遍历的结果得到的。

上图的后缀表达式为:A B C D - * + E F * -下⾯我们关注两个点:1.如何根据⼀个逆波兰表达式求出运算结果?2.如果将⼀个中缀表达式转换成后缀表达式(逆波兰表达式)⼀.通过逆波兰表达式计算结果我们先看⼀个例⼦...后缀表达式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,由此得出最终结果。

从上⾯的过程我们如何编写代码实现呢?可以采⽤⼀个辅助的栈来实现计算,扫描表达式从左往右进⾏,如果扫描到数值,则压进辅助栈中,如果扫描到运算符,则从辅助栈中弹出两个数值参与运算,并将结果压进到栈中,当扫描表达式结束后,栈顶的数值就是表达式结果。

逆波兰表达式求值实验报告湖大

逆波兰表达式求值实验报告湖大

HUNAN UNIVERSITY 课程实习报告题目:逆波兰表达式求值学生姓名范舜奕学生学号20100820608专业班级通信6班指导老师吴帆完成日期 2012.04. 07实验二逆波兰表达式求值★问题描述选一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确★基本要求(1)从键盘中输入一个后缀表达式,该表达式包括加减乘除的操作符,一级正整数作为操作数等(2)用堆栈来表示★输入输出格式输入:在字符界面上输入一个后缀表达式,其中两相邻操作数之间利用空格隔开。

以“#”表示结束。

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

如果不正确,请在字符界面上输出表达式错误提示★测试用例输入:2 3 * 1 -#输出:5★设计思路◆为了测试需要,应以浮点数存储输入和输出,利用堆栈来实现算法。

栈的抽象数据类型的定义如下:ADT Stack {数据对象:D={a i| a i∈ElemSet, i=1,2,...,n, n≥0 }数据关系:R={<a i-1 , a i >| a i-1 ,a i∈D, i=2,...,n}基本操作:InitStack(&S)操作结果:构造一个空栈SDestoryStack(&S)初始条件:栈S已存在操作结果:栈S被销毁Pop(&S,e)初始条件:栈S已存在且非空操作结果:删除S的栈顶元素,并用e返回其值Push(&S,e)初始条件:栈S存在且非空操作结果:插入元素e为新的栈顶元素StackLength(&S)初始条件:栈S已存在操作结果:返回S的元素的个数,即栈的长度} ADT LinkLiSt◆本程序包含三个基本模块(1)主程序模块:元素进栈、出栈、删除栈顶元素、实现数字元素的运算(2)线性表模块:实现栈的抽象数据类型(3)元素结构单元模块:定义栈每个元素的结构◆算法的基本思想:定义堆栈的抽象数据类型,读取键盘上输入的数据,根据读取的输入调用入栈函数,判断输入的数据是否合法,通过switch_case结构判断输入运算符的种类,转而执行不同的处理代码。

实验三 逆波兰表达式的产生及计算

实验三 逆波兰表达式的产生及计算

实验三逆波兰表达式的产生及计算一、实验目的非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。

二、实验内容将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。

三、逆波兰表达式的产生及计算实验设计思想及算法◆逆波兰式定义将运算对象写在前面,而把运算符号写在后面。

用这种表示法表示的表达式也称做后缀式。

逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。

◆产生逆波兰式的前提中缀算术表达式◆逆波兰式生成的设计思想及算法(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)读入一个用逆波兰式表示的简单算术表达式。

数据结构课程实验报告_实验7优先队列

数据结构课程实验报告_实验7优先队列

HUNAN UNIVERSITY课程实习报告题目:逆波兰表达式问题优先队列与堆学生姓名学生学号指导老师完成日期2015-5-9逆波兰表达式问题实验背景在工资管理软件中,不可避免的要用到公式的定义及求值等问题。

对于数学表达式的计算,虽然可以直接对表达式进行扫描并按照优先级逐步计算,但也可以将中缀表达式转换为逆波兰表达式,这样更容易处理。

基本要求使用二叉树来实现。

实现提示利用二叉树后序遍历来实现表达式的转换,同时可以使用实验3的结果来求解后缀表达式的值。

输入输出格式:输入:在字符界面上输入一个中缀表达式,回车表示结束。

输出:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。

测试用例输入:21+23*(12-6)输出:21 23 12 6 -*+源代码:#include<iostream>#include<string>#include<iomanip>using namespace std;char str[100][15];//由于一个数字可能有多个数字组成int search_1(int start,int end)//寻找优先级最小的'+'或‘-’{int i,count=0,pos=-1;//count用来记录括号的数量,pos用来记录优先级最小的'+'或'-'的位置for(i=start;i<end;i++){if(str[i][0]=='(')count++;else if(str[i][0]==')')count--;else if((str[i][0]=='+' || str[i][0]=='-') && count==0)//无括号时pos=i;//i记录的是优先级最小的'+'或'-'的位置,也就是没有括号,并且在后面的加减运算}return pos;}int search_2(int start ,int end)//寻找优先级最小的‘*’或‘/’的位置{int i,count=0,pos=-1;//count用来记录括号的数量,pos用来记录优先级最小的'+'或'-'的位置for(i=start;i<end;i++){if(str[i][0]==')')count--;else if(str[i][0]=='(')count++;else if((str[i][0]=='*' || str[i][0]=='/') && count==0)pos=i;}return pos;}double turn(char c[]) //将字符串中的数字转换为浮点型{double temp=0;int i;for(i=0;;i++){if(c[i]!='\0')temp=temp*10+c[i]-'0';elsebreak;}return temp;}class Node{public:char data[15];Node* lchild;Node* rchild;Node(){lchild=NULL;rchild=NULL;}};class Bintree{public:Node* subroot;Node* creattree(int start ,int end);//建立二叉树void postorder(Node* subroot); //后续遍历二叉树double calcute(Node* subroot); //计算表达式的结果void destory(Node* subroot); //销毁二叉树,释放空间};Node* Bintree::creattree(int start,int end)//用递归的方法来建立二叉树{int pos=-1;Node* root =new Node;if(end-start==1)strcpy(root->data,str[start]);else{pos=search_1(start,end); //找优先级最低的加减法if(pos==-1)pos=search_2(start,end);//如果没有的话那就找优先级最低的乘除法if(pos==-1)root=creattree(start+1,end-1);else{strcpy(root->data,str[pos]);root->lchild=creattree(start,pos);root->rchild=creattree(pos+1,end);}}return root;}void Bintree::postorder(Node* subroot)//递归的方法后续遍历{if(subroot!=NULL){postorder(subroot->lchild);postorder(subroot->rchild);cout<<subroot->data<<" ";}}void Bintree::destory(Node *subroot){if(subroot!=NULL){destory(subroot->lchild);destory(subroot->rchild);}delete (subroot);}double Bintree::calcute(Node* subroot)//计算表达式的结果{double result;if(subroot->lchild==NULL && subroot->rchild==NULL) //递归出口,返回值{result=turn(subroot->data);return result;}switch(subroot->data[0]){case'+':return calcute(subroot->lchild)+calcute(subroot->rchild);break;case'-':return calcute(subroot->lchild)-calcute(subroot->rchild);break;case'*':return calcute(subroot->lchild)*calcute(subroot->rchild);break;case'/':return calcute(subroot->lchild)/calcute(subroot->rchild);break;}}int main(){char a[100];Bintree tree;Node* subroot;int i=0,count=0;bool flag=0;cout<<"请输入表达式:"<<endl;while(cin>>a){int j=0;while(a[i]!=0){if(a[i]=='+' || a[i]=='-' || a[i]=='/' || a[i]=='*'){if(flag){cout<<"表达式错误"<<endl; //判断表达式是否正确,即是否有多个运算符连续输入goto loop;}str[j++][0]=a[i++];flag=1;}else if(a[i]=='(' || a[i]==')'){str[j++][0]=a[i];if(a[i++]=='(')count++;elsecount--;if(count<0){cout<<"表达式错误"<<endl;//判断括号是否匹配goto loop;}}else{int k=0;while(a[i]!='+' && a[i]!='-' && a[i]!='*' && a[i]!='/' && a[i]!=')' && a[i]!='(' && a[i]!=0 )str[j][k++]=a[i++];j++;flag=0;}}if(count!=0){cout<<"表达式错误"<<endl;goto loop;}subroot=tree.creattree(0,j);tree.postorder(subroot);cout<<endl;cout<<"表达式的值:"<<endl;cout<<fixed<<setprecision(2)<<tree.calcute(subroot)<<endl;tree.destory(subroot);loop:{i=0;count=0;flag=0;}}return 0;}运行结果:优先队列与堆一、需求分析1.本程序可以模拟实现医院排列病人看病的顺序;2.程序要求从键盘输入来看病的病人的顺序和他们的病情的紧急程度,病情越紧急紧急程度的数值越小;3.计算机通过程序将紧急程度按照从小到大的顺序,把看病的病人重新排序,最终得到看病的顺序;4.输入的值每次有两个,病人来的顺序和紧急程度,都是整数,以-1,-1输入作为结束符;测试用例输入1152 33 5420510-1 -1输出23514二、概要设计抽象数据类型最终出列的顺序是按照priority的值从小到大的顺序排列的,所以,我们考虑用所输入的权值构建最小值堆来实现。

逆波兰表达式求值(实验报告及C源码)

逆波兰表达式求值(实验报告及C源码)

逆波兰表达式求值一、需求分析1、从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操作数等。

2、用堆栈来实现3、测试数据输入:2 3 * 1 – #输出:2 3 * 1 -- =5二、概要设计抽象数据类型需要一个浮点数栈来存储还没有计算的浮点数或者运算的结果。

ADT Stack数据成员:int size; int top; //分别用于存储栈大小、栈顶位置float *listArray;//存储浮点型数字的数组成员函数:bool push(float it);bool pop(float& it);bool isEmpty(); //判断栈为空bool isOne();//判断栈是否只有一个元素算法的基本思想1. 逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;2. 如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;3. 遇到空格前是数据的,将x押入栈;4. 如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;程序的流程输入字符串,程序对字符串依次扫描。

扫描一位,处理一位。

扫描完成后,判断栈里是不是只有一个数据,若是,得到正确结果;若不是,则表达式出错。

三、详细设计物理数据类型用浮点数类型的栈存储运算中要用的数据,需要入栈、出栈,故设计如下的浮点类型的栈:class Stack{private:int size;int top;float *listArray;public:Stack(int sz=20);~Stack();bool push(float it);//入栈bool pop(float& it);//出栈bool isEmpty();//判断栈是否为空bool isOne(); //判断栈里是否只有且仅有一个元素};成员函数的函数体Stack::Stack(int sz) //栈构造函数{size=sz;top=0;listArray=new float[size]; }bool Stack::push(float it) {if(top==size)return false;listArray[top++]=it;return true;}bool Stack::pop(float& it) {if(top==0)return false;it=listArray[--top];return true;}bool Stack::isEmpty() //判断站是否为空{if(top==0)return true;return false;}bool Stack::isOne(){if(top==1)return true;return false;}Stack::~Stack(){delete listArray;}算法的具体步骤用switch语句实现1. 逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;2. 如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;3. 遇到空格前是数据的,将x押入栈;4. 如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;算法的时空分析因为入栈、出栈的时间复杂度均为Θ(1),所以时间的复杂度主要取决于字符串的长度,空间也同样取决于字符串长度。

湖南大学数据结构试验2逆波兰问题

湖南大学数据结构试验2逆波兰问题

HUNAN UNIVERSITY 课程实习报告题目:逆波兰问题学生姓名刘乐学生学号20080820208专业班级通信工程2班指导老师朱宁波完成日期2010年4月19日一、需求分析1.本程序要求采用堆栈方法计算表达式的值,同时验证后缀报答是是否正确。

2.从键盘输入一个后缀表达式,该表示包括加减乘除等操作,以及正整数作为操作数等。

3.用堆栈来实现。

4.测试数据二、概要设计抽象数据类型为实现上述程序的功能,应以字符存储用户的输入,以及计算出的结果。

算法的基本思想5.根据题目要求,设计一个堆栈,对输入的字符串即后缀表达式中的数字字符逐个入栈,遇到运算符则出栈对栈顶元素和第二个元素进行运算,栈顶指向运算结果。

其中除数不可以为0。

直到表达式运算完输出结果。

定义如下线性表ADT Stack {数据对象:D={ a i | a i∈ElemSet, i=1,2,...,n, n≥0 }数据关系:R1={ <a i-1 ,a i >|a i-1 ,a i∈D, i=2,...,n }约定a n端为栈顶,a1端为栈底}ADT Stack基本操作:InitStack (&S) (构造空栈)DestroyStack(&S)(销毁栈结构)ClearStack (&S) (栈清空)StackLength(S) (求栈长)StackEmpty (S)(判空)GetTop (S, &e) (求栈顶元素)Push (&S, e) (入栈)Pop (&S, &e) (出栈)StackTraverse (S, visit( ))(遍历栈)本程序包含三个基本模块(1)输入模块:完成后缀表达式的输入。

(2)调用循环模块:调用函数建立堆栈进行出栈入栈操作,并计算表达式值。

(3)输出模块:屏幕上显示出结果。

三、详细设计算法的具体步骤float comp(){ int x;i = 0; top = -1;ch = exp[i];while (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){ printf("除数错误!\n");exit(0);//switch语句判断输入为运算符时则运算栈顶元素和第二个元素,特别的对除数不等于0做出出错处理、。

逆波兰表达式

逆波兰表达式

基本思路:
扫描后缀算术表达式字符串,每次从字符串中读取一个字符, 读到空格不做任何处理,若读到运算符,则表明它的两个操 作数已经在栈中,否则读到的字符必为数字,应把它转换为 一个正整数存入一个变量中,然后把计算或转换得到的正整 数(即该变量的值)压入栈中,依次扫描每个字符并进行上述 处理,直到遇到结束符,表明后缀表达式计算完成,最终结 果保存在栈中,并且栈中只有这一个值。
function rpn() Begin read(ch) while ( ch <> '\n') do begin case (ch) of case ’+’ : r ← pop()+pop() push(r) case ’-’ : r ← pop() r ← pop()-r push(r) case ’*’ : r ← pop()*pop() push(r) case ’/’ : r ← pop() r ← pop()/r push(r) end
前缀表达式的递归定义,就像正常表达式可以递归定义一样。
c (常量) rpn rpn rpn - rpn rpn * rpn rpn / rpn rpn
可以考虑用递归函数来求解。
function rpn() begin read(ch) case ch of case ’+’ case ’-’ case ’*’ case ’/’ case ’ ’ default end end
Hale Waihona Puke : : : : : :return return return return return return
rpn() + rpn() rpn() * rpn() / rpn() ch-’0’

逆波兰实验报告

逆波兰实验报告

实验一约瑟夫环问题基本要求需要基于线性表的基本操作来实现约瑟夫问题需要利用数组来实现线性表输入输出格式输入格式:n,m输出格式1:在字符界面上输出这n个数的输出序列输出格式2:将这n个数的输出序列写入到文件中实验原理设编号为1-n的n(n>0)个人按顺时针方向围成一圈.首先第1个人从1开始顺时针报数.报m的人(m 为正整数).令其出列。

然后再从他的下一个人开始,重新从1顺时针报数,报m的人,再令其出列。

如此下去,直到圈中所有人出列为止。

求出列编号序列。

利用数组对每个人排序。

利用while函数找到数到m的人,当第L个人出圈之后,报数,并在用后面的人依次填充。

实验程序#include<iostream>using namespace std;int main(){int A[100],n,m;cout<<"输入总人数和喊到的数字:\n";cin>>n>>m;int i,j,k=n;for(i=0;i<n;i++)A[i]=i+1; //让数组的值从1开始while(k>0){for(j=1;j<m;j++)i=(i+1)%k; //寻找第一个喊到m的人cout<<A[i]<<" ";for(j=i+1;j<k;j++) //从i+1开始继续向后喊数A[j-1]=A[j];k--; //剩余人数}cout<<"\n"<<A[i];cout<<endl;return 0;}。

逆波兰表达式

逆波兰表达式
问题描述: 问题描述:逆波兰表达式
【课题】若某算术表达式采用后置法表示(即逆波兰表达式) ,请编程计算该表达式 的值。如:表达式(a+b*c)/d-e 用后置法表示为 abc*+d/e-。 【问题描述】 计算用运算符后置法表示的表达式的值。 后缀表达式也称逆波兰表达式, 比中缀表达式计算起来更方便简单些,中缀表达式要计算就存在着括号的匹配问题,所以 在计算表达式值时一般都是先转换成后缀表达式,再用后置法计算表达式的值。如:表达 式(a+b*c)/d-e 用后置法表示应为 abc*+d/e-。
4
ch=exp[0]; while(ch!='#'){ if(!In(ch,OPSET)){//不是运算符则压入栈中 if(exp[i+1]==' '){//未出现连续数字 Push(&OPND,ch-48); i+=2; ch=exp[i]; }//if else{//出现连续数字 s=exp[i++]-48; while(exp[i]>='0'&&exp[i]<='9'){ s=s*10+exp[i++]-48; }//while Push(&OPND,s); s=0; ch=exp[++i]; }//else }//if else{ theta=ch; b=Pop(&OPND); a=Pop(&OPND); Push(&OPND,Operate(a,theta,b)); i+=2; ch=exp[i]; } } return GetTop(&OPND); }//EvaluateExpression_2( 3) 函数调用关系图

编译原理报告四逆波兰式

编译原理报告四逆波兰式

逆波兰式的产生及计算一、目的与要求1、目的通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。

2、要求(1)选用目前世界上普遍采用的语义分析方法──语法制导翻译技术。

(2)语义分析对象重点考虑经过语法分析后已是正确的语法范畴,实习重点是语义子程序。

(3)中间代码选用比较常见的形式,例如四元式。

二、背景知识属性文法:A=(G,V,F),其中:G:一个CFG, 属性文法的基础。

V:有穷的属性集:每个属性与一个文法符号相关联,这些属性代表与文法符号相关的语义信息,如:类型、地址、值、代码、符号表内容等等。

属性与变量一样,可以进行计算和传递,属性加工的过程即是语义处理的过程。

属性加工与语法分析同时进行。

属性的表示:标始符(或数),写在相应文法的下边,点记法:E.Val,E.Place,E.Type…。

F:关于属性的属性断言或一组属性的计算规则(称为语义规则)。

断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性。

属性有两类:综合属性:归约型属性,用于“自下而上”传递信息。

继承属性:推导型属性,用于“自上而下”传递信息。

综合属性的例子:非终结符E、T及F都有一个综合属性val,符号digit有一个综合属性,它的值由词法分析器提供。

与产生式L→E对应的语义规则仅仅是打印由E产生的算术表达式的值的一个过程,我们可认为这条规则定义了L的一个虚属性。

某些非终结符加上标是为了区分一个产生式中同一非终结符多次出现。

设表达式为3*5+4,则语义动作打印数值19。

3*5+4的带注释的分析树继承属性的例子:继承属性的自上而下定值(Real id1,id2,id3):Real id1,id2,id3的分析树L-属性文法:一个属性文法称为L-属性文法,如果对于每个产生式A→X1X2…Xn,满足:1、Xj(1≤j≤n)的继承属性仅依赖于下述属性值中的一种:A的继承属性或产生式右部位于Xj左边的符号X1,X2,…,Xj-1的属性。

逆波兰式的转化与求值 栈与队列 实验报告

逆波兰式的转化与求值 栈与队列 实验报告

逆波兰式实验报告2011.4.15实验题目:逆波兰式的转化与求值实验目的:了解并运用栈与队列。

在程序中将非逆波兰式表示的算术表达式转换为用逆波兰式表示,并计算用逆波兰式来表示的算术表达式的值。

验证刚学的栈和队列的理论,巩固知识并加深理解。

实验内容:一、抽象数学模型:逆波兰式转化程序流程:逆波兰式求值程序流程:二、详细算法描述:逆波兰式计算://先初始化一个栈s,并将左括号'('压栈//从左至右对表达式进行扫描,依次存入字符串s1中//若遇到数字则存入字符串s2中//若遇到右括号则将栈s中的元素弹出放入s2中直到遇到左括号'(',并将左括号出栈//若遇到左括号则直接进栈//若遇到运算符则需比较其与栈顶元素优先级顺序,若大于则直接入栈,否则弹出栈顶元素存入s2中直到运算符的优先级//低于栈顶元素并将其压栈//当遇到'#'时表明表达式以全部输入,此时将栈s中元素弹出并放入s2中,直至遇到左括号')'//将'#'放入s2作为表达式结束标志,表达式转换为逆波兰式(后缀表达式)后缀表达式求值算法描述//先初始化一个栈s//从左至右对s2进行扫描//若遇到数字字符则压入栈s//若遇到运算符则将栈s中元素依次弹出两个进行运算,将运算结果压栈//当遇到'#'时表达式结束,此时弹出栈顶元素即为表达式的值三、程序清单:(见附录)四、运行结果(截图):运行结果分析:将运算对象写在前面,而把运算符号写在后面。

程序采用逆波兰式可以很好的表示简单算术表达式,易于计算机处理表达式。

由运行结果可知,可以正确地把算术表达式转化为后缀表达式且能够正确计算出表达式的值五、调试分析和体会:(一)、实验程序编写过程中运用了栈的相关知识,通过栈实现逆波兰式的转化和计算。

(二)、利用栈,巧妙地把表达式转化为后缀表达式从而大大简化翻译过程,同时在对后缀表达式进行计算时也方便了计算。

数据结构实验报告三-逆波兰表达式

数据结构实验报告三-逆波兰表达式

数据结构实验报告三-逆波兰表达式问题描述:读入一个后缀表达式,利用堆栈来计算该表达式的值,同时要效验后缀表达式是否正确。

一、需求分析:1、用户从界面输入一个后缀表达式,用字符数组存储,以回车间结束2、若表达式正确,界面自动输出后缀表达式的值,否则输出表达式错误的信息,将结果置为0。

3测试数据:输入:请输入一个后缀表达式: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保存对于计算后缀表达式的值的算法:首先假设此表达式正确从字符串第一个开始扫描,遇到运算数就先转化成为数值然后压入堆栈中,如遇到运算符则弹出堆栈上面的两个元素,并进行对应的运算,将得到的值压入栈中,直到最后一个字符为止。

对于表达式错误:返回0程序的流程程序由三个模块组成:输入模块:输入一个后缀表达式:2 3 * 1 –计算模块:计算出后缀表达式的值输出模块:输出表达式的值:5三、详细设计算法的具体步骤:对于ADT Stack模板:物理数据类型采用数组:#includeusing namespace std;const int MaxSize=1000;templateclass Stack{public:Stack(int size=0); //构造大小为size的堆栈~Stack(){delete p;} //撤销堆栈bool IsFull(){return top==Size;} //判断堆栈是否已满bool IsEmpty(){return top==0;} //判断堆栈是否为空void Push(T &x); //将x压入堆栈T Pop(T &x); //将栈顶元素弹出用x保存private:int Size;//大小int top;//栈顶T *p;//数组指针};//构造堆栈templateStack::Stack(int size){Size=size;//栈大小为sizetop=0;//栈顶top指向0p=new T[Size];//为p开辟Size大小的空间}//向堆栈中压入xtemplatevoid Stack::Push(T &x){p[top++]=x;//将x保存于栈顶,栈顶+1}//弹出栈顶元素templateT Stack::Pop(T &x){x=p[--top];//x保存栈顶元素,栈顶-1return x;}/*上述每个函数时间复杂度O(1);对于后缀表达式求值函数*/float nibolan (char *array){ //array存储表达式Stack sta(MaxSize); //建立大小为Maxsize的堆栈int i=0;if(array[0]=='.'){cout<<"表达式错误:小数表示错误"<<endl;< p="">return 0;}while(array[i]!='\0'){ //当表达式没有结束if(array[i]=='.'){//数字第一个字符为小数点或运算符后是小数点cout<<"表达式错误:小数表示错误"<<endl;< p="">return 0;}if(i==0&&array[i]=='-'){//判断第一个是否负数,后面的没有必要判断,如果是i++; //处理下一个字符float tem=0;while(array[i]>='0'&&array[i]<='9'){tem=(float)array[i]-48+tem*10;//先计算该负数的绝对值i++;}if(array[i]=='.'){//若存在小数i++;//忽略该位if(!(array[i]>='0'&&array[i]<='9')){//小数点后不是数字cout<<"表达式错误:小数表示错误"<<endl;< p="">return 0;}}Stack s(7);//用于存储小数字符while(array[i]>='0'&&array[i]<='9'){s.Push(array[i]);i++;}float item=0;char x;while(!s.IsEmpty())item=((float)s.Pop(x)-48)*0.1+item*0.1;//计算小数tem+=item;tem=-tem;//取相反数得到原数sta.Push(tem);//将该数压入栈中}if(array[i]>='0'&&array[i]<='9'){//其他时候,判断是否为数字float tem=0;while(array[i]>='0'&&array[i]<='9'){//计算整数部分tem=(float)array[i]-48+tem*10;i++;}if(array[i]=='.'){//若存在小数i++;//忽略该位if(!(array[i]>='0'&&array[i]<='9')){//小数点后不是数字cout<<"表达式错误:小数表示错误"<<endl;< p="">return 0;}}Stack s(7);//用于存储小数字符while(array[i]>='0'&&array[i]<='9'){s.Push(array[i]);i++;}float item=0;char x;while(!s.IsEmpty())item=((float)s.Pop(x)-48)*0.1+item*0.1;//计算小数tem+=item;sta.Push(tem);}if(array[i]=='+'||array[i]=='-'||array[i]=='*'||array[i]=='/'){ float it1,it21,it22;//it21栈顶元素,it22倒数第二个,it1是it21,it22对应运算的值char ch=array[i];switch(ch){case '+':it21=sta.Pop(it21);if(sta.IsEmpty()){cout<<"表达是错误:运算符比对应所需的运算数多"<<="">return 0;}it22=sta.Pop(it22);it1=it21+it22;sta.Push(it1);break;case '-':it21=sta.Pop(it21);if(sta.IsEmpty()){cout<<"表达是错误:运算符比对应所需的运算数多"<<endl;< p="">return 0;}it22=sta.Pop(it22);it1=it22-it21;sta.Push(it1);break;case '*':it21=sta.Pop(it21);if(sta.IsEmpty()){cout<<"表达是错误:运算符比对应所需的运算数多"<<endl;< p="">return 0;}it22=sta.Pop(it22);it1=it21*it22;sta.Push(it1);break;case '/':it21=sta.Pop(it21);if(sta.IsEmpty()){cout<<"表达是错误:运算符比对应所需的运算数多"<<endl;< p="">return 0;}it22=sta.Pop(it22);it1=it22/it21;sta.Push(it1);break;default:break;}i++;}elsei++;}float value;sta.Pop(value);if(!sta.IsEmpty()){cout<<"表达式错误:运算数多于所需的运算符"<<="">return 0;}return value;}时间复杂度:该算法的时间复杂度O(n);四、调试分析略。

实验报告_编译原理_表达式翻译程序(逆波兰式)(后缀表达式)的设计与实现

实验报告_编译原理_表达式翻译程序(逆波兰式)(后缀表达式)的设计与实现

5.1目的和要求1、掌握表达式由中缀式转变成后缀式的过程。

2、学会用栈这种数据结构实现的方法。

5.2实验环境Windows XP + VC++6.05.3实验准备写出一个中缀式,分析可能得到的后缀式s=(a+b)*c 后缀式sab+c*=s<a 后缀式sa<a=b&c=d 后缀式ab=cd=&a>b|c=d 后缀式ab>cd=|5.4实验内容及步骤1、输入已给的文本格式的扫描程序biaoda.cpp文件,然后编译运行,检查修改错误。

2、编译成功后,提示输入表达式,用回车键查看输出的结果。

3、比较自己分析的结果和屏幕上的输出结果。

给出代码没有‘=’,‘<’,‘>’,‘&’,‘|’运算结果错误5.5实验小结1、得到的经验。

中缀表达式转换为后缀表达式2、遇到的主要问题。

运算符优先级不清楚,自行查找。

3、改进方案。

在原代码中加入有关‘=’,‘<’,‘>’,‘&’,‘|’的运算。

else if(str[i]=='&'|| str[i]=='|') {while((S.top!=S.base)&&(*(S.top-1)!='(')) {Pop(S,ch);exp[j]=ch;j++;}Push(S,str[i]);} else if(str[i]=='=') {while((*(S.top-1)=='=')){Pop(S,ch);exp[j]=ch;}Push(S,str[i]);} /* end of else if */else if(str[i]=='+'||str[i]=='-') {while((S.top!=S.base)&&(*(S.top-1)!='(')){Pop(S,ch);exp[j]=ch;j++;}Push(S,str[i]);} /* end of else if */else if(str[i]=='<'||str[i]=='>') {while((S.top!=S.base)&&(*(S.top-1)!='(')){Pop(S,ch);exp[j]=ch;j++;}Push(S,str[i]);} /* end of else if */else if (str[i]=='*'||str[i]=='/'){while((*(S.top-1)=='*')||(*(S.top-1)=='/')) {Pop(S,ch);exp[j]=ch;j++;}Push(S,str[i]);} /* end of else if */i++;} /* end of while */exp[j]='#';cout<<"\n\n输入的表达式";i=1;while(str[i+1]!='#'){cout<<str[i];} /* end of while */ cout<<"逆波兰表达式为:\n"; i=0;while(exp[i]!='#'){cout<<exp[i];i++;}}。

逆波兰式实验报告

逆波兰式实验报告

课程实习报告题目:逆波兰表达式班级:智能1201班姓名:易全政学号:201208070123完成日期:2014.3.27一、需求分析1、本程序要求输入一个包含四则运算且操作数为正数的逆波兰表达式,并利用堆栈求出结果值2、输入的的后缀表达式由键盘输入到字符界面,并要求相邻的操作数之间用空格隔开,最后以‘#’字符作为结束标识符3、如果该后缀表达式正确,那么在字符界面上输出其结果,计算结果小数点后面保留两位有效数字,如果不正确,请在字符界面上输出表达式错误提示4、测试数据输入2 3 * 1 -#输出5二、概要设计1、抽象数据类型为实现上述程序的功能,应该以字符串存入输入的字符以及操作数为实现操作数的保存以及运算,应该利用堆栈来完成2、算法的基本思想通过键盘一些字符与操作数,利用一个字符串来保存,并同时定义一个栈与字符串指针,每次栈里面保存当前输入的操作数,而当遇到运算符时将栈顶与栈的上个元素进行相应的运算,并将栈顶元素弹出同时保存进入新的栈顶中,在最后进行判断从而实现对输入正确的逆波兰表达式输出其运算结果。

3、程序的流程程序的流程由三个模块组成:(1)输入模块:输入字符串,并将地址赋给字符串指针(2)运算模块:输入字符的判断,操作数的入栈以及相应的运算(3)输出模块:对于符合条件的逆波兰表达式输出运算结果三、详细设计1、物理数据类型题目要求输入一行运算表达式,为一个字符串,并定义字符串指针保存其地址;定义一个顺序栈,用double型数组来保存栈内元素;用typedef定义一个新的结构体类型;含有很多的int与double型的变量;23、算法的时空分析根据程序的实现情况可知,算法运行时间主要集中在do while循环上,所以对于该字符串,若含有n个字符,则必有产生的时间代价为:Θ(n);4、输入输出的格式输入请输入要计算的表达式://提示等待输入输出等待输出输出的式子的构成为:输入的表达式= 运算结果或者输入的表达式--- error四、测试结果第一组测试:单字符减加乘除:输入2 3 4 + - 5 * 3 /#输出2 3 4 + - 5 * 3 /# =-8.33第二组测试:连续字符的加减乘除输入12 34 + 234 – 2 * 3 /#输出12 34 + 234 – 2 * 3 /# =-125.33第三组测试:输入错误情况测试输入1 2 3 -#输出1 2 3 -#———Input error!第四组测试:计算错误情况测试输入3 0 /#输出3 0 /#———Input error!五、实验心得本次实验通过在栈的基础上要进行对逆波兰表达式的计算,最初只是进行了单个字符的计算,并且很容易的就编出来了并且验证争取,但是在处理连续字符,例如12 2 *# 上却多次尝试但是都没有效果,就是在用cin输入字符串时,遇到空格键会自动终止,但是运算结果不正确,因为在同学的提示下利用getline来输入字符串就可以避免这种情况,因为我在原有程序的基础上做出了改进,并实现了最后的编程。

数据结构实验报告五—四则运算表达式求值

数据结构实验报告五—四则运算表达式求值

问题描述:四则运算表达式求值,将四则运算表达式用中缀表达式,然后转换为后缀表达式,并计算结果。

一、需求分析:1、本程序是利用二叉树后序遍历来实现表达式的转换,同时可以使用实验三的结果来求解后缀表达式的值。

2、输入输出格式:输入格式:在字符界面上输入一个中缀表达式,回车表示结束。

请输入表达式:输入一个中缀表达式输出格式:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。

逆波兰表达式为:输出逆波兰表达式运算结果为:输出运算后的结果3、测试用例输入:21+23*(12-6)输出:21 23 12 6 -*+二、概要设计:抽象数据类型二叉树类BiTree算法的基本思想根据题目要求,利用栈计算,和二叉树存储,来计算表达式该算法的基本思想是:先利用栈进行计算,然后用二叉树进行存储,和实验三算法一样来计算逆波兰表达式的值程序的流程程序由三个模块组成:(1)输入模块:输入一个运算式(2)计算模块:利用栈进行表达式的计算,二叉树来存储。

(3 )输出模块:屏幕上显示出后缀表达式和运算结果。

三、详细设计物理数据类型程序含有两个类,其中栈不再赘述,另一个类为二叉树class BiTree 包含私有成员struct BiTreeNode,根节点BiTreeNode *T;索引index; int number_of_point 优先级比较函数 compare(char a,char b);生成树的函数void InorderCreate(BiTreeNode *&T,char str[30][10],int start,int end);判断数字函数bool IsNumber(char a);求值函数double Operate(BiTreeNode *T);还有显示后缀表达式的函数void display(BiTreeNode *T) ;而公有成员函数则是对私有函数的重载,为方便使用,因为函数中普遍使用了递归的算法。

逆波兰表达式 计算器 实验报告

逆波兰表达式 计算器 实验报告

计算机科学与工程学院综合设计报告说明:1、报告中的第一、二、三项由指导教师在综合设计开始前填写并发给每个学生;四、五两项(中英文摘要)由学生在完成综合设计后填写。

2、学生成绩由指导教师根据学生的设计情况给出各项分值及总评成绩。

3、指导教师评语一栏由指导教师就学生在整个设计期间的平时表现、设计完成情况、报告的质量及答辩情况,给出客观、全面的评价。

4、所有学生必须参加综合设计的答辩环节,凡不参加答辩者,其成绩一律按不及格处理。

答辩小组成员应由2人及以上教师组成。

5、报告正文字数一般应不少于5000字,也可由指导教师根据本门综合设计的情况另行规定。

6、平时表现成绩低于6分的学生,其综合设计成绩按不及格处理。

7、此表格式为武汉工程大学计算机科学与工程学院提供的基本格式(适用于学院各类综合设计),各教研室可根据本门综合设计的特点及内容做适当的答辩记录表目录摘要 (II)Abstract (II)第一章课题背景 (1)1.1 课题背景 (1)1.2 课程设计目的 (1)第二章设计简介及设计方案论述 (2)2.1 工作原理 (2)2.2.1要求 (2)2.2.2任务 (3)第三章详细设计 (4)3.1流程图 (4)3.2 设计的细节 (4)3.3 由后缀表达式计算中缀表达式原理 (6)3.4 算法描述 (6)第四章设计结果及分析 (7)4.1输入不同表达式验证程序的正确性 (7)致谢 (10)参考文献 (11)摘要本课程设计将实现一个简单计算器。

在功能上尽量模仿windows的计算器。

系统界面不做牵制要求。

该程序能实现标准型中+、-、*、/、^(乘方)、%(求余)、(、)的混合运算表达式(一般意义上的中缀表达式),将其转换成逆序波兰表达式(后缀表达式)并计算输出结果。

在进行运算后可以选择继续运算或者结束当前运算。

即时准确地获得需要的计算的结果,充分降低了数字计算的难度和节约了时间,对人们的生活有一定的帮助。

在课程设计中,系统开发平台为Windows XP,程序设计设计语言采用Visual C++,在程序设计中,采用了结构化与面向对象两种解决问题的方法。

数据结构——逆波兰式

数据结构——逆波兰式

数据结构——逆波兰式很久没有关注算法和数据结构,⼤部分知识都已经忘记了;是时间好好回炉⼀下了,说实话⼲读数据机构这本书还是挺枯燥⽽且这本书原理性⽐较多,有⼀定的难度。

这不刚看到逆波兰式废了好⼤劲才搞懂,⽼了。

逆波兰式逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)⼀个E的后缀形式可以如下定义:(1)如果E是⼀个变量或,则E的是E本⾝。

(2)如果E是E1 op E2形式的表达式,这⾥op是如何⼆元操作符,则E的后缀式为E1'E2' op,这⾥E1'和E2'分别为E1和E2的后缀式。

(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。

如:我们平时写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/-算法实现将⼀个普通的中序转换为的⼀般算法是:⾸先需要分配2个栈,⼀个作为临时存储运算符的栈S1(含⼀个结束符号),⼀个作为输⼊逆波兰式的栈S2(空栈),S1栈可先放⼊优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。

可指定其他字符,不⼀定⾮#不可。

从中缀式的左端开始取字符,逐序进⾏如下步骤:(1)若取出的字符是,则分析出完整的运算数,该操作数直接送⼊S2栈(2)若取出的字符是,则将该运算符与S1栈栈顶元素⽐较,如果该(不包括括号运算符)⼤于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送⼊S2栈中,直⾄S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送⼊S1栈。

(3)若取出的字符是“(”,则直接送⼊S1栈顶。

(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个,依次送⼊S2栈,此时抛弃“(”。

逆波兰表达式 if

逆波兰表达式 if

逆波兰表达式 if【最新版】目录1.逆波兰表达式的概念2.逆波兰表达式的特点3.逆波兰表达式的应用4.逆波兰表达式与中缀表达式的转换5.逆波兰表达式的计算方法正文1.逆波兰表达式的概念逆波兰表达式(Reverse Polish Notation,简称 RPN),是一种用于表示算术表达式的方式。

与中缀表达式和中文表达式不同,逆波兰表达式的操作符位于操作数的右侧,即先写出操作数,再写出操作符。

例如,表达式“3 + 5”的逆波兰表达式为“3 5 +”。

2.逆波兰表达式的特点逆波兰表达式的主要特点如下:- 操作符位于操作数的右侧。

- 表达式中没有括号,因此不需要考虑括号的优先级问题。

- 逆波兰表达式的长度是所有可能中缀表达式中最短的。

3.逆波兰表达式的应用逆波兰表达式在计算表达式值时具有较高的效率。

它可以方便地转换为堆栈式计算,通过不断地弹出操作数和操作符进行计算,最终得到表达式的结果。

此外,逆波兰表达式在编译器和解释器中有着广泛的应用,如表达式求值、算术运算等。

4.逆波兰表达式与中缀表达式的转换逆波兰表达式和中缀表达式可以相互转换。

从逆波兰表达式转换为中缀表达式时,只需将操作符插入到相应的操作数之间即可。

例如,表达式“3 5 +”转换为中缀表达式为“3 + 5”。

从中缀表达式转换为逆波兰表达式时,需要遍历表达式,将操作数和操作符依次排列。

例如,表达式“3 + 5”转换为逆波兰表达式为“3 5 +”。

5.逆波兰表达式的计算方法逆波兰表达式的计算方法通常采用堆栈来实现。

具体步骤如下:- 初始化一个空堆栈。

- 从左到右遍历逆波兰表达式,遇到操作数时将其入栈,遇到操作符时弹出相应的操作数进行计算,并将计算结果入栈。

- 当遍历完整个逆波兰表达式后,堆栈中的元素即为表达式的结果。

逆波兰式分析实验报告

逆波兰式分析实验报告
stack[top-1]=stack[top-1]+stack[top];
top--;
break;
case '-':
stack[top-1]=stack[top-1]-stack[top];
top--;
brp-1]=stack[top-1]*stack[top];
d=10*d+ch-'0'; /*将数字字符转化为对应的数值*/
ch=ex[t];t++;
}
top++;
stack[top]=d;
}
ch=ex[t];t++;
}
printf("\n\t计算结果:%g\n",stack[top]);
}
int main(){
trans();
compvalue();
return 0;
top--;
break;
case '/':
if(stack[top]!=0)
stack[top-1]=stack[top-1]/stack[top];
else{
printf("\n\t除零错误!\n");
exit(0); /*异常退出*/
}
top--;
break;
default:
d=0;
while(ch>='0'&&ch<='9'){
3.本次试验激发了我的学习兴趣,培养了我独立发现问题、分析问题、解决问题的能力。也增强了我与同学交流沟通共同解决问题的能力。
4.理解了编译原理和各个学科之间的融合渗透,锻炼了编程的能力,达到学以致用的目的

逆波兰表达式还原

逆波兰表达式还原

逆波兰表达式还原【原创版】目录1.逆波兰表达式的概念2.逆波兰表达式的还原方法3.实例解析正文一、逆波兰表达式的概念逆波兰表达式(Reverse Polish Notation,简称 RPN),是一种用于表示算术表达式的形式,其主要特点是将运算对象放在运算符之前,即“后缀表示法”。

这种表示法在计算表达式值时,可以避免传统的中缀表示法中的括号匹配问题,从而降低计算复杂度。

二、逆波兰表达式的还原方法逆波兰表达式的还原,主要是通过栈数据结构来进行计算。

具体步骤如下:1.初始化一个空栈。

2.从左到右遍历 RPN 表达式中的每一个元素:a.如果遇到数字,将其入栈。

b.如果遇到运算符,弹出栈顶的两个数字,进行运算,并将结果入栈。

注意:当遇到“+”和“-”时,需要从栈中弹出两个数字进行运算;当遇到“*”和“/”时,需要确保栈中至少有一个数字,否则无法进行运算。

3.当遍历完整个 RPN 表达式后,栈中剩下的数字就是表达式的结果。

三、实例解析假设有一个 RPN 表达式:2 + 3 * 4 - 5,我们按照上述方法进行还原:1.初始化空栈。

2.遍历表达式:a.遇到数字 2,入栈。

b.遇到运算符“+”,弹出栈顶数字 2,进行加法运算,结果 2 入栈。

c.遇到数字 3,入栈。

d.遇到运算符“*”,弹出栈顶两个数字 2 和 3,进行乘法运算,结果 6 入栈。

e.遇到数字 4,入栈。

f.遇到运算符“-”,弹出栈顶两个数字 6 和 4,进行减法运算,结果 2 入栈。

g.遇到数字 5,入栈。

h.遍历结束,栈中剩下的数字 2 即为表达式的结果。

通过以上步骤,我们可以将逆波兰表达式还原成正常的中缀表示法,然后进行计算。

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

HUNAN UNIVERSITY 课程实习报告
题目逆波兰表达式求值
学生姓名XX
学生学号
专业班级
指导老师
完成日期
一、需求分析
1.本程序要求对用户输入一个后缀表达式,打印输出其结果。

2.后缀表达式有用户通过键盘输入,其中两相邻操作数之间利用空格隔开,以“#”表达结束。

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

3.测试数据
输入
2 3*1-#
输出
5
二、概要设计
1.抽象数据类型
为实现上述程序的功能,应以一个字符数组存储用户的输入,运算中运用到整数及浮点数。

2.算法的基本思想
根据题目要求,计算后缀表达式,需要用到堆栈来实现。

算法如下:
1)假设此表达式正确从字符串第一个开始扫描,遇到运算数就先转化成为数值然后压入堆栈中,
2)如遇到运算符则弹出堆栈上面的两个元素,并进行对应的运算,将得到的值压入栈中,循环计算,然后往堆栈中压入结果,直到最后一个字符为止。

3)若表达式错误:返回错误提示。

ADT:
Stack{
操作对象:字符,整数,浮点数
基本操作:
Stack(int size);//构造大小为size的栈
~Stack();//释放内存空间
void push(const float& n);//数据进栈
float pop();//数据出栈
int length();//计算栈内元素个数
}
3.程序的流程
程序由三个模块组成:
1)输入模块:输入一个表达式的字符串。

2)计算模块:设计一个计算后缀表达式的函数。

3)输出模块:输出显示计算的结果。

三、详细设计
1.算法的具体设计
算法流程图如下:
2.算法的时间复杂度分析
该算法的时间复杂度O(n)。

四、代码源程序
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
class Stack{ 输入字符串a
a[i]>47&&a[i]<57?
数值进栈
a[i]=' '?
a[i]==42 ||a[i]==43 ||a[i]==45 ||a[i]==47

运算结果进栈
输出结果Y
N
a[i]='#' ?
Y
N
private:
int size;
int top;
float *listArray;
public:
Stack(int size=5){//定义构造函数
this->size=size;
top=0;
listArray=new float[size];
}
~Stack(){
delete [] listArray;
}
void push(const float& n){// 入栈
if(top==size)
return ;
listArray[top++]=n;
}
float pop(){// 出栈
if(top==0)
return 0;
else
return listArray[--top];
}
int length(){// 栈内元素个数
return top;
}
};
void nibolan(char *p){
int a=strlen(p);//字符串长度
int t=1,k=0,g=0;//s作为有数的标志,t作为是否为整数的标志,k是记录小数计算的幂级数float in=0,fl=0,x,y;//in 为一个数的整数部分,fl为小数部分,x为第一个数,y为第二个数
Stack it(a);//实例化一个栈对象
for(int i=0;i<a;i++){//循环检查字符串的每一个字符
if(p[0]==46){
cout<<"表达式有误"<<endl;
break;
}
else if(p[i]>47 && p[i]<58){//字符对应的数在48~57的范围是数字
if(t)//若是整数
in=in*10+(p[i]-48);
else//小数
fl=fl+(p[i]-48)*pow(0.1,k++);//pow(x,y)函数计算x的y次幂
}
else if(p[0]!=46 && p[i]==46){//若是小数点则记录t=0
if(t==0){//已记录则跳出
cout<<"表达式有误"<<endl;
break;
}
else{
t=0;//有小数
k=1;
}
}
else if(p[i]==' '){
//第一个数整数部分和小数部分进栈
it.push(in+fl);
//此时无数,复原
in=0;
fl=0;
t=1;
k=0;
}
//若为运算符则令数出栈运算然后再将结果入栈
else if(p[i]==42 ||p[i]==43 ||p[i]==45 ||p[i]==47 ){
//第二个数整数部分和小数部分进栈
it.push(in+fl);
//令第二个和第一个数依次出栈
y=it.pop();
x=it.pop();
if(p[i]=='+')
it.push(x+y);
else if(p[i]=='-')
it.push(x-y);
else if(p[i]=='*')
it.push(x*y);
else if(p[i]=='/'){
if(y==0){
cout<<"分母为0!表达式有误"<<endl;
return ;
}else
it.push(x/y);
}
//复原整数和小数部分,默认无小数
in=0;
fl=0;
t=1;
k=0;
}
else if(p[i]=='#'){//若是#则结束
g=1;
break;
}
}
if(it.length()==1 && g==1){//栈内只有一个数,表达式正确且已结束 cout<<"答案为:"<<it.pop();
}
}
int main(){
char s[30];
cout<<"请输入后缀表达式:"<<endl;
while(gets(s))
nibolan(s);
return 0;
}
五、测试结果
六、实验心得
通过此次实验了解了前缀表达式,中缀表达式以及后缀表达式,并且更加熟悉了栈的算法编写,虽然此次实验过程中遇到了很多问题,出现很多Bug以及逻辑上的程序问题,但最后通过与同学讨论以及自己查询资料探究基本得到了解决,完成了基本的要求,感受到了不仅要在课堂上认真学习课后仍需多实践练习,才能掌握好知识。

相关文档
最新文档