算术表达式求值-数据结构实验报告

合集下载

数据结构表达式求值实验报告

数据结构表达式求值实验报告

竭诚为您提供优质文档/双击可除数据结构表达式求值实验报告篇一:数据结构实验二——算术表达式求值实验报告《数据结构与数据库》实验报告实验题目算术表达式求值学院:化学与材料科学学院专业班级:09级材料科学与工程系pb0920603姓学邮名:李维谷号:pb09206285箱:指导教师:贾伯琪实验时间:20XX年10月10日一、需要分析问题描述:表达式计算是实现程序设计语言的基本问题之一,它的实现是栈的应用的一个典型例子。

设计一个程序,演示通过将数学表达式字符串转化为后缀表达式,并通过后缀表达式结合栈的应用实现对算术表达式进行四则混合运算。

问题分析:在计算机中,算术表达式由常量、变量、运算符和括号组成。

由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。

因而在程序设计时,借助栈实现。

设置运算符栈(字符型)和运算数栈(浮点型)辅助分析算符优先关系。

在读入表达式的字符序列的同时完成运算符和运算数的识别处理,然后进行运算数的数值转换在进行四则运算。

在运算之后输出正确运算结果,输入表达式后演示在求值中运算数栈内的栈顶数据变化过程,最后得到运算结果。

算法规定:输入形式:一个(:数据结构表达式求值实验报告)算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。

为使实验更完善,允许操作数为实数,操作符为(、)、.(表示小数点)、+、-、*、/、^(表示乘方),用#表示结束。

输出形式:演示表达式运算的中间结果和整个表达式的最终结果,以浮点型输出。

程序功能:对实数内的加减乘除乘方运算能正确的运算出结果,并能正确对错误输入和无定义的运算报错,能连续测试多组数据。

测试数据:正确输入:12*(3.6/3+4^2-1)#输出结果:194.4无定义运算:12*(3.6/(2^2-4)+1)#输出结果:表达式出错,除数为0,无意义错误输入:12+s#输出结果:eRRoR!二、概要设计拟采用两种类型的展分别对操作数和操作符进行操作。

数据结构表达式求值实验报告

数据结构表达式求值实验报告

实验报告课程名:数据结构(C语言版)实验名:表达式求值姓名:班级:学号:时间:2014.10.25一实验目的与要求1. 了解栈的应用2. 利用栈进行算术表达式求值二实验内容1.以字符串的形式给出一个算术表达式, 计算出该算术表达式的值。

2.表达式中可能出现”+”, ”−”, ”∗”, ”/”, ”(”, ”)”。

三实验结果与分析分析:r:读入字符t:栈顶字符r( ) # 低优先运算符高优先运算符( 入栈出栈错误入栈入栈) 错误错误错误错误错误t # 入栈错误结束入栈入栈低优先运算符入栈出栈+运算出栈+计算出栈+计算入栈高优先运算符入栈出栈+运算出栈+计算出栈+计算出栈+计算1, 入栈2, 错误3, 出栈4, 出栈+计算5, 结束( ) # 低优先运算符高优先运算符( 1 3 2 1 1) 2 2 2 2 2# 1 2 5 1 1低优先运算符 1 4 4 4 1高优先运算符 1 4 4 4 4此实验可用两个栈和数组来实现,一个操作栈,一个数字栈,两个栈的字符进行优先权比较可得到5种结果。

首先置操作栈为空栈,表达式起始符“#”作为数字栈的栈底元素,依次读入表达式的每个字符,若是操作字符进操作栈,若是数字进数字栈,操作栈和数字栈的栈顶元素比较优先权后进行相应操作,直至结束,最后输出值即可。

