吕明远数据结构课程设计报告.docx
- 文档编号:23054244
- 上传时间:2023-04-30
- 格式:DOCX
- 页数:19
- 大小:118.37KB
吕明远数据结构课程设计报告.docx
《吕明远数据结构课程设计报告.docx》由会员分享,可在线阅读,更多相关《吕明远数据结构课程设计报告.docx(19页珍藏版)》请在冰豆网上搜索。
吕明远数据结构课程设计报告
软件学院
课程设计报告书
课程名称数据结构
设计题目算术表达式求值演示程序
专业班级软件09-6班
学号0920010614
姓名吕明远
指导教师孙宁
2010年12月
目录
1.设计时间2
2.设计目的2
3.设计任务2
4.设计内容2
4.1需求分析2
4.2总体设计2
4.2.1抽象数据类型定义2
4.2.2函数模块说明3
4.2.3主函数流程图4
4.2.4函数模块调用关系5
4.2.5运算符间的优先关系5
4.3详细设计6
4.3.1数据类型的定义6
4.3.2函数调用关系8
4.3.3主要模块的算法描述8
4.4测试与分析10
4.4.1测试10
4.4.2分析11
4.5附录11
5.总结与展望16
参考文献17
成绩评定17
1设计时间
2010.12.27-2011.1.3
2设计目的
掌握栈的使用和把一个表达式翻译成能够正确求值的一个机器指令序列的原理。
3设计任务
设计一个程序,演示用算符优先法对算术表达式求值的过程。
4设计内容
4.1需求分析
1、程序所能达到的功能:
能够处理以字符序列的形式输入的不含变量的实数表达式,正确处理负数与小数,判断表达式是还语法正确(包含分母不能为零的情况),正确实现对算术四则混合运算表达式的求值,能够将计算中遇到的问题和结果以文件的形式予以存储。
2、输入的形式和输入值的范围:
以字符串的形式输入表达式,以“#”结束。
3、输出的形式:
在计算过程中遇到的问题或最终的答案将显示在屏幕上,同时所计算的表达式的最终的结果也将保存在文件中。
4、测试数据:
输入“3*(7-2)#”时,输出“15.000000”,测试正确;输入“!
(9-2)#”时,输出“输入错误!
”,测试正确。
4.2总体设计
4.2.1抽象数据类型定义
ADTStack{
数据对象:
D={
|
∈ElemSet,i=1,2,…,n,n≧0}
数据对象:
R1={<
>|
i=2,…,n}
约定
端为栈顶,
端为栈底。
基本操作:
InitStack(&S)
操作结果:
构造一个空栈S。
GetTop(S)
初始条件:
栈S已存在。
操作结果:
用P返回S的栈顶元素。
Push(&S,ch)
初始条件:
栈S已存在。
操作结果:
插入元素ch为新的栈顶元素。
Pop(&S)
初始条件:
栈S已存在。
操作结果:
删除S的栈顶元素。
In(ch)
操作结果:
判断字符是否是运算符,运算符即返回1。
Precede(c1,c2)
初始条件:
c1,c2为运算符。
操作结果:
判断运算符优先权,返回优先权高的。
Operate(a,op,b)
初始条件:
a,b为整数,op为运算符。
操作结果:
a与b进行运算,op为运算符,返回其值。
num(n)
操作结果:
返回操作数的长度。
EvalExpr()
初始条件:
输入表达式合法。
操作结果:
返回表达式的最终结果。
}ADTStack
4.2.2函数模块说明
为实现算符优先算法,可以使用两个工作栈。
一个称做OPTR,用以寄存运算符;另一个称做OPND,用以寄存操作数或运算结果。
算法的基本思想是:
(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈底元素
(2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)。
算法中还调用了两个函数。
其中Precede是判定运算符栈顶运算符θ1与读入的运算符θ2之间优先关系的函数;Operateo为进行二元运算aθb的函数,如果是编译表达式,则产生这个运算的一组相应指令并返回存放结果的中间变量名;如果是解释执行表达式,则直接进行该运算,并返回运算结果。
4.2.3主函数流程图
4.2.4函数模块调用关系
4.2.5运算符间的优先关系
θ1θ2
+
-
*
/
(
)
#
+
>
>
>
<
<
>
>
-
>
>
>
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>
>
<
>
>
(
<
<
<
<
<
=
)
>
>
>
>
>
>
#
<
<
<
<
<
=
4.3详细设计
4.3.1数据类型的定义及基本操作
//=====ADTStack的表示与实现=====
//-----栈的顺序存储表示-----
#defineSTACK_INIT_SIZT100;
#defineSTACKINCREMENT10
typedefstruct{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
//-----基本操作的算法描述-----
StatusInitStack(SqStack&S){
S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
S.base)exit(OVERFLOW);
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
returnOK;
}
StatusGetTop(SqStackS,SElemType&e){
if(S.top==S.base)returnERROR;
e=*(S.top-1);
returnOK;
}
StatusPush(SqStack&S,SElemTypee){
if(S.top-S.base>=S.stacksize){
S.base=(SElemType*)realloc(S.base
(S.StackSize+STACKINCREMENT)*sizeof(SElemType));
if(!
S.base)exit(OVERFLOW);
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
returnOK;
}
StatusPop(SqStack&S,SElemType&e){
if(S.top==S.base)returnERROR;
e=*--S.top;
returnOK;
}
OperandTypeEvaluateExpession(){
InitStack(OPTR);Push(OPTR,’#’);
InitStack(OPND);c=getchar();
while(c!
’#’||GetTop(OPTR)!
=’#’){
if(!
In(c,OP)){Push((OPND,c);c=getchar();)
else
switch(Precede(GetTop(OPTR),c)){
case’<’:
Push(OPTR,c);c=getchar();break;
case’=’:
Pop(OPTR,x);c=getchar();break;
case’>’:
Pop(OPTR,theta);Pop(OPND,b);Pop(OPND,a);
Push(OPND,Operate(a,theta,b));break;
}
}
}
4.3.2函数调用关系
4.3.3主要模块的算法描述
voidmain(){
SqStack_TOPTR;SqStack_NOPND;
floata,b,i;chartheta,c,x;
InitStack_T(&OPTR);Push_T(&OPTR,’#’);
InitStack_N(&OPND);
printf(“请输入表达式关以’#’结尾:
\n”);
c=getchar();
if(c==35||(c>=40&&c<=43)||c==45||(c>=47&&c<=57))
{
while(c!
=’#’||GetTop_T(&OPTR)!
=’#’)
{
if(c>=48&&c<=57)
{
i=(float)c-48;
Push_N(&OPND,i);
c=getchar();
}
else
{
switch(Precede(GetTop_T(&OPND),c))
{
case’<’:
Push_T(&OPTR,c);c=getchar();break;
case’=’:
x=Pop_T(&OPTR);c=getchar();break;
case’>’:
theat=Pop_T(&OPTR);b=Pop_N(&OPND);
a=Pop_N(&OPND);Push_N(&OPND,Operate(a,theta,b));
break;
}
}
}
printf(“结果是%f\n”,GetTop_N(&OPND));
}
elseprintf(“输入错误!
\n”);
}
4.4测试与分析
4.4.1测试
加法测试,输入正确,输出正确,测试正确:
减法测试,输入正确,输出正确,测试正确:
乘法测试,输入正确,输出正确,测试正确:
除法测试,输入正确,输出正确,测试正确:
输入表达式正确,输出正确,测试正确:
输入表达式错误,能正确判断,测试正确:
4.4.2分析
内容包括:
1、调试过程中遇到的问题是如何解决的以及对设计与实现的回顾讨论和分析:
遇到的问题:
调试过程中遇到了输入非法字符不输出“错误!
”的情况。
解决的办法:
查ASCII码表得知运算符’+’,’-‘,’*’,’/’,’(‘,’)’,’#’和运算数’0’,’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’相应的ASCII值。
在主程序中加入了判断语句,判断输入的是否为运算符或运算数。
如果是,则进行正常运算;如果不是,则返回错误。
2、算法的时间复杂度和空间复杂度的分析:
中缀表达式运算时间主要用在字符串扫描和算符优先权的比较上。
把#看作运算符,操作数与运算符个数相同,最坏情况下优先级比较是n/2次,即运算顺序完全是逆序的,每个字符扫描一遍是O(n)的,所以整个算法复杂度是O(n2)的。
算法中用到两个栈,分别为O(n/2),其算法空间复杂度是O(n)。
4.5附录
#include"stdio.h"
#include"stdlib.h"
#defineOK1
#defineERROR0
#defineOVERFLOW0
#defineSTACK_INIT_SIZE100
#defineSTACKINCREMENT10
typedefstruct{
char*base;
char*top;
intstacksize;
}SqStack_T;
typedefstruct{
float*base;
float*top;
intstacksize;
}SqStack_N;
voidInitStack_T(SqStack_T*S){
(*S).base=(char*)malloc(STACK_INIT_SIZE*sizeof(char));
if(!
(*S).base)exit(OVERFLOW);
(*S).top=(*S).base;
(*S).stacksize=STACK_INIT_SIZE;
}
voidInitStack_N(SqStack_N*S){
(*S).base=(float*)malloc(STACK_INIT_SIZE*sizeof(float));
if(!
(*S).base)exit(OVERFLOW);
(*S).top=(*S).base;
(*S).stacksize=STACK_INIT_SIZE;
}
charGetTop_T(SqStack_T*S){
chare;
if((*S).top==(*S).base)returnERROR;
e=*((*S).top-1);
returne;
}
floatGetTop_N(SqStack_N*S){
floate;
if((*S).top==(*S).base)returnERROR;
e=*((*S).top-1);
returne;
}
charPush_T(SqStack_T*S,chare){
if((*S).top-(*S).base>=(*S).stacksize){
(*S).base=(char
*)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(char));
if(!
(*S).base)exit(OVERFLOW);
(*S).top=(*S).base+(*S).stacksize;
(*S).stacksize+=STACKINCREMENT;
}
*((*S).top)++=e;
returnOK;
}
floatPush_N(SqStack_N*S,floate){
if((*S).top-(*S).base>=(*S).stacksize){
(*S).base=(float
*)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(float));
if(!
(*S).base)exit(OVERFLOW);
(*S).top=(*S).base+(*S).stacksize;
(*S).stacksize+=STACKINCREMENT;
}
*((*S).top)++=e;
returnOK;
}
charPop_T(SqStack_T*S){
chare;
if((*S).top==(*S).base)returnERROR;
e=*(--(*S).top);
returne;
}
floatPop_N(SqStack_N*S){
floate;
if((*S).top==(*S).base)returnERROR;
e=*(--(*S).top);
returne;
}
charm[7]="+-*/()#";
charn[7][7]={">><<<>>",">><<<>>",">>>><>>",">>>><>>","<<<<<="
">>>>>>","<<<<<="};
charPrecede(chara,charb){
inti=0,j=0;
while(m[i]!
=a)
i++;
while(m[j]!
=b)
j++;
return(n[i][j]);
}
floatOperate(floata,chartheta,floatb){
floatr;
switch(theta){
case'+':
r=a+b;break;
case'-':
r=a-b;break;
case'*':
r=a*b;break;
case'/':
if(b!
=0)r=a/b;
elseprintf("输入错误!
");
break;
}
returnr;
}
voidmain(){
SqStack_TOPTR;
SqStack_NOPND;
floata,b,i;
chartheta,c,x;
InitStack_T(&OPTR);Push_T(&OPTR,'#');
InitStack_N(&OPND);
printf("请输入表达式并以'#'结尾:
\n");
c=getchar();
if(c==35||(c>=40&&c<=43)||c==45||(c>=47&&c<=57))
{
while(c!
='#'||GetTop_T(&OPTR)!
='#')
{
if(c>=48&&c<=57)
{
i=(float)c-48;
Push_N(&OPND,i);
c=getchar();
}
else
{
switch(Precede(GetTop_T(&OPTR),c))
{
case'<':
Push_T(&OPTR,c);c=getchar();break;
case'=':
x=Pop_T(&OPTR);c=getchar();break;
case'>':
theta=Pop_T(&OPTR);b=Pop_N(&OPND);
a=Pop_N(&OPND);
Push_N(&OPND,Operate(a,theta,b));break;
}
}
}printf("结果是%f\n",GetTop_N(&OPND));
}
elseprintf("输入错误!
\n");
}
}
5总结与展望
通过这段时间的课程设计,本人对计算机的应用、数据结构的作用以及C语言的使用都有了更深的了解。
当然也遇到不少问题,也正是国为这些问题引发的思考给我带来了收获。
从当初不喜欢上机写程序到现在能主动写程序,从当初拿着程序不知从何下手到现在知道如何分析问题,如何用专业知识解决实际问题的转变。
我发现无论是专业知识还是动手能力,自己都有很大程度的提高。
在实际上机操作过程中,不仅是让我们了解数据结构的理论知识,更重要的是培养解决实际问题的能力,为后续课程的学习及实践打下良好的基础。
这次课程设计让我更加了解大一学到的C和这个学期学到的数据结构的紧密联系。
设计题目不仅要求设计者对课本知识有较深刻的了解,同时要有较强的思维动手能力。
这次的课程设计让我有一个深刻的体会:
严谨!
编程最需要的就是严谨,往往检查到的错误是在某个括号、分号、引号等不应该犯错的地方上。
程序设计时难免遇到错误,但这不是坏事情,它可以让我发现自己的薄弱环节,在具体操作中还可以巩固所学的C及数据结构。
更加体会到了C的语句简洁、使用灵活、执行效率高等特点。
参考文献
[1]严蔚敏.吴伟民.数据结构(C语言版).北京:
清华大学出版社,2007
[2]谭浩强著.C程序设计(第二版).北京:
清华大学出版社,2005
成绩评定
成绩教师签字
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 吕明远 数据结构 课程设计 报告