数据结构表达式求值完整篇(含实验报告)
数据结构表达式求值完整篇(含实验报告)
1、实验目的和要求
(1)深入理解栈的特点及其描述方法
(2 )能够在两种存储结构上实现栈抽象数据类型实现
(3)掌握栈的几个典型应用算法,能灵活应用栈解决实际问题。
2、概要设计
【定义所有抽象数据类型、自定义函数间的调用关系图,自定义函数的功能描述和流程图,以及主程 序的流程图。】
//比较OPTRI 勺栈顶元
—素和ch 的优先级
//运算并将 一结果出栈 =
输出结
3、调试分析
【⑴ 调试过程中遇到的问题是如何解决的以及对设计与实现中关键点的回顾讨论和分析; (2)算法的
时空分析(包括基本操作和其他算法的时间复杂度和空间复杂度的分析
)和改进设想;(3)经验和体会等。】
■■
定义运算符和操 Evaluate Expressi
输入每个字符
1?栈的定义、初始化、出栈进栈、取栈顶元素等步骤不难就先把结构打好了
2.操作数和运算符分别入不同的栈
char->int
进操作数栈 先考虑了小于10的整数直接进栈,重点是运算符的优先级这块函数的编写
3前面的都听简单的,就是 小数编写这块想了很久,
定义了 low 做判定符号的标志。如果在运算符后输入负号则 low=-1(将p 入栈时入栈
的是p*low ),继续输入ch 总结:
我觉得写的好的地方在于定义了
flag,low
分别作为小数入栈和负号与减号区别的条
件。第一次写这么长的代码,还有就是将输入的字符再转到小数这段代码可以留着很有 用。开始考虑的大整数想麻
将单个字符转为整数后还要定一个
double p;使依次输入的数成一个小数 ->p.
在小数入栈使要考虑放在那条
if 语句中,防止在运算结果入栈后 p 再次入
flag 的值判定p 是否入栈。并且成功入栈后
else
数解决
p ■*= (ch -' 9'); scant t tch);
4.负数部分
DPND_Push(OPND ,p*lou); "操作^数进才夷OPHD dim-' O'; P-o ; q-0-1 ;
p - p^Cch-F fl'); q-q?q;;
讨论 ?输入的表达式串中第】个字符是;
-可断定此匸是负号
?其余的“
-若紧接在常送后的=可断定是页号
右图重点。
开始就有负数和运算符后面有负数的情况<
(比较容易)
OP1R_Pu5h(OPlR,ch);"运算符入栈 lo Vf = 1;
scanF(ia ic H
,&ch);
if( ch ―)
{
5&anFC k>tc ll a ftch);
Lou = -1; >
break; 栈,又定义了 int flag;通过
p,q 都要回到初始状态
Flag == 1 )
H-CCI1 ' =
烦了,直接用double 难度降低了很多
4、测试数据与结果
】
5、附录
【给岀每部分的源代码(必须要有一定量的注释) o]
/* common.h */
#include "stdio.h"
#include "string.h"
#i nclude "ctype.h"
#in elude "math.h"
/*其他函数的声明*/
double EvaluateExpressi on ( ); // 算数表达式求值的算法优先算法
char Precede (SEIemType_OPTR top, char ch); // 比较OPTR勺栈顶元素和ch的优先级
double Operate (SEIemType_OPND a, SEIemType_OPTRheta, SElemType_OPND); // 运算
//栈基本操作的函数声明
void OPTR_lnitStack(Sqstack_OPTR &s);
//运算符栈初始化
void OPND_InitStack(Sqstack_OPND &s);
//操作数栈初始化
char OPTR_GetTop(Sqstack_OPTR s);
//取运算符的栈顶元素
double OPND_GetTop(Sqstack_OPNDs);
//取操作数的栈顶元素
void OPTR_Push(Sqstack_OPTR &s,SElemType_OPTR e); // 入栈
void OPND_Push(Sqstack_OPND &s,SElemType_OPND e); // 入栈
void OPTR_Pop(Sqstack_OPTR &s,SEIemType_OPTR &e); // 出栈
void OPND_Pop(Sqstack_OPND &s,SElemType_OPND &e); // 出栈
/*基本操作函数的实现*/
#i nclude "common .h"
#include "Sqstack.h"
#in clude "other.h"
//运算符栈初始化
void OPTR_I ni tStack(Sqstack_OPTR &s)
{ 一一
s.base=new SEIemType_OPTR[MAXSIZE];
if(!s.base)
printf("\n 运算符栈存储分配失败!\n");
s.top=s.base;
s.stacksize=MAXSIZE;
}
//操作数栈初始化
void OPND」n itStack(Sqstack_OPND &s)
{ 一一
s.base=new SElemType_OPND[MAXSIZE];
if(!s.base)
printf("\n 操作数栈存储分配失败!\n");
s.top=s.base;
s.stacksize=MAXSIZE;
}
//取操作符的栈顶元素
char OPTR_GetTop(Sqstack_OPTR s)
{ 一一
if(s.top!=s.base)
return *(s.top-1);
return 0;
//取运算数的栈顶元素
double OPND_GetTop(Sqstack_OPND s)
{ 一一
if( s.top != s.base )
return ( *(s.top-1) )-'O';
return 0;
}
//运算符入栈
void OPTR_Push(Sqstack_OPTR &s,SEIemType_OPTR e) { ~ ~ 一if(s.top-s.base == s.stacksize) prin tf("\n 满栈!\n");
*s.top++=e; // 先赋值后自加
}
//操作数入栈
void OPND_Push(Sqstack_OPND & s,SEIemType_OPND e) { ~ ~ 一if(s.top-s.base == s.stacksize) prin tf("\n 满栈!\n");
*s.top++=e+'0'; // 先赋值后自加
}
//运算符出栈
void OPTR_Pop(Sqstack_OPTR & s,SEIemType_OPTR &e) {
if(s.top == s.base)
prin tf("\n 空栈!\n");
e=*--s.top;
}
//操作数出栈
void OPND_Pop(Sqstack_OPND & s,SEIemType_OPND &e)
{ ~ ~ 一
if(s.top == s.base)
prin tf("\n 空栈!\n");
e=(*--s.top)-'0';
}
/*其他函数的实现*/
#i nclude "common .h"
#include "Sqstack.h"
#in clude "other.h"
//算数表达式求值的算法优先算法 double EvaluateExpressi on () {
Sqstack_OPTR OPTR; Sqstack_OPND OPND; char ch; char x; // char dimo='0'; //
int low=1;
//
int flag=1; //
判断负数
用来判定double p 是否入栈
SEIemType_OPTR theta; // 运算符栈顶元素
SEIemType_OPND a,b;
//
弹出的两个要运算的操作数
//初始化
OPTR_I nitStack(OPTR); //OPTR 运算符 OPND_I nitStack(OPND); //OPND 操作数
OPTR_Push(OPTR,#); //
将表达式起始符压入运算符栈
sca nf("%c",&ch);
if( ch =='-') {
low=-1; scan f("%c",&ch); }
//保证接下来的实现从数字开始
while(ch != '#' || OPTR_GetTop(OPTR) != '#') {
if( isdigit(ch) || ch =='.')
flag=1; if(ch !='.')
if ( dimo !='.') {
p = p*10 ;
p += (ch-'O'); scan f("%c",&ch); }
else if ( dimo =='.') {
p = p+(ch-'O')*q; q=q*q;;
double p=0; // double q=0.1;
//
将输入的操作数处理后得
小数点后运算
double p;然后p 入栈
弹出的'('
记录小数点分前后计算
scan f("%c",&ch);
}
}
else if( ch =='.')
{
dimo ='.';
sca nf("%c",&ch);
}
} else
{
if( flag == 1 )
{
OPND_Push(OPND,p*low); // 操作数进栈OPND dimo='0';
p=0;
q=0.1;
}
switch( Precede( OPTR_GetTop(OPTR), ch ))
{ _
case '<':
OPTR_Push(OPTR,ch); // 运算符入栈
low = 1;
sca nf("%c",&ch);
if( ch =='-')
{
scan f("%c",&ch);
low = -1;
}
break;
case '>':
OPTR_Pop(OPTR,theta); // 运算符存到theta 出栈
OPND_Pop(OPND,b); // 操作数出栈
OPND_Pop(OPND,a); // 操作数出栈
OPND_Push( OPND,Operate(a,theta,b));
flag =0 ;
break; // 注意此处没有输入!!!!!!!!!
case '=':
OPTR_Pop(OPTR,x); //相等的情况:栈顶元素是'(',且ch是')' 即消除一对括号
sca nf("%c",&ch);
//low=1;
break;
}
}
}
return OPND_GetTop( OPND );
}
//比较OPTF的栈顶元素和ch的优先级
char Precede (SEIemType_OPTR top, char ch)
{ _
switch (top)
{
case '+':
if(ch=='+'||ch=='-'||ch==')'||ch==#)
return '>';
if(ch=='*'||ch=='/'||ch=='('||ch=='A')
return '<';
break;
case '-':
if(ch=='+'||ch=='-'||ch==')'||ch=='#')
return '>';
if(ch=='*'||ch=='/'||ch=='('||ch=='A')
return '<';
break;
case '*':
if(ch=='+'||ch=='-'||ch=='*'||ch==7'||ch==')'||ch==#)
return '>';
if(ch=='('||ch==w) return '<';
break;
case '/': if(ch=='+'||ch=='-'||ch=='*'||ch==7'||ch==')'||ch==#) return '>';
if(ch=='('||ch=='A')
return '<';
break;
case '(':
if(ch=='+'||ch=='-'||ch=='*'||ch==7'||ch=='(') return '<';
if(ch==')') return '=';
if(ch=='A')
return '<';
break;
case ')':
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch==')'||ch==#||ch=='A') return '>';
break;
case '#': if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch=='A')
return '<';
if(ch=='#')
return '=';
break;
case 'A': if(ch=='+'||ch=='-'||ch=='*'||ch==7'||ch==')'||ch==#) return '>';
if(ch=='(')
return '=';
break;
}
return 0;
//运算
double Operate (SEIemType_OPND a, SEIemType_OPTR theta, SEIemType_OPND b) ~ ~ ~ {
switch(theta)
case '+':
retur n a+b;break; case '-':
return a-b;break; case '*':
return a*b;break; case '/':
return a/b;break;
case
return pow(a,b);break; }
return 0;
}
/*测试程序*/
/* ctype.h 是否为数字int isdigit(int ch); */
#i nclude "common .h"
#include "Sqstack.h"
#in clude "other.h"
int main()
{
while (1)
{
printf ("\n 请输入算式表达式(以'#'结尾):\n");
fflush(stdi n);
printf ( "\n 结果:\n%.3lf \n",EvaluateExpression ()); }
return 0;