实验程序:#include<stdio.h>#include<stdlib.h>#include<string.h>int change(char c)//字符转换{int j=-1;switch(c){case '(':j=0;break;case ')':j=1;break;case '#':j=2;break;case '+':j=3;break;case '-':j=3;break;case '*':j=4;break;case '/':j=4;break;}return(j);}int compu(int x,int y,char c)//数字计算转换{int j=-1;switch(c){case '+':j=x+y;break;case '-':j=x-y;break;case '*':j=x*y;break;case '/':j=x/y;break;}return(j);}void get(char a[],int num_op,int method[5][5]){int a_length=strlen(a)+1;//表达式的长度int p=0,num_p=0,op_p=0;int *num_s=(int *)malloc((a_length)*sizeof(int));// char *op_s=(char *)malloc((a_length)*sizeof(int));// op_s[op_p]='#';op_p++;//进字符栈int k=-1;//输出结果判断int ox,oy;while(1){char c=a[p];//将表达式中的字符一个一个赋值给cif(c>='0'&&c<='9')//判断是不是数字{num_s[num_p]=c-48;//将Ascll码转换成对应数字num_p++;//进数字栈p++;//代表表达式的位置开始为0指向第一位}else{int t=method[change(op_s[op_p-1])][change(c)];//将5种操作的一种传给tswitch(t){case 1:op_s[op_p]=c;op_p++;p++;break;case 2:k=0;break;case 3:op_p--;p++;break;case 4:ox=num_s[num_p-2];oy=num_s[num_p-1];num_p=num_p-2;num_s[num_p]=compu(ox,oy,op_s[op_p-1]);//将计算的值存入num_s[]num_p++;//入数字栈op_p--;break;case 5:k=1;break;}}if(k>=0)//跳出循环{break;}}switch(k)//0错误,1输出结果{case 0:printf("表达式错误!");break;case 1:printf("%s=%d\n",a,num_s[num_p-1]);break;}}int main(int argc,char *argv[]){ char a[20];puts("请输入个位数的表达式:");gets(a);int num_op=5;//表示操作的种数int method[5][5]={{1,3,2,1,1},{2,2,2,2,2},{1,2,5,1,1},{1,4,4,4,1},{1,4,4,4,4}};//1表示入栈,2表示错误,//3表示出栈,4表示出栈+计算,//5表示结束get(a,num_op,method);return 0;}图1.表达式求值运行结果。

数据结构课程设计-表达式求值【完整版】

数据结构课程设计-表达式求值【完整版】

XXXXXX大学《数据结构》课程设计报告班级:学号:姓名:指导老师:目录一算术表达式求值一、需求分析二、程序得主要功能三、程序运行平台四、数据结构五、算法及时间复杂度六、测试用例七、程序源代码二感想体会与总结算术表达式求值一、需求分析一个算术表达式就是由操作数(operand)、运算符(operator)与界限符(delimiter)组成得。

假设操作数就是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号与表达式起始、结束符“#”,如:#(7+15)*(23—28/4)#。

引入表达式起始、结束符就是为了方便.编程利用“算符优先法”求算术表达式得值.二、程序得主要功能(1)从键盘读入一个合法得算术表达式,输出正确得结果。

(2)显示输入序列与栈得变化过程。

三、程序运行平台Visual C++6、0版本四、数据结构本程序得数据结构为栈。

