数据结构课程设计.docx
《数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计.docx(22页珍藏版)》请在冰豆网上搜索。
数据结构课程设计
内蒙古科技大学
本科生课程设计论文
题目:
数据结构课程设计
——算术表达式求值
学生姓名:
董雪
学号:
1176807442
专业:
计算机科学与技术
班级:
11级四班
指导教师:
王丽颖
2013年5月29日
目录
第一章需求分析-1-
1.1引言-1-
1.2任务概述-1-
1.3数据描述-1-
1.4功能需求-2-
1.5运行需求-2-
1.6任务计划-2-
第二章概要设计-3-
2.1总体设计-3-
2.2抽象数据类型定义-3-
2.3接口设计-4-
2.4运行界面设计-5-
第三章详细设计-7-
3.1主函数-7-
3.2计算leftorright的值-8-
3.3计算的实现过程-9-
3.4运算符的比较-10-
3.5主界面的实现-12-
第四章测试分析-14-
4.1测试程序执行情况-14-
第五章课程设计总结-16-
参考文献-16-
附录:
程序代码-17-
致谢………………………………………………………………………-23-
内蒙古科技大学课程设计任务书
课程名称
数据结构课程设计
设计题目
算术表达式求值
指导教师
王丽颖
时间
2013.5.20——2013.5.30
一、教学要求
1.掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力
2.初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能
3.提高综合运用所学的理论知识和方法独立分析和解决问题的能力
4.训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风
二、设计资料及参数
每个学生在教师提供的课程设计题目中任意选择一题,独立完成,题目选定后不可更换。
算术表达式求值
以字符串表示算术表达式,在此基础上借助栈完成对表达式的转换和求值操作。
要求设计类(或类模板)来描述算术表达式及其操作,包含必要的构造函数和析构函数,以及其他能够完成如下功能的成员函数:
v输入算术表达式(中缀表示)
v中缀表达式转换为后缀表达式
v输出表达式
v对后缀表达式求值
并设计主函数测试该类。
三、设计要求及成果
1.分析课程设计题目的要求
2.写出详细设计说明
3.编写程序代码,调试程序使其能正确运行
4.设计完成的软件要便于操作和使用
5.设计完成后提交课程设计报告
四、进度安排
资料查阅与讨论(1天)
系统分析(2天)
系统的开发与测试(5天)
编写课程设计说明书和验收(2天)
五、评分标准
1.根据平时上机考勤、表现和进度,教师将每天点名和检查
2.根据课程设计完成情况,必须有可运行的软件。
3.根据课程设计报告的质量,如有雷同,则所有雷同的所有人均判为不及格。
4.根据答辩的情况,应能够以清晰的思路和准确、简练的语言叙述自己的设计和回答教师的提问
六、建议参考资料
1.《数据结构(C语言版)》严蔚敏、吴伟民主编清华大学出版社2004.11
2.《数据结构课程设计案例精编(用C/C++描述)》,李建学等编著,清华大学出版社2007.2
3.《数据结构:
用面向对象方法与C++语言描述》,殷人昆主编, 清华大学出版社2007.6
第一章需求分析
1.1引言
在计算机中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。
因而在程序设计时,借助栈实现。
算法输入:
一个算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。
为简化,规定操作数只能为正整数,操作符为+、-、*、/,用#表示结束。
算法输出:
表达式运算结果。
算法要点:
设置运算符栈和运算数栈辅助分析算符优先关系。
在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。
1.2任务概述
编写一个简单的算术表达式求值程序,能实现对表达式的求值。
要求:
输入一个算术表达式,其中包含有数字,加、减、乘、除号、括号,能根据四则运算法则计算出正确结果。
例如:
3+5*6a.从左算到右b.先乘除,后加减c.先括号内,后括号外
1.3数据描述
Classinfix2postfix类中定义了Stackstk存储运算符的堆栈
Infix2postfix()Infix2postfix(conststring&infixexp)Postfixexp()
Set_priority()setlnficexp(constshring&infixexp)
ClassSetPostfixEval类中定义了Stackstk存放操作数的对栈
Intevaluate()
Intcomputer()
1.4功能需求
算术表达式求值
以字符串表示算术表达式,在此基础上借助栈完成对表达式的转换和求值操作。
要求设计类(或类模板)来描述算术表达式及其操作,包含必要的构造函数和析构函数,以及其他能够完成如下功能的成员函数:
v输入算术表达式(中缀表示)
v中缀表达式转换为后缀表达式
v输出表达式
v对后缀表达式求值
1.5运行需求
可以再MS-DOS下运行的,C++编写的程序
1.6任务计划
程序是进行算术表达式的求值,可以根据运算符的优先级来计算表达式的值。
输入为实型数字与+,—,*,/,()这些字符。
输出为计算结果(实型),输入范围为double范围。
程序可以根据预先定义好的运算符的优先级来计算算术表达式的值。
测试数据(2+1)*5=15
第二章概要设计
2.1总体设计
为实现算符优先算法,可以使用两个工作栈。
一个称做OPTR,用以寄存运算符;另一个称做OPND,用以寄存操作数或运算结果。
算法的基本思想是:
(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈底元素
(2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)
2.2抽象数据类型定义
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
2.3接口设计
函数名
函数格式//即函数首部
函数功能
infix2postfix()
infix2postfix(){}
构造函数
setInfixExp
voidsetInfixExp()
设置中缀表达式
String
postfixExp()
stringpostfixExp()
求取并返回后缀表达式
Stringpostfix
Stringpostfix
设置后缀表达式
Stringinfix
Stringinfix
用于转换的中缀表达式
Set_priority
VoidSet_priority()
设置运算符优先级
postfixEval()
postfixEval(){}
设置后缀表达式
Getoperands
voidGetoperands()
从堆栈中取操作数
evaluate()
intevaluate()
计算后缀表达式并返回其值
computer()
intcomputer()
计算表达式“leftopright”的值
Voidmain
Voidmain
实现各函数的测试
表2.1:
函数列表
2.4运行界面设计
图2.1函数模块调用关系流程图
θ1θ2
+
-
*
/
(
)
#
+
>
>
>
<
<
>
>
-
>
>
>
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>
>
<
>
>
(
<
<
<
<
<
=
)
>
>
>
>
>
>
#
<
<
<
<
<
=
表2.2运算符间的优先关系
第三章详细设计
3.1主函数
classinfix2postfix
{
public:
infix2postfix(){}
infix2postfix(conststring&infixExp):
infix(infixExp){}
voidsetInfixExp(conststring&infixExp){infix=infixExp;}
stringpostfixExp();
private:
stringinfix;
stringpostfix;
stackstk;
mapoper_prio,oper_prio_out;
voidset_priority();//设置运算符('+'、'-'、'*'、'/'、'%'、'^')的优先级
};
postfixEval
classpostfixEval
{
public:
postfixEval(){};
voidsetPostfixExp(conststring&postfixExp){postfix=postfixExp;};
intevaluate();
private:
stringpostfix;//待求值的后缀表达式
stackstk;//存放操作数的堆栈
voidgetOperands(int&left,int&right);
intcompute(intleft,intright,charop)const;
boolisOperator(charch)const;
};
3.2计算leftorright的值
intpostfixEval:
:
compute(intleft,intright,charop)const
{
intvalue;
switch(op)
{
case'+':
value=left+right;
break;
case'-':
value=left-right;
break;
case'*':
value=left*right;
break;
case'/':
if(right==0)
cout<<"postfixEval出现除0错误"<value=left/right;
break;
case'%':
if(right==0)
cout<<"postfixEval出现除0错误"<value=left%right;
break;
case'^':
if(left==0&&right==0)
cout<<"postfixEval出现未定义的0^0现象"<value=1;
while(right>0)
{
value*=left;
right--;
}
break;
}//endswitch
returnvalue;
}
3.3计算的实现过程
intpostfixEval:
:
evaluate()
{
inti,left,right,expValue;
charch;
for(i=0;i{
ch=postfix[i];
if(isdigit(ch))
stk.push(ch-'0');
elseif(isOperator(ch))
{
getOperands(left,right);
stk.push(compute(left,right,ch));
}//endif
}//endfor
expValue=stk.top();stk.pop();
returnexpValue;
}
3.4运算符的比较
stringinfix2postfix:
:
postfixExp()
{
postfix="";
set_priority();
stk.push("#");
inti=0;
stringinput,topstk;
for(;i{topstk=stk.top();
input=infix.substr(i,1);
if(!
oper_prio[input])
postfix+=input;
else
{
if(oper_prio[input]>oper_prio[topstk])
{
if(pare(")")==0)
{
while(pare("(")!
=0)
{
postfix+=topstk;
stk.pop();
topstk=stk.top();
}//endwhile
stk.pop();
}
else
stk.push(input);
}
else
{
if(pare("(")!
=0)
{
postfix+=topstk;
stk.pop();
continue;
};//endif
stk.push(input);
}//endif
}//endelse
//取infix的下一个元素输入
++i;
}//endfor
//将运算符栈中剩余的符号pop出栈,直至遇到保护标志“#”
topstk=stk.top();
while(pare("#")!
=0)
{
postfix+=topstk;
stk.pop();
topstk=stk.top();
}//endwhile
returnpostfix;
}
3.5主界面的实现
voidmain()
{
infix2postfixiexp;
stringinfix,postfix;
postfixEvalpexp;
cout<<"**本程序模拟一位数的中缀表达式转化为后缀表达式及其运算**"<cout<<"****学号:
1176807442姓名:
董雪****"<cout<<"请输入一个一位数的中缀表达式(qtoquit!
):
"<cin>>infix;
while(pare("q")!
=0)
{
cout<<"你输入的中缀表达式为:
"<iexp.setInfixExp(infix);
//求出相应的后缀表达式并输出
postfix=iexp.postfixExp();
cout<<"其相应的后缀表达式为"<//计算后缀表达式的值并输出
pexp.setPostfixExp(postfix);
cout<<"表达式的运算值="<cout<<"请再输入一个一位数的中缀表达式(qtoquit!
):
"<cin>>infix;
}
}
第四章测试分析
4.1测试程序执行情况
图4.1加法测试
图4.2减法测试
图4.3乘法运算
图4.4除法测试
图4.5输入表达式测试
第五章课程设计总结
经过这两周的课程设计,我又从新学到了很多关于数据结构的知识。
尤其是我的课程设计题目对我来说具有一定的难度,因为我们的数据结构课本上关于算术表达式求值的描述仅仅刚有短短的3页。
这使我在写程序上出现了很大的障碍。
因此,我去图书馆借阅了很多这方面的书籍,更多的了解算术表达式求解的过程。
其过程可概括为两步:
(1)将中缀表达式转换为其相应的后缀表达式。
(2)根据后缀表达式计算出表达式的值。
了解算法思想后,我开始考虑应用到的函数。
我发现在图书馆的大多数书籍都是用标准C++描述的,所以我就考虑用标准C++来描述我的程序,因为我们的C++课本不是标准的,所以我还在图书馆借阅的图书中,学到了很多东西。
我还应用到了STL库,用到了STL的容器map(映射表)。
但在调程时,我遇到的困难也是前所未有的。
这很锻炼了我的耐心。
根据我在课程设计中遇到得问题,我将在以后的学习过程中注意以下几点:
1、认真上好专业实验课,多在实践中锻炼自己。
2、写程序的过程中要考虑周到,严密。
3、在做设计的时候要有信心,有耐心,切勿浮躁。
4、认真的学习课本知识,掌握课本中的知识点,并在此基础上学会灵活运用。
5、在课余时间里多写程序,熟练掌握在调试程序的过程中所遇到的常见错误,以便能节省调试程序的时间。
参考文献
1.《数据结构(C语言版)》严蔚敏、吴伟民主编清华大学出版社2004.11
2.《数据结构课程设计案例精编(用C/C++描述)》,李建学等编著,清华大学出版社2007.2
3.《数据结构:
用面向对象方法与C++语言描述》,殷人昆主编, 清华大学出版社2007
附录:
程序代码
#include
#include
#include
#include
usingnamespacestd;
classinfix2postfix
{
public:
infix2postfix(){}
infix2postfix(conststring&infixExp):
infix(infixExp){}
voidsetInfixExp(conststring&infixExp){infix=infixExp;}
stringpostfixExp();
private:
stringinfix;
stringpostfix;
stackstk;
mapoper_prio,oper_prio_out;
voidset_priority();
};
voidinfix2postfix:
:
set_priority()
{
oper_prio["#"]=1;
oper_prio["("]=2;
oper_prio["+"]=3;
oper_prio["-"]=3;
oper_prio["*"]=4;
oper_prio["/"]=4;
oper_prio["%"]=4;
oper_prio["^"]=5;
oper_prio[")"]=6;
}
stringinfix2postfix:
:
postfixExp()
{
postfix="";
set_priority();
stk.push("#");
inti=0;
stringinput,topstk;
for(;i{
topstk=stk.top();
input=infix.substr(i,1);
if(!
oper_prio[input])
postfix+=input;
else
{
if(oper_prio[input]>oper_prio[topstk])
{
if(pare(")")==0)
{
while(pare("(")!
=0)
{
postfix+=topstk;
stk.pop();
topstk=stk.top();
}//endwhile
stk.pop();
}
else
stk.push(input);
}
else
{
if(pare("(")!
=0)
{
postfix+=topstk;
stk.pop();
continue;
};//endif
stk.push(input);
}//endif
}//endelse
//取infix的下一个元素输入
++i;
}//endfor
topstk=stk.top();
while(pare("#")!
=0)
{
postfix+=topstk;
stk.pop();
topstk=stk.top();
}//endwhile
returnpostfix;
}
classpostfixEval
{
public:
postfixEval(){};
voidsetPostfixExp(conststring&postfixExp){postfix=postfixExp;};
intevaluate();
private:
stringpostfix;
stackstk;
voidgetOperands(int&left,int&right);
intcompute(intleft,intri