《数据结构课程设计》表达式求值实验报告.docx
数据结构课程设计表达式求值实验报告 实验课程名称 专业班级 学生姓名 学号 指导教师 20 至 20 学年第学期第至周 算术表达式求值演示 一、概述 数据结构课程设计.要求学生在数据结构的逻辑特性和物理表示、数据结构的选择和应用、算法的设计及其实现等方面.加深对课程基本内容的理解。同时.在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。 在这次的课程设计中我选择的题目是算术表达式求值演示。表达式计算是实现程序设计语言的基本问题之一.也是栈的应用的一个典型例子。设计一个程序.演示用算符优先法对算术表达式求值的过程。深入了解栈和队列的特性.以便在解决实际问题中灵活运用它们.同时加深对这种结构的理解和认识。 二、系统分析 1以字符列的形式从终端输入语法正确的、不含变量的整数表达式。利用已知的算符优先关系.实现对算术四则混合运算表达式的求值.并仿照教科书的例子在求值中运算符栈、运算数栈、输入字符和主要操作的变化过程。 2一般来说.计算机解决一个具体问题时.需要经过几个步骤:首先要从具体问题抽象出一个适当的数学模型.然后设计一个解决此数学模型的算法.最后编出程序.进行测试. 调试直至得到想要的答案。对于算术表达式这个程序.主要利用栈.把运算的先后步骤进行分析并实现简单的运算!为实现算符优先算法.可以使用两个栈.一个用以寄存运算符.另一个用以寄存操作数和运算结果。 3演示程序是以用户于计算机的对话方式执行.这需要一个模块来完成使用者与计算机语言的转化。 4程序执行时的命令: 本程序为了使用具体.采用菜单式的方式来完成程序的演示.几乎不用输入什么特殊的命令.只需按提示输入表达式即可。(要注意输入时格式.否者可能会引起一些错误)5. 测试数据。 三、概要设计 一个算术表达式中除了括号、界限符外.还包括运算数据和运算符。由于运算符有优先级别之差.所以一个表达式的运算不可能总是从左至右的循序执行。每次操作的数据或运算符都是最近输入的.这与栈的特性相吻合.故本课程设计借助栈来实现按运算符的优先级完成表达式的求值计算。 算法设计 程序包含三个模块 (1) 主程序模块.其中主函数为 void main 输入表达式; 根据要求进行转换并求值; 输出结果; (2) 表达式求值模块实现具体求值。 (3) 表达式转换模块实现转换。 各个函数之间的调用关系 栈的抽象数据类型定义ADT SqStack 主函数 表达式转换表达式求值 数据输入 输出输出 数据对象:D=a i| a iElemSet,i=1,2,3.n,n0 数据关系:R1=| a i-1,a iD,i=1,2,3,.n 约定其中a i端为栈底.a n端为栈顶。 操作集合: (1)void InitStack1(SqStack1 &S1);/声明栈建立函数 (2)void InitStack2(SqStack2 &S2);/声明栈建立函数 (3)void evaluate(SqStack1 &S1,SqStack2 &S2);/确定如何入栈函数 (4)void Push1(SqStack1 &S1,char e);/声明入栈函数 (5)void Push2(SqStack2 &S2,float e);/声明入压栈函数 (6)char GetTop1(SqStack1 &S1);/声明取栈顶元素函数 (7)float GetTop2(SqStack2 &S2);/声明取栈顶元素函数 (8)char Pop1(SqStack1 &S1);/声明出栈函数 (9)float Pop2(SqStack2 &S2);/声明出栈函数 (10)char Compare(char m,char n);/声明比较函数 (11)float Operate(float a,char rheta,float b);/声明运算函数 (12)void DispStack1(SqStack1 &S1);/从栈底到栈顶依次输出各元素 (13)void DispStack2(SqStack2 &S2);/从栈底到栈顶依次输出各元素 ADT SqStack 结构分析: 栈中的数据节点是通过数组来存储的。因为在C语言中数组是用下标从零开始的.因此我们在调用他们的数据是要特别注意。指针变量的值要么为空(NULL).不指向任何结点;要么其值为非空.即它的值是一个结点的存储地址。注意.当P为空值时.则它不指向任何结点.此时不能通过P来访问结点.否则会引起程序错误。如果输入的数字不符合题目要求.则会产生错误结果。 算法的时空分析: 时间和空间性能分析:时间上.对于含n个字符的表达式.无论是对其进行合法性检测还是对其进行入栈出栈操作n次.因此其时间复杂度为O(n)。空间上.由于是用数组来存储输入的表达式.用栈来存储运算中的数据和运算符.而栈的本质也用到的数组.数组在定义时必须确定其大小。在不知表达式长度的情况下确定数组的长度确非易事.此时极易造成空间的浪费.因此空间性能不是很好。 四、详细设计 源程序 #include using namespace std; #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 typedef struct /运算符栈 char *base; char *top; int stacksize; SqStack1; typedef struct /运算数栈 float *base; float *top; int stacksize; SqStack2; void InitStack1(SqStack1 &S1);/声明栈建立函数 void InitStack2(SqStack2 &S2);/声明栈建立函数 void evaluate(SqStack1 &S1,SqStack2 &S2);/确定如何入栈函数void Push1(SqStack1 &S1,char e);/声明入栈函数 void Push2(SqStack2 &S2,float e);/声明入压栈函数 char GetTop1(SqStack1 &S1);/声明取栈顶元素函数 float GetTop2(SqStack2 &S2);/声明取栈顶元素函数 char Pop1(SqStack1 &S1);/声明出栈函数 float Pop2(SqStack2 &S2);/声明出栈函数 char Compare(char m,char n);/声明比较函数 float Operate(float a,char rheta,float b);/声明运算函数void DispStack1(SqStack1 &S1);/从栈底到栈顶依次输出各元素void DispStack2(SqStack2 &S2);/从栈底到栈顶依次输出各元素 /*主函数*/ void main() SqStack1 S1;/定义运算符栈 SqStack2 S2;/定义运算数栈 /freopen("data1.in","r",stdin); /freopen("data1.out","w",stdout); InitStack1(S1);/调用栈建立函数 InitStack2(S2);/调用栈建立函数 evaluate(S1,S2);/调用确定如何入栈函数 cout=S1.stacksize)/如果栈满.追加存储空间 S1.base=(char *)realloc(S1.base,(S1.stacksize+STACKINCREMENT)*sizeof(char); if(!S1.base) cout=S2.stacksize)/栈满.追加存储空间 S2.base=(float *)realloc(S2.base,(S2.stacksize+STACKINCREMENT)*sizeof(float); if(!S2.base)cout>ch; c=ch0; cout=0) e=float(c-48); n+; if(n=1)t=e; else if(n>1)t=t*10+e; c=chs+; if(n=-1) e=float(c-48); t=t+e/10; c=chs+; if(c='.') n=-1; c=chs+; if(c>='0'&&c':/栈顶元素优先级高.则退栈并将运算结果入栈 p1=Pop2(S2); p2=Pop2(S2); ch1=Pop1(S1); Push2(S2,Operate(p2,ch1,p1); cout'/否则.栈顶符号优先级高,返回">" else if(n='*'|n='/')/输入的符号为"*"、"/" if(m=')'|m='*'|m='/')return '>'/栈顶元素为")"、"*"、"/",此时栈顶符号优先级高.返回">" else return ''/否则.栈顶符号优先级高,返回">" else /输入符号为其他 if(m='#')return'='/栈顶元素为"#",此时优先级同.返回"=" else return '>'/否则.栈顶符号优先级高,返回">" float Operate(float a,char theta,float b)/运算函数 float tmp=0; if (theta='+')tmp=a+b;/从运算符栈取出的符号为"+".则运算数栈的两元素相加.并返回 else if(theta='-')tmp=a-b;/从运算符栈取出的符号为"-".则运算数栈的两元素相减.并返回