(1)运算符栈部分:struct SqStack //定义栈{char *base; //栈底指针char *top; //栈顶指针intstacksize; //栈得长度};intInitStack (SqStack &s) //建立一个空栈S{if (!(s、base= (char *)malloc(50*sizeof(char))))exit(0);s、top=s、base;s、stacksize=50;return OK;}char GetTop(SqStack s,char &e) //运算符取栈顶元素{if (s、top==s、base) //栈为空得时候返回ERROR{ﻩ printf("运算符栈为空!\n");ﻩ return ERROR;}elsee=*(s、top-1); //栈不为空得时候用e做返回值,返回S得栈顶元素,并返回OK returnOK;}int Push(SqStack&s,char e) //运算符入栈{if (s、top—s、base >= s、stacksize)ﻩ{printf("运算符栈满!\n");ﻩs、base=(char*)realloc(s、base,(s、stacksize+5)*sizeof(char));//栈满得时候,追加5个存储空间if(!s、base)exit (OVERFLOW);s、top=s、base+s、stacksize;s、stacksize+=5;}ﻩ*(s、top)++=e;//把e入栈ﻩreturn OK;}int Pop(SqStack &s,char &e) //运算符出栈{if (s、top==s、base) //栈为空栈得时候,返回ERROR{printf("运算符栈为空!\n”);ﻩ return ERROR;}else{ﻩﻩe=*-—s、top;//栈不为空得时候用e做返回值,删除S得栈顶元素,并返回OK return OK;}}int StackTraverse(SqStack&s)//运算符栈得遍历{ﻩchar *t;ﻩt=s、base;ﻩif (s、top==s、base){ﻩ printf(”运算符栈为空!\n”); //栈为空栈得时候返回ERRORreturn ERROR;}while(t!=s、top){ﻩﻩprintf(" %c",*t); //栈不为空得时候依次取出栈内元素t++;ﻩ}return ERROR;}(2)数字栈部分:struct SqStackn//定义数栈{int *base; //栈底指针int*top; //栈顶指针int stacksize; //栈得长度};intInitStackn (SqStackn &s) //建立一个空栈S{s、base=(int*)malloc(50*sizeof(int));if(!s、base)exit(OVERFLOW);//存储分配失败s、top=s、base;s、stacksize=50;return OK;}int GetTopn(SqStackn s,int&e) //数栈取栈顶元素{if(s、top==s、base){printf("运算数栈为空!\n");//栈为空得时候返回ERRORﻩ return ERROR;}elseﻩe=*(s、top-1);//栈不为空得时候,用e作返回值,返回S得栈顶元素,并返回OKreturnOK;}int Pushn(SqStackn &s,int e) //数栈入栈{if(s、top—s、base>=s、stacksize){ﻩﻩprintf("运算数栈满!\n");//栈满得时候,追加5个存储空间ﻩs、base=(int*)realloc (s、base,(s、stacksize+5)*sizeof(int));if(!s、base) exit (OVERFLOW);ﻩs、top=s、base+s、stacksize;//插入元素e为新得栈顶元素s、stacksize+=5;}*(s、top)++=e; //栈顶指针变化returnOK;}int Popn(SqStackn &s,int &e)//数栈出栈{ﻩif (s、top==s、base){ﻩ printf("运算符栈为空!\n");//栈为空栈得视时候,返回ERRORﻩ return ERROR;ﻩ}else{ﻩﻩe=*—-s、top;//栈不空得时候,则删除S得栈顶元素,用e返回其值,并返回OK ﻩreturnOK;}}int StackTraversen(SqStackn &s)//数栈遍历{ﻩint*t;ﻩt=s、base ;ﻩif(s、top==s、base)ﻩ{printf("运算数栈为空!\n”);//栈为空栈得时候返回ERRORﻩ return ERROR;ﻩ}ﻩwhile(t!=s、top)ﻩ{printf(” %d”,*t); //栈不为空得时候依次输出t++;}return ERROR;}五、算法及时间复杂度1、算法:建立两个不同类型得空栈,先把一个‘#’压入运算符栈。

数据结构表达式求值(中缀)实验报告

数据结构表达式求值(中缀)实验报告

数据结构表达式求值(中缀)实验报告题目名称表达式求值学号姓名指导教师日期一1. 问题描述:在计算机中,算术表达式由常量、变量、运算符和括号组成。

由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行,在程序设计时,借助栈实现。

2. 表达式求值这个程序,主要利用栈和数组,把运算的先后步骤进行分析并实现简单的运算,以字符列的形式从终端输入语法的正确的、不含变量的整数表达式。

利用已知的算符优先关系,实现对算术四则运算的求值,在求值中运用栈、运算栈、输入字符和主要操作的变化过程。

该程序相当于一个简单的计算机计算程序,只进行简单的加减乘除和带括号的四则运算。

1、基本思想(中缀表达式求值)要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值,首先要能够正确解释表达式,要了解算术四则运算的规则即:(1)先乘除后加减;(2)从左到右计算;(3)先括号内,后括号外。

下表定义的运算符之间的关系:b + - * / () # a+ > > < < < > > _ > > < < < > > * > > > > < > > / > > > > < > > ( < < < < < = ) > > > > > > # < < < < < =为了实现运算符有限算法,在程序中使用了两个工作栈。

