数据结构算术表达式求值.docx
《数据结构算术表达式求值.docx》由会员分享,可在线阅读,更多相关《数据结构算术表达式求值.docx(23页珍藏版)》请在冰豆网上搜索。
数据结构算术表达式求值
二课程设计2——算术表达式求值
一、需求分析
二、程序的主要功能
三、程序运行平台
四、数据构造
五、算法及时间复杂度
六、测试用例
七、程序源代码
三感想体会与总结
算术表达式求值
一、需求分析
一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、完毕符“*〞,如:
*〔7+15〕*〔23-28/4〕*。
引入表达式起始、完毕符是为了方便。
编程利用“算符优先法〞求算术表达式的值。
二、程序的主要功能
〔1〕从键盘读入一个合法的算术表达式,输出正确的结果。
〔2〕显示输入序列和栈的变化过程。
三、程序运行平台
VisualC++6.0版本
四、数据构造
本程序的数据构造为栈。
〔1〕运算符栈局部:
structSqStack//定义栈
{
char*base;//栈底指针
char*top;//栈顶指针
intstacksize;//栈的长度
};
intInitStack(SqStack&s)//建立一个空栈S
{
if(!
(s.base=(char*)malloc(50*sizeof(char))))
e*it(0);
s.top=s.base;
s.stacksize=50;
returnOK;
}
charGetTop(SqStacks,char&e)//运算符取栈顶元素
{
if(s.top==s.base)//栈为空的时候返回ERROR
{
printf("运算符栈为空!
\n");
returnERROR;
}
else
e=*(s.top-1);//栈不为空的时候用e做返回值,返回S的栈顶元素,并返回OK
returnOK;
}
intPush(SqStack&s,chare)//运算符入栈
{
if(s.top-s.base>=s.stacksize)
{
printf("运算符栈满!
\n");
s.base=(char*)realloc(s.base,(s.stacksize+5)*sizeof(char));//栈满的时候,追加5个存储空间
if(!
s.base)e*it(OVERFLOW);
s.top=s.base+s.stacksize;
s.stacksize+=5;
}
*(s.top)++=e;//把e入栈
returnOK;
}
intPop(SqStack&s,char&e)//运算符出栈
{
if(s.top==s.base)//栈为空栈的时候,返回ERROR
{
printf("运算符栈为空!
\n");
returnERROR;
}
else
{
e=*--s.top;//栈不为空的时候用e做返回值,删除S的栈顶元素,并返回OK
returnOK;
}
}
intStackTraverse(SqStack&s)//运算符栈的遍历
{
char*t;
t=s.base;
if(s.top==s.base)
{
printf("运算符栈为空!
\n");//栈为空栈的时候返回ERROR
returnERROR;
}
while(t!
=s.top)
{
printf("%c",*t);//栈不为空的时候依次取出栈元素
t++;
}
returnERROR;
}
(2)数字栈局部:
structSqStackn//定义数栈
{
int*base;//栈底指针
int*top;//栈顶指针
intstacksize;//栈的长度
};
intInitStackn(SqStackn&s)//建立一个空栈S
{
s.base=(int*)malloc(50*sizeof(int));
if(!
s.base)e*it(OVERFLOW);//存储分配失败
s.top=s.base;
s.stacksize=50;
returnOK;
}
intGetTopn(SqStackns,int&e)//数栈取栈顶元素
{
if(s.top==s.base)
{
printf("运算数栈为空!
\n");//栈为空的时候返回ERROR
returnERROR;
}
else
e=*(s.top-1);//栈不为空的时候,用e作返回值,返回S的栈顶元素,并返回OK
returnOK;
}
intPushn(SqStackn&s,inte)//数栈入栈
{
if(s.top-s.base>=s.stacksize)
{
printf("运算数栈满!
\n");//栈满的时候,追加5个存储空间
s.base=(int*)realloc(s.base,(s.stacksize+5)*sizeof(int));
if(!
s.base)e*it(OVERFLOW);
s.top=s.base+s.stacksize;//插入元素e为新的栈顶元素
s.stacksize+=5;
}
*(s.top)++=e;//栈顶指针变化
returnOK;
}
intPopn(SqStackn&s,int&e)//数栈出栈
{
if(s.top==s.base)
{
printf("运算符栈为空!
\n");//栈为空栈的视时候,返回ERROR
returnERROR;
}
else
{
e=*--s.top;//栈不空的时候,则删除S的栈顶元素,用e返回其值,并返回OK
returnOK;
}
}
intStackTraversen(SqStackn&s)//数栈遍历
{
int*t;
t=s.base;
if(s.top==s.base)
{
printf("运算数栈为空!
\n");//栈为空栈的时候返回ERROR
returnERROR;
}
while(t!
=s.top)
{
printf("%d",*t);//栈不为空的时候依次输出
t++;
}
returnERROR;
}
五、算法及时间复杂度
1、算法:
建立两个不同类型的空栈,先把一个‘*’压入运算符栈。
输入一个算术表达式的字符串〔以‘*’完毕〕,从第一个字符依次向后读,把读取的数字放入数字栈,运算符放入运算符栈。
判断新读取的运算符和运算符栈顶得运算符号的优先级,以便确定是运算还是把运算符压入运算符栈。
最后两个‘*’遇到一起则运算完毕。
数字栈顶的数字就是要求的结果。
2、时间复杂度:
O(n)
数据压缩存储栈,其操作主要有:
建立栈intPush(SeqStack*S,char*)
入栈intPop(SeqStack*S,char*)
出栈。
以上各操作运算的平均时间复杂度为O(n),其主要时间是消耗在输入操作。
六、测试用例
如下图。
最终结果如下图:
七、源代码
/**************************************************************************************************
第七题算术表达式求值
[问题描述]
一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
假设操作数是正整数,
运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、完毕符“*〞,
如:
*〔7+15〕*〔23-28/4〕*。
引入表达式起始、完毕符是为了方便。
编程利用“算符优先法〞求算术表达式的值。
[根本要求]
〔1〕从键盘读入一个合法的算术表达式,输出正确的结果。
〔2〕显示输入序列和栈的变化过程。
***************************************************************************************************/
*include
*include
*include
*include
*include
*include
*defineOK1
*defineERROR0
*defineSTACK_INIT_SIZE100
//*defineSTACKINCREMENT10
//========================================================
//以下定义两种栈,分别存放运算符和数字
//========================================================
//*******************运算符栈局部*************************
structSqStack//定义栈
{
char*base;//栈底指针
char*top;//栈顶指针
intstacksize;//栈的长度
};
intInitStack(SqStack&s)//建立一个空栈S
{
if(!
(s.base=(char*)malloc(50*sizeof(char))))
e*it(0);
s.top=s.base;
s.stacksize=50;
returnOK;
}
charGetTop(SqStacks,char&e)//运算符取栈顶元素
{
if(s.top==s.base)//栈为空的时候返回ERROR
{
printf("运算符栈为空!
\n");
returnERROR;
}
else
e=*(s.top-1);//栈不为空的时候用e做返回值,返回S的栈顶元素,并返回OK
returnOK;
}
intPush(SqStack&s,chare)//运算符入栈
{
if(s.top-s.base>=s.stacksize)
{
printf("运算符栈满!
\n");
s.base=(char*)realloc(s.base,(s.stacksize+5)*sizeof(char));//栈满的时候,追加5个存储空间
if(!
s.base)e*it(OVERFLOW);
s.top=s.base+s.stacksize;
s.stacksize+=5;
}
*(s.top)++=e;//把e入栈
returnOK;
}
intPop(SqStack&s,char&e)//运算符出栈
{
if(s.top==s.base)//栈为空栈的时候,返回ERROR
{
printf("运算符栈为空!
\n");
returnERROR;
}
else
{
e=*--s.top;//栈不为空的时候用e做返回值,删除S的栈顶元素,并返回OK
returnOK;
}
}
intStackTraverse(SqStack&s)//运算符栈的遍历
{
char*t;
t=s.base;
if(s.top==s.base)
{
printf("运算符栈为空!
\n");//栈为空栈的时候返回ERROR
returnERROR;
}
while(t!
=s.top)
{
printf("%c",*t);//栈不为空的时候依次取出栈元素
t++;
}
returnERROR;
}
//**********************数字栈局部***************************
structSqStackn//定义数栈
{
int*base;//栈底指针
int*top;//栈顶指针
intstacksize;//栈的长度
};
intInitStackn(SqStackn&s)//建立一个空栈S
{
s.base=(int*)malloc(50*sizeof(int));
if(!
s.base)e*it(OVERFLOW);//存储分配失败
s.top=s.base;
s.stacksize=50;
returnOK;
}
intGetTopn(SqStackns,int&e)//数栈取栈顶元素
{
if(s.top==s.base)
{
printf("运算数栈为空!
\n");//栈为空的时候返回ERROR
returnERROR;
}
else
e=*(s.top-1);//栈不为空的时候,用e作返回值,返回S的栈顶元素,并返回OK
returnOK;
}
intPushn(SqStackn&s,inte)//数栈入栈
{
if(s.top-s.base>=s.stacksize)
{
printf("运算数栈满!
\n");//栈满的时候,追加5个存储空间
s.base=(int*)realloc(s.base,(s.stacksize+5)*sizeof(int));
if(!
s.base)e*it(OVERFLOW);
s.top=s.base+s.stacksize;//插入元素e为新的栈顶元素
s.stacksize+=5;
}
*(s.top)++=e;//栈顶指针变化
returnOK;
}
intPopn(SqStackn&s,int&e)//数栈出栈
{
if(s.top==s.base)
{
printf("运算符栈为空!
\n");//栈为空栈的视时候,返回ERROR
returnERROR;
}
else
{
e=*--s.top;//栈不空的时候,则删除S的栈顶元素,用e返回其值,并返回OK
returnOK;
}
}
intStackTraversen(SqStackn&s)//数栈遍历
{
int*t;
t=s.base;
if(s.top==s.base)
{
printf("运算数栈为空!
\n");//栈为空栈的时候返回ERROR
returnERROR;
}
while(t!
=s.top)
{
printf("%d",*t);//栈不为空的时候依次输出
t++;
}
returnERROR;
}
//========================================================
//以下定义函数
//========================================================
intIsoperator(charch)//判断是否为运算符,分别将运算符和数字进入不同的栈
{
switch(ch)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'*':
return1;
default:
return0;
}
}
intOperate(inta,charop,intb)//运算操作
{
intresult;
switch(op)
{
case'+':
result=a+b;
break;
case'-':
result=a-b;
break;
case'*':
result=a*b;
break;
case'/':
result=a/b;
break;
}
returnresult;
}
charPrecede(charch1,charch2)//运算符优先级的比拟
{
charp;
switch(ch1)
{
case'+':
case'-':
if(ch2=='+'||ch2=='-'||ch2==')'||ch2=='*')
p='>';//ch1运算符的优先级小于ch2运算符
else
p='<';
break;
case'*':
case'/':
if(ch2=='(')
p='<';
else
p='>';
break;
case'(':
if(ch2==')')
p='=';
elseif(ch2=='*')
{
printf("表达式错误!
运算符不匹配!
\n");
e*it(0);
}
else
p='<';
break;
case')':
if(ch2=='(')
{
printf("表达式错误!
运算符不匹配!
\n");
e*it(0);
}
else
p='>';
break;
case'*':
if(ch2==')')
{
printf("表达式错误!
运算符不匹配!
\n");
e*it(0);
}
elseif(ch2=='*')
p='=';
else
p='<';
break;
}
returnp;
}
//========================================================
//以下是求值过程
//========================================================
intEvaluateE*pression()//参考书p53算法3.4
{
inta,b,temp,answer;
charch,op,e;
char*str;
intj=0;
SqStacknOPND;//OPND为运算数字栈
SqStackOPTR;//OPTR为运算符栈
InitStack(OPTR);
Push(OPTR,'*');//,所以此栈底是'*',因为运算符栈以'*'作为完毕标志
InitStackn(OPND);
//printf("\n\n按任意键开场求解:
\n\n");
//ch=getch();
printf("\n请输入表达式并以'*'完毕:
\n");
str=(char*)malloc(50*sizeof(char));
gets(str);
ch=str[j];//ch是字符型的,而e是整型的整数
j++;
GetTop(OPTR,e);//e为栈顶元素返回值
while(ch!
='*'||e!
='*')
{
if(!
Isoperator(ch))//遇到数字,转换成十进制并计算
{
temp=ch-'0';//将字符转换为十进制数
ch=str[j];
j++;
while(!
Isoperator(ch))
{
temp=temp*10+ch-'0';//将逐个读入运算数的各位转化为十进制数
ch=str[j];
j++;
}
Pushn(OPND,temp);
}
elseif(Isoperator(ch))//判断是否是运算符,不是运算符则进栈
switch(Precede(e,ch))
{
case'<':
Push(OPTR,ch);//栈顶元素优先权低
ch=str[j++];
printf("\n\n运算符栈为:
\n");//输出栈,显示栈的变化
StackTraverse(OPTR);
printf("\n运算数栈为:
\n");
StackTraversen(OPND);
break;
case'=':
Pop(OPTR,op);//脱括号并接收下一字符
ch=str[j++];
printf("\n\n运算符栈为:
\n");
StackTraverse(OPTR);
printf("\n数栈为:
\n");
StackTraversen(OPND);
break;
case'>':
Pop(OPTR,op);//弹出最上面两个,并运算,把结果进栈
Popn(OPND,b);
Popn(OPND,a);
Pushn(OPND,Operate(a,op,b));
printf("\n\n运算符栈为:
\n");
StackTraverse(OPTR);
printf("\n数栈为:
\n");
StackTraversen(OPND);
}
else
{
printf("您的输入有问题,请检查重新输入!
");
e*it(0);
}
GetTop(OPTR,e);//取出运算符栈最上面元素是否是'*'
}//while
GetTopn(OPND,answer);//已输出。
数字栈最上面即是最终结果
returnanswer;
}
//========================================================
//执行局部
//========================================================
voidShowMenu()
{
printf("\n\n");
printf("███████████████████████████████████████\n");
printf("████\n");
printf("██表达式求值系统██\n");
printf("████\n");
printf("████████████████████