数据结构.docx
《数据结构.docx》由会员分享,可在线阅读,更多相关《数据结构.docx(15页珍藏版)》请在冰豆网上搜索。
数据结构
《算法与数据结构》
课程设计报告
题目名称表达式求值
学号
姓名
指导教师
日期
一设计题目
表达式求值(中缀)
二需求分析
1.问题描述:
在计算机中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行,在程序设计时,借助栈实现。
2.表达式求值这个程序,主要利用栈和数组,把运算的先后步骤进行分析并实现简单的运算,以字符列的形式从终端输入语法的正确的、不含变量的整数表达式。
利用已知的算符优先关系,实现对算术四则运算的求值,在求值中运用栈、运算栈、输入字符和主要操作的变化过程。
该程序相当于一个简单的计算机计算程序,只进行简单的加减乘除和带括号的四则运算。
三概要设计
1、基本思想(中缀表达式求值)
要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值,首先要能够正确解释表达式,要了解算术四则运算的规则即:
(1)先乘除后加减;
(2)从左到右计算;
(3)先括号内,后括号外。
下表定义的运算符之间的关系:
b
a
+
-
*
/
(
)
#
+
>
>
<
<
<
>
>
_
>
>
<
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>
>
<
>
>
(
<
<
<
<
<
=
)
>
>
>
>
>
>
#
<
<
<
<
<
=
为了实现运算符有限算法,在程序中使用了两个工作栈。
分别是:
运算符栈OPTR,操作数栈OPND.
基本思想:
(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;
(2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈得栈顶运算符比较优先级后作相应操作。
若大于栈顶元素优先级则如栈,若小于栈顶元素优先级则退出和OPND得操作数进行计算,并把计算结果如OPND栈。
直至整个表达式求值完毕(即OPND栈的栈顶元素和当前读入的字符均为“#”)。
2、栈的抽象数据类型的定义:
ADTStack{
数据对象:
D={ai|ai∈IntegerSet,i=1,2,…,n,n≥0}
数据关系:
R1={〈ai-1,ai〉|ai-1,ai∈D,i=1,2,…,n}
约定an端为栈顶,ai端为栈底
基本操作:
InitStack(&S)
操作结果:
构造一个空栈S。
DestroyStack(&S)
初始条件:
栈S已存在。
操作结果:
栈S被销毁。
ClearStack(&S)
初始条件:
栈S已存在。
操作结果:
将S清为空栈。
StackEmpty(S)
初始条件:
栈S已存在。
操作结果:
若栈S为空栈,则返回True,否则返回False。
StackLength(S)
初始条件:
栈S已存在。
操作结果:
返回S的元素个数,即栈的长度。
GetTop(S,&e)
初始条件:
栈S已存在且非空。
操作结果:
用e返回S的栈顶元素。
Push(&S,e)
初始条件:
栈S已存在。
操作结果:
插入元素e为新的栈顶元素。
Pop(&S,&e)
初始条件:
栈S已存在且非空。
操作结果:
删除S的栈顶元素,并用e返回其值。
StackTraverse(S,visit())
初始条件:
栈S已存在且非空。
操作结果:
从栈底到栈顶依次对S的每个数据元素调用函数visit()。
一旦visit()失败,则操作失败。
}ADTStack
3、基本操作
我选择的是中缀表达式求值,在转换和计算中主要用到了下列几个函数
1)charPrecede(chart1,chart2)
作用:
判断运算符t1和t2的优先关系。
如:
case'+':
case'-':
if(t1=='('||t1=='#')
f='<';//t1else
f='>';//t1>t2
break;
2)boolIsOperator(charc)
作用:
判断c是否为7种运算符之一
boolIsOperator(charc)//判断c是否为7种运算符之一
{
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':
returntrue;
default:
returnfalse;
}
}
3)intOperate(inta,charoper,intb)
作用:
intOperate(inta,charoper,intb)
{
switch(oper)
{
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
default:
break;
}
returna/b;
}
4)intEvaluateExpression()
作用:
中缀表达式求值的算法
intEvaluateExpression()
{
stackOPTR,OPND;//设置操作数栈和操作符栈
inta,b,d,x;
charc;
OPTR.push('#');
c=getchar();
x=OPTR.top();
while(c!
='#'||x!
='#')
{
if(IsOperator(c))
{
switch(Precede(x,c))
{
case'<':
OPTR.push(c);
c=getchar();
break;
case'=':
x=OPTR.top();
OPTR.pop();
c=getchar();
break;
case'>':
x=OPTR.top();
OPTR.pop();
b=OPND.top();
OPND.pop();
a=OPND.top();
OPND.pop();
OPND.push(Operate(a,x,b));
}
}
elseif(c>='0'&&c<='9')
{
d=0;
while(c>='0'&&c<='9')
{
d=d*10+c-'0';
c=getchar();
}
OPND.push(d);
}
else
{
cout<<"出现非法字符"<exit(0);
}
x=OPTR.top();
}
x=OPND.top();
if(OPND.empty())
{
cout<<"表达式不正确#"<exit(0);
}
returnx;
}
四详细设计中缀表达式求值.cpp
#include
#include
usingnamespacestd;
intEvaluateExpression();
intmain()
{
cout<<"请输入算术表达式,负数要用(0--正数)表示\n";
cout<return0;
}
charPrecede(chart1,chart2)
{//判断t1,t2两符号的优先关系('#'用'#'代替)
charf;
switch(t2)
{
case'+':
case'-':
if(t1=='('||t1=='#')
f='<';//t1else
f='>';//t1>t2
break;
case'*':
case'/':
if(t1=='*'||t1=='/'||t1==')')
f='>';//t1>t2
else
f='<';//t1break;
case'(':
if(t1==')')
{
cout<<"括号不匹配"<exit(0);
}
else
f='<';//t1break;
case')':
switch(t1)
{
case'(':
f='=';//t1=t2
break;
case'#':
cout<<"缺乏左括号"<exit(0);
default:
f='>';//t1>t2
}
break;
case'#':
switch(t1)
{
case'#':
f='=';//t1=t2
break;
case'(':
cout<<"缺乏右括号"<exit(0);
default:
f='>';//t1>t2
}
}
returnf;
}
boolIsOperator(charc)//判断c是否为7种运算符之一
{
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':
returntrue;
default:
returnfalse;
}
}
intOperate(inta,charoper,intb)
{//做死者运算athetab,返回运算结果
switch(oper)
{
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
default:
break;
}
returna/b;
}
intEvaluateExpression()
{
stackOPTR,OPND;//设置操作数栈和操作符栈
inta,b,d,x;
charc;
OPTR.push('#');
c=getchar();
x=OPTR.top();
while(c!
='#'||x!
='#')
{
if(IsOperator(c))
{
switch(Precede(x,c))
{
case'<':
OPTR.push(c);
c=getchar();
break;
case'=':
x=OPTR.top();
OPTR.pop();
c=getchar();
break;
case'>':
x=OPTR.top();
OPTR.pop();
b=OPND.top();
OPND.pop();
a=OPND.top();
OPND.pop();
OPND.push(Operate(a,x,b));
}
}
elseif(c>='0'&&c<='9')
{
d=0;
while(c>='0'&&c<='9')
{
d=d*10+c-'0';
c=getchar();
}
OPND.push(d);
}
else
{
cout<<"出现非法字符"<exit(0);
}
x=OPTR.top();
}
x=OPND.top();
if(OPND.empty())
{
cout<<"表达式不正确#"<exit(0);
}
returnx;
}
}while(ir[i]=r[0];
c++;
q(r,s,j-1);
q(r,j+1,t);
}
}
六测试结果
七附录和设计心得体会
这次的课程设计,表达式求值。
我首先选择的是后缀表达式求值,将中缀转换成后缀并计算。
后来又采用了栈的标准库,但只因为后缀比中缀难度大一些,并且标准库的算法较为复杂,我选择的方法不太正确,最终没能调试成功,好像是堆栈那地方有问题。
下面是标准库的算法,老师如果有时间,请帮我看一下。
未成功的\课设.cpp
未成功的\stack.cpp
未成功的\stack.h
但是我通过这次的课程设计,进一步熟悉掌握栈的定义和应用,比如构造空栈,清空栈,求栈的大小,压栈和出栈操作,栈的遍历等等。
对于算符优先算法、中缀变后缀的算法、后缀表达式求值的算法以及中缀表达式求值的算法都有了更深刻的理解,
现在我已经能够应用所学数据结构知识,独立完成问题分析,结合数据结构理论知识,整合程序段,编写程序求解表达式求值的问题。
初步掌握了设计的一般步骤与方法,提高了综合运用所学的理论知识和方法独立分析和解决问题的能力。