分别是:运算符栈OPTR,操作数栈OPND.基本思想:(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;(2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈得栈顶运算符比较优先级后作相应操作。

数据结构实验报告-算术表达式求值

数据结构实验报告-算术表达式求值

- - 1.前言12.概要设计12.1 数据构造设计12.2 算法设计12.3 ADT描述22.4 功能模块分析23.详细设计33.1 数据存储构造设计33.2主要算法流程图〔或算法伪代码〕44.软件测试75.心得体会8参考文献8附录9- -优质-..1.前言在计算机中,算术表达式由常量、变量、运算符和括号组成。

由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进展。

因而在程序设计时,借助栈实现。

算法输入:一个算术表达式,由常量、变量、运算符和括号组成〔以字符串形式输入〕。

为简化,规定操作数只能为正整数,操作符为+、-*、/,用#表示完毕。

算法输出:表达式运算结果。

算法要点:设置运算符栈和运算数栈辅助分析算符优先关系。

在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。

2.概要设计2.1 数据构造设计任何一个表达式都是由操作符,运算符和界限符组成的。

我们分别用顺序栈来存放表达式的操作数和运算符。

栈是限定于紧仅在表尾进展插入或删除操作的线性表。

顺序栈的存储构造是利用一组连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置,base为栈底指针,在顺序栈中,它始终指向栈底,即top=base可作为栈空的标记,每当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。

2.2 算法设计为了实现算符优先算法。

可以使用两个工作栈。

一个称为OPTR,用以存放运算符,另一个称做OPND,用以存放操作数或运算结果。

1.首先置操作数栈为空栈,表达式起始符〞#〞为运算符栈的栈底元素;2.依次读入表达式,假设是操作符即进OPND栈,假设是运算符那么和OPTR栈的栈顶运算符比拟优先权后作相应的操作,直至整个表达式求值完毕〔即OPTR栈的栈顶元素和当前读入的字符均为〞. .word.zl.数据构造课程设计第 2 页#〞〕。

表达式求值实验报告

表达式求值实验报告

表达式求值实验报告西南大学数据结构实验报告学院:专业:班级:姓名:学号:实验报告一、实验题目:表达式表达式二、实验目的和建议:目的:(1)通过该算法的设计思想,熟识栈的特点和应用领域方法;(2)通过对波函数优先法对算术表达式表达式的算法继续执行过程的模拟,认知在继续执行适当栈的操作方式时的变化过程。

(3)通过程序设计,进一步熟识栈的基本运算函数;(4)通过自己动手同时实现算法,强化从伪码算法至c语言程序的同时实现能力。

建议:(1)采用栈的顺序存储则表示方式;(2)采用波函数优先法;(3)用c语言同时实现;(4)从键盘输入一个符合要求的算术表达式,输入恰当的结果。

三、实验过程:#include#include#include#include#include#include#include#include#include#inclu de#include//函数结果状态代码#definetrue1#definefalse0#defineok1#defineerror0#defineinfeasible-1typedefintstatus;//status就是函数的类型,其值就是函数结果状态代码,如ok等typedefintelemtype;constintstack_init_size=100;constintstackincrement=10;typed efstruct{elemtype*base;elemtype*top;intstacksize;}stack;statusinitstack(stack&s){//构造一个空栈ss.base=(elemtype*)malloc(stack_init_size*sizeof(elemtype));if(!s.base)exit(er ror);s.top=s.base;s.stacksize=stack_init_size;returnok;}statuspush(stack&s,ele mtypee){//插入元素e为新的栈顶元素if(s.top-s.base>=s.stacksize){s.base=(elemtype*)realloc(s.base,(s.stacksize+stackincrem ent)*sizeof(elemtype));if(!s.base)exit(overflow);s.top=s.base+s.stacksize;s.st acksize+=stackincrement;}*s.top++=e;returnok;}statuspop(stack&s,elemtype&e){//若栈不空,则删除,用e返回其值,并返回ok;否则返回errorif(s.top==s.base)returnerror;e=*--s.top;returnok;}statusgettop(stack&s){//若栈不空,用e返回s的栈顶元素,并返回ok;否则返回errorif(s.top==s.base)returnerror;return*(s.top-1);}operate.h:#include\statusin(charc){//辨别c与否为运算符if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#')returnok;elsereturnerror;}statusoper ate(inta,charc,intb){//二元运算switch(c){case'+':returna+b;break;case'-':returna-b;break;case'*':returna*b;break;case'/':if(b==0){printf(\(提示信息:存有除数为零错误)\\n\);returnerror;}//除数无法为零elsereturna/b;break;}}charprecede(chara,charb){//波函数间优先关系switch(a){case'+':switch(b){case'+':return'>';break;case'-':return'>';break;case'*':return'';break;case'#':return'>';break;}break;case'-':switch(b){case'+':return'>';break;case'-':return'>';break;case'*':return'';break;case'#':return'>';break;}break;case'*':switch(b){case'+':return'>';break;case'-':return'>';break;case'*':return'>';break;case'/':return'>';break;case'(':return'';break;case'#':return'>';break;}break;case'/':switch(b){case'+':return'>'; break;case'-':return'>';break;case'*':return'>';break;case'/':return'>';break;case'(':return'';break;case'#':return'>';break;}break;case'(':switch(b){case'+':return'';b reak;case'-':return'>';break;case'*':return'>';break;case'/':return'>';break;case')':return'>';break;case'#':return'>';break;}break;case'#':switch(b)。

《数据结构课程设计》表达式求值实验报告

《数据结构课程设计》表达式求值实验报告

实验课程名称专业班级学生姓名学号指导教师20 至 20 学年第学期第至周算术表达式求值演示一、概述数据结构课程设计.要求学生在数据结构的逻辑特性和物理表示、数据结构的选择和应用、算法的设计及其实现等方面.加深对课程基本内容的理解。

同时.在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。

在这次的课程设计中我选择的题目是算术表达式求值演示。

表达式计算是实现程序设计语言的基本问题之一.也是栈的应用的一个典型例子。

设计一个程序.演示用算符优先法对算术表达式求值的过程。

深入了解栈和队列的特性.以便在解决实际问题中灵活运用它们.同时加深对这种结构的理解和认识。

二、系统分析1.以字符列的形式从终端输入语法正确的、不含变量的整数表达式。

利用已知的算符优先关系.实现对算术四则混合运算表达式的求值.并仿照教科书的例子在求值中运算符栈、运算数栈、输入字符和主要操作的变化过程。

2.一般来说.计算机解决一个具体问题时.需要经过几个步骤:首先要从具体问题抽象出一个适当的数学模型.然后设计一个解决此数学模型的算法.最后编出程序.进行测试.调试直至得到想要的答案。

对于算术表达式这个程序.主要利用栈.把运算的先后步骤进行分析并实现简单的运算!为实现算符优先算法.可以使用两个栈.一个用以寄存运算符.另一个用以寄存操作数和运算结果。

3.演示程序是以用户于计算机的对话方式执行.这需要一个模块来完成使用者与计算机语言的转化。

4.程序执行时的命令:本程序为了使用具体.采用菜单式的方式来完成程序的演示.几乎不用输入什么特殊的命令.只需按提示输入表达式即可。

(要注意输入时格式.否者可能会引起一些错误)5. 测试数据。

三、概要设计一个算术表达式中除了括号、界限符外.还包括运算数据和运算符。

由于运算符有优先级别之差.所以一个表达式的运算不可能总是从左至右的循序执行。

每次操作的数据或运算符都是最近输入的.这与栈的特性相吻合.故本课程设计借助栈来实现按运算符的优先级完成表达式的求值计算。

数据结构表达式求值实验报告

数据结构表达式求值实验报告

数据结构表达式求值实验报告数据结构表达式求值实验报告⒈引言本实验旨在研究和实现数据结构中表达式求值的算法。

表达式求值是计算机科学中常见的问题,对于计算机程序的正确性和性能具有重要影响。

本报告将详细介绍实验设计、实验步骤、实验结果及分析,并对实验过程中遇到的问题进行讨论。

⒉实验设计⑴实验目的本实验的目的是实现一个可以对常见的算术表达式进行求值的算法,包括支持基本的加减乘除运算符和括号。

⑵实验环境●操作系统:Windows 10●开发语言:C++●开发工具:Visual Studio 2019⑶数据结构设计为了实现表达式求值的算法,我们需要设计适当的数据结构来存储和处理表达式。

本实验中,我们选择使用栈来实现表达式求值。

●表达式栈:用于存储操作数和运算符。

●运算符栈:用于存储运算符。

⑷算法设计表达式求值的算法可以分为以下几个步骤:●遍历表达式,逐个处理操作数和运算符:●如果是操作数,入表达式栈。

●如果是运算符,与运算符栈栈顶元素进行比较,根据优先级决定如何处理。

●当表达式遍历完成后,依次处理剩余的运算符。

●最终表达式栈中的元素即为求值结果。

⒊实验步骤⑴数据结构实现根据设计,我们首先实现表达式栈和运算符栈的数据结构,包括入栈、出栈等操作。

⑵表达式输入与预处理用户输入待求值的表达式,进行预处理,去除空格、验证表达式的合法性等。

⑶表达式求值算法实现根据前述的算法设计,实现表达式求值的算法,利用表达式栈和运算符栈来处理表达式。

⑷测试与结果分析对于不同的测试用例,进行表达式求值的测试,并分析结果的正确性和性能。

⒋实验结果与分析经过实验测试,我们得到了表达式求值的结果。

结果显示,我们的算法能够正确地求得表达式的值,而且性能良好。

⒌讨论与总结在实验过程中,我们遇到了一些问题,并进行了讨论和解决。

通过这个实验,我们更加深入地理解了表达式求值的算法,并对数据结构的应用有了更清晰的认识。

附件:无法律名词及注释:●无。

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

清华大学数据结构课程实验报告(20 -20 学年第学期)报告题目:算术表达式求值任课老师:专业:学号:姓名:二0一年月日摘要:现代科学技术高速发展,各种高科技产品频频问世,而各种技术的基础都离不开基本的表达式求值,它虽然简单,但却是任何复杂系统的基本执行操作。

栈是一种重要的线性结构,从数据结构的角度看,它是一种特殊的线性表,具有先入先出的特点。

而算符优先法的设计恰巧符合先入先出的思想。

故我们基于栈这种数据结构,利用算符优先法,来实现简单算术表达式的求值。

关键字:算符优先法;算术表达式;数据结构;栈一、课题概述1、问题描述一个算术表达式是由运算数、运算符、界限符组成。

假设操作数是正整数,运算符只含有加“+”、减“-”、乘“*”、除“/”四种二元运算符,界限符有左括号“(”、右括号“)”和表达式起始、结束符“#”。

利用算符优先法对算术表达式求值。

2、设计目的(1)通过该算法的设计思想,熟悉栈的特点和应用方法;(2)通过对算符优先法对算术表达式求值的算法执行过程的演示,理解在执行相应栈的操作时的变化过程。

(3)通过程序设计,进一步熟悉栈的基本运算函数;(4)通过自己动手实现算法,加强从伪码算法到C语言程序的实现能力。

3、基本要求:(1)使用栈的顺序存储表示方式;(2)使用算符优先法;(3)用C语言实现;(4)从键盘输入一个符合要求的算术表达式,输出正确的结果。

4、编程实现平台Microsoft Visual C++ 6.0二、设计思路及采取方案1、设计思路:为了实现算符优先法,可以使用两个工作栈。

一个称做OPTR,用以寄存运算符;另一个称做OPND ,用以寄存操作数或运算结果。

算法的基本思想是:(1)首先置操作数栈为空栈,表达式起始符“#”作为运算符栈的栈底元素; (2)依次读入表达式中每个字符,若是操作数则进入OPND 栈,若是运算符则和OPTR 栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR 栈的栈顶元素和当前读入的字符均为“#”)。

算法中还调用了两个函数。

其中函数Precede 是判定运算符栈顶运算符1θ与读入的运算符2θ之间优先关系的函数;函数Operate 为进行二元运算b a θ的函数,如果是编译表达式,则产生这个运算的一组相应指令并返回存放结果的中间变量名;如果是解释执行表达式,则直接进行该运算,并返回运算结果。

2、方案设计(1)抽象数据类型定义 ADT Stack{数据对象:D={ i a | i a ∈ElemSet,i=1,2,…,n,, n ≧0} 数据对象:R1={<i a , 1-i a > | i a , 1-i a ∈D ,i=2,…,n} 约定n a 端为栈顶,i a 端为栈底。

基本操作: InitStack(&S)操作结果:构造一个空栈S 。

GetTop(S)初始条件:栈S 已存在。

操作结果:用P 返回S 的栈顶元素。

Push(&S, e)初始条件:栈S 已存在。

操作结果:插入元素e 为新的栈顶元素。

Pop(&S, e)初始条件:栈S 已存在。

操作结果:删除S 的栈顶元素,并用e 返回其值。

Precede(1c ,2c )初始条件:1c ,2c 为运算符。

操作结果:判断运算符优先权,返回表示优先权高低关系的“<”、“=”或“>”的字符。

Operate(a, OP, b)初始条件:a, b 为整数,OP 为运算符。

操作结果:a 与b 进行运算,OP 为二元运算符,返回其值。

}ADT Stack(2)符号之间的优先权关系比较1θ<2θ:1θ的优先权低于2θ: 1θ=2θ:1θ的优先权等于2θ(3)顺序栈的定义 typedef struct { SElemType *base; SElemType *top;int stacksize;}SqStack; (4)调用函数:void InitStack(SqStack *S) //构造空栈 SElemType GetTop(SqStack *S) //用e 返回栈顶元素 SElemType Push(SqStack *S, SElemType e)//插入e 为新的栈顶元素SElemType Pop(SqStack *S) //删除栈顶元素int jiancha1(char e) //判断e是运算符还是运算数void jiancha2(char e) //判断e是否为合法的运算符或运算数SElemType Precede(char g, char h) //优先权比较float Operate(float s,char yunsuanfu,float t) //返回二元运算结果三、实验结果测试表达式及对应运行结果1、“3+6#”结果为92、“(7-5)*3#”结果为63、“8/4#”结果为2.四、心得体会1、算符优先法是教材上有关栈的应用的一个具体实例,考虑到算符优先法中对于运算符的操作是先入先出的,正好符合栈这种结构的存储使用规则,于是我们便可以利用栈来实现算法2、由于教材上给出的存储结构定义、函数等都是伪码,不是可执行的程序代码,故需要从程序语言(C语言)角度考虑,将伪码转换成程序代码。

而这是不是一个简单的工作。

编写程序的过程需要非常的小心仔细,任何一个细小的错误,都会导致程序的运行失败。

在写好程序第一次编译时,我的程序出现了将近80条错误,经过两天的检查、调试以及和同学的讨论,我的程序才最终通过编译,成功运行。

比如在定义字符常量时,#define STACK_INIT_SIZE 100和#define STACKINCREMENT 10这两个语句的句末是不能加分号的,这个问题我花了两个多小时才发现。

3、经过自己动手编写这个有关栈的程序,我发现自己对栈的理解更加完全、更加深刻了。

对于栈的逻辑结构、存储结构、操作函数、应用以及具体实现,我有一种豁然开朗的感觉。

4、此算法只能进行个位数的加减乘除运算,对两位及以上数不能操作,。

因此算符优先法对算术表达式求值存在很大的局限性。

若要完善算术表达式求值,应该完善算法,或者换用其它算法来实现。

五、参考文献【1】严蔚敏,吴伟民. 数据结构(C语言版). 北京:清华大学出版社,2007【2】李春葆. 数据结构教程(第3版)上机实验指导. 北京:清华大学出版社,2009 【3】谭浩强. C程序设计(第四版).北京:清华大学出版社六、附录C语言程序代码及部分注释#include<stdio.h>#include<stdlib.h>#define ERROR 0;#define STACK_INIT_SIZE 100#define STACKINCREMENT 10int flag=0; //flag标记输入字符是否合法typedef struct{float *base;float *top;int stacksize;}SqStack; //存放运算数的栈的顺序存储表示typedef struct{char *base;char *top;int stacksize;}sqStack; //存放运算符的栈的顺序存储表示void InitStack(SqStack *S) //构造空栈(运算数栈){S->base=(float*)malloc((STACK_INIT_SIZE)*sizeof(float));S->top=S->base;S->stacksize=STACK_INIT_SIZE;}void initStack(sqStack *S) //构造空栈(运算符栈){S->base=(char*)malloc((STACK_INIT_SIZE)*sizeof(char));S->top=S->base;S->stacksize=STACK_INIT_SIZE;}float GetTop(SqStack *S) //用e返回栈顶元素(运算数){float e;if(S->top==S->base) return ERROR;e=*(S->top-1);return e;}char getTop(sqStack *S) //用e返回栈顶元素(运算符){char e;if(S->top==S->base) return ERROR;e=*(S->top-1);return e;}float Push(SqStack *S,float e) //插入e为新的栈顶元素(运算数){if(S->top-S->base>=S->stacksize){S->base=(float*)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(float));S->top=S->base+S->stacksize;S->stacksize+=STACKINCREMENT;}*S->top++=e;return e;}char push(sqStack *S,char e) //插入e为新的栈顶元素(运算符){if(S->top-S->base>=S->stacksize){S->base=(char*)realloc(S->base,(S->stacksize+STACKINCREMENT )*sizeof(char));S->top=S->base+S->stacksize;S->stacksize+=STACKINCREMENT;}*(S->top)=e;(S->top)++;return e;}float Pop(SqStack *S) //删除栈顶元素(运算数){float e;if(S->top==S->base) return ERROR;(S->top)--;e=*(S->top);return e;}char pop(sqStack *S) //删除栈顶元素(运算符){char e;if(S->top==S->base) return ERROR;(S->top)--;e=*(S->top);return e;}int jiancha1(char e) //判断e是运算符还是运算数{if(e!='+'&&e!='-'&&e!='*'&&e!='/'&&e!='('&&e!=')'&&e!='#')return 1;else return 0;}void jiancha2(char e) //判断e是否为合法的运算符或运算数{if(e==48||e==49||e==50||e==51||e==52||e==53||e==54||e==55||e==56||e==57) flag=1;elseif(e=='+'||e=='-'||e=='*'||e=='/'||e=='('||e==')'||e=='#')flag=1;else flag=0;}char Precede(char p,char q) //优先级比较函数{switch(p){case'+':if((q=='*')||(q=='/')||(q=='(')) return'<';else return '>';break;case'-':if((q=='*')||(q=='/')||(q=='(')) return'<';else return '>';break;case'*':if(q=='(') return '<'; else return '>';break;case'/':if(q=='(') return '<'; else return '>';break;case'(':if(q==')') return '='; else if(q=='#') return ' '; else return '<';break;case')':if(q=='(') return ' '; else return '>';break;case'#':if(q=='#') return '='; else if(q==')') return ' '; else return '<';break;default: printf("你的输入非法\n");}}float Operate(float s,char yunsuanfu,float t) //二元运算操作{float r;switch(yunsuanfu){case'+':r=s+t;break;case'-':r=s-t;break;case'*':r=s*t;break;case'/':if(t!=0)r=s/t;else printf("分母不能为零!");break;default:printf("Sorry,您的输入有误!");}return r;}void main() //主函数部分{char c,x,theta;float a,b;sqStack OPTR;SqStack OPND;initStack(&OPTR);push(&OPTR,'#');InitStack(&OPND);printf("输入一个以“#”结束的算数表达式:\n\n");c=getchar();jiancha2(c);while(flag&&(c!='#'||getTop(&OPTR)!='#')){if(jiancha1(c)){float cc;cc=(float)(c-48);Push(&OPND,cc);c=getchar();jiancha2(c);}else{x=Precede(getTop(&OPTR),c);switch(x){case'<':push(&OPTR,c);c=getchar();jiancha2(c);break;case'=':pop(&OPTR);c=getchar();jiancha2(c);break;case'>':theta=pop(&OPTR);b=Pop(&OPND);a=Pop(&OPND);Push(&OPND,Operate(a,theta,b));break;}}}if(flag==1) printf("\n计算所得结果是: %f\n",GetTop(&OPND));else if(flag==0) printf("\nSorry,您的输入有错误!\n");}。

相关文档
最新文档