数据结构表达式求值代码
数据结构实验报告表达式求值
数据结构实验报告题目:编制一个表达式求值的程序。
一.需求分析1.本演示程序中,利用堆栈存储结构存储读入的运算符,输入的限定范围是数字(0—9),以及+*/()。
输入字符串限定长度为20,可以根据需要进行改变。
如果遇到不是以上范围或者连续输入两个运算符,如:++,则会提示输入错误,请重新输入。
输出的结果是转换后的后序表达式,以及float型数字,不会含有非法字符。
2.演示程序采用的是文件输入,只需要在源代码中输入要输入的文件的地址,然后就可以在文本文件中进行输入,运行过程中会自动读取,输出文本输入的表达式,及运算结果。
3.程序执行的命令包括:1)构造字符优先级比较表,比较优先关系2)文件输入3)构造堆栈,运算符入栈4)堆栈输出,变为后序表达式,并计算5)输出结果,结束4.测试数据文件地址:C:\\Users\\lenovo\\Desktop\\4.txt1) 输入:(35+20/2)*2-4/2+12正确输出结果是:100.00002)输入:(35+20/2)*2-/2+12结果是:error input3) 输入:a+ar/3=135结果是:error input二.概要设计为实现以上程序功能,需运用堆栈用于存储运算符,因此需要定义抽象数据类型。
1.堆栈的抽象数据类型定义为:ADT stack{数据对象:D={ai|ai∈正整数,i=0,1,2,3,…n,及{+-*/()}}数据关系:R1={<ai-1,a1>|ai-1,ai∈D}基本操作:Init stack(&s)操作结果:构造一个空的堆栈sPush stack(&s, e)初始条件:存在堆栈s操作结果:元素e压入堆栈s,top+1Pop (&s,e)初始条件:栈s已经存在且非空操作结果:删除栈顶元素e,输出其值,top-12.程序包含三个模块:1)运算符优先关系模块2)主程序模块;Int main(void){初始化;Do{接受命令;处理命令;}while(“命令”=”退出”);}3)堆栈模块三.详细设计1.程序源代码解释为:float Result(int c,float r[],int top){ //定义输出结果int j;float temp;switch(c){ //以下是四种基本运算的计算定义,运算完成后直接将top-1值赋予topcase 42:r[top-1]=r[top-1]*r[top];top=top-1;break; //乘法case 43:r[top-1]=r[top-1]+r[top];top=top-1;break;///加法case 45:r[top-1]=r[top-1]-r[top];top=top-1;break;//减法case 47:r[top-1]=r[top-1]/r[top];top=top-1;break;// 除法case 94:for(j=1,temp=r[top-1];j<r[top];j++) //平方或者几次方的运算temp=r[top-1]*temp; //循环相乘r[top-1]=temp;top=top-1;break;}return(r[top]);}if(temp1!=1){while(top>=1){ //栈不空的时候,栈中元素赋给houzhi,并计数biaozhi[b++]=i;houzhi[i]=duizhan[top-1];top=top-1;i=i+1;}max=i; //从0到i循环输出后序表达式for(i=0,b=0;i<max;i++){if(i!=biaozhi[b])printf("%d ",houzhi[i]) ; //输出后序表达式中的数字else {printf("%c ",houzhi[i]); //输出后序表达式中的运算符b=b+1;}}top=-1;for(i=0,b=0;i<max;i++){ //从0到maxif(i!=biaozhi[b]){top=top+1;result[top]=houzhi[i]; //将后值赋予result,调用result函数,进行Result运算}else {Result(houzhi[i],result,top); //运算结束,输出栈顶值,既是运算结果top--;b=b+1;}}printf("\n\nThe result is %f ",Result(houzhi[i],result,top)); //输出并打印结果}}getch();return 0;///返回0}2.程序的模块调用:主程序↓文件打开读入字符↓输入字符有效及优先级的判断↓运算模块↓输出结果四.调试分析1.本次作业的核心就是利用堆栈将中序表达式改成后序表达式,然后进行表达式的求值。
表达式求值(数据结构-栈的应用)
表达式求值(数据结构-栈的应⽤)⼀.问题描述:限制:只含有‘+’,‘-’,‘*’,‘/ ’和圆括号,正整数。
表⽰:字符数组,栈。
中缀表达式:在程序语⾔中,运算符位于两个运算数中间的表达式称为中缀表达式,例如 1+2*3.中缀表达式运算规则:先乘除,后加减,从左到右,先括号内,后括号外,因此中缀表达式不仅要判断运算符的优先级,⽽且还有处理括号。
后缀表达式:运算符在运算数的后⾯,如1+2*3的后缀表达式:1 2 3*,在后缀表达式中已经考虑了运算符的优先级,没有括号,只有运算数和运算符。
后缀表达式的运算:按照运算符的次序进⾏的。
例如123*+,从左到右扫描时,第⼀个运算符为*,先执⾏2*3=6,第⼆个运算符为‘+’,执⾏1+6=7。
⼆ .表达式求值的过程:将算术表达式转换成后缀表达式,然后对后缀表达式求值。
1.将算术表达式转换为后缀表达式。
(1)从左到右⼀次扫描中缀表达式的每⼀个字符,如果是字符串,直接写⼊后缀表达式。
(2)如果遇到的是' ( ',则压⼊操作符栈,遇到‘(’时,将栈中的元素放到后缀表达式中,直达栈顶元素为'('时,将栈顶元素'('删除,不需要⼊栈。
(3)如果遇到的是操作符,则将操作符和操作符栈顶元素⽐较。
:如果a[i]的运算符的优先级⼩于等于栈顶元素的优先级,退栈运算符并放到后缀表达式中,直到a[i]的运算符优先级⼤于栈顶运算符的优先级:否则⼊栈。
(4)重复上述步骤,知道中缀表达式的结束符标记“#”,转换结束。
我的代码:#include<bits/stdc++.h>using namespace std;stack<char>f;//操作符栈stack<double>s;//操作数栈bool flag;int prior(char ch)//运算符的优先级{switch(ch){case'+':case'-':return 1;case'*':case'%':case'/':return 2;default:return 0;//括号}}string trans(string a){while(!f.empty()) f.pop();f.push('#');string ret="";//保存中缀表达式int len=a.size(),i=0;while(i<len){if(a[i]==' '||a[i]=='=')//??{i++;continue;}else if(a[i]=='(')f.push(a[i++]);else if(a[i]==')'){while(f.top()!='('){ret+=f.top();ret+=' ';f.pop();}f.pop();//(出栈i++;}else if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/'||a[i]=='%'){while(prior(f.top())>=prior(a[i]))//如果a[]的运算符的优先级⼩于等于栈顶元素的优先级,退栈运算符并放到后缀表达式中,直到a[i]的运算符优先级⼤于栈顶运算符的优先级ret+=f.top();ret+=' ';f.pop();}f.push(a[i++]);}else{while((a[i]>='0'&&a[i]<='9')||a[i]=='.'){ret+=a[i++];}ret+=' ';}}while(f.top()!='#'){ret+=f.top();ret+=' ';f.pop();}ret+='=';return ret;}double cal(double a,double b,double ch)//计算{if(ch=='+') return a+b;if(ch=='-') return a-b;if(ch=='*') return a*b;if(ch=='%') return ((int)a%(int)b);if(ch=='/'){if(b!=0)return a/b;flag=true;return 0;}}double solve(string a)//后缀表达式计算{string t=trans(a);while(!s.empty()) s.pop();flag=false;int len=t.length(),i=0;while(i<len){if(t[i]==' '||t[i]=='='){i++;continue;}else if(t[i]=='+'||t[i]=='-'||t[i]=='*'||t[i]=='/'||t[i]=='%') {double num1,num2;num1=s.top();s.pop();num2=s.top();s.pop();s.push(cal(num1,num2,t[i]));i++;}else{double x=0;while(t[i]>='0'&&t[i]<='9'){x=x*10+t[i]-'0';i++;}if(t[i]=='.'){double k=10.0,y=0;i++;while(t[i]>='0'&&t[i]<='9'){y+=((t[i]-'0')/k);i++;k*=10;;}x+=y;}s.push(x);}}return s.top();}int main(){int num;scanf("%d",&num);while(num--){cin>>a;// cout<<e.trans(a)<<endl;//将中缀表达式装换为后缀表达式 cout<<solve(a)<<endl;}return 0;}。
数据结构-算术表达式求值(含需求分析和源代码)
需求分析(附代码)一、需求分析(1)首先定义两个栈OPTR、OPND,栈OPTR用于存放运算符,栈OPND 用于存放操作数;定义一个一维数组expr【】存放表达式串。
(2)主函数主要包括两部分:(1)判断运算符优先权,返回优先权高的;(2)操作函数。
(3)开始将‘#’入操作符栈,通过一个函数来判别算术运算符的优先级。
且规定‘#’的优先级最低。
在输入表达式的最后输入‘#’,代表表达式输入结束。
在表达式输入过程中,遇操作数则直接入栈。
遇到运算符则与栈顶运算符比较优先级,当前运算符优先级高(前面的运算还不应执行)则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,重新比较当前运算符(注意当前运算符未变)与新栈顶运算符。
如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。
(4)最初实现的加、减、乘、除及带小括号的基本运算,但考虑到实用性,后来的设计中有加上了乘方运算。
在乘方运算中借用了C库中自带的乘方函数pow。
二、概要设计1、设定栈的抽象数据类型定义:ADT Stack {数据对象:D={ ai | ai∈ElemSet, i=1,2,...,n,n≥0 }数据关系:R1={ <ai-1, ai >| ai-1, ai∈D, i=2,...,n }约定an端为栈顶,a1端为栈底。
基本操作:InitStack(&S)操作结果:构造一个空栈S。
DestroyStack(&S)初始条件:栈S已存在。
操作结果:栈S被销毁。
StackEmpty(S)初始条件:栈S已存在。
操作结果:若栈S为空栈,则返回TRUE,否则FALE。
StackLength(S)初始条件:栈S已存在。
操作结果:返回S的元素个数,即栈的长度。
GetTop(S, &e)初始条件:栈S已存在且非空。
操作结果:用e返回S的栈顶元素。
ClearStack(&S)初始条件:栈S已存在。
数据结构表达式求值(可以求小数与多位数)
//栈顶压入一个数
S.top++; } char PopOPTR(SqStackOPTR &S,char &e){ --S.top; e=*S.top; return e; } float PopOPND(SqStackOPND &S,float &e){ --S.top; e=*S.top; return e; } Status GetTopOPTR(SqStackOPTR &S,char &e){ e=*(S.top-1); return e; } float GetTopOPND(SqStackOPND &S,float &e){ e=*(S.top-1); return e; } unsigned char Prior[7][7] = { '>','>','<','<','<','>','>', '>','>','<','<','<','>','>', '>','>','>','>','<','>','>', '>','>','>','>','<','>','>', // 算符间的优先关系 //取栈顶元素
数据结构表达式求值(栈)
{
case '+':c=a+b;break;
case '-':c=a-b;break;
case '*':c=a*b;break;
case '/':if(b!=0) c=a/b;
else
{
printf("Error!出现分母为0情况。\n");
return 0;
}
break;
case '%':c=(float)((int)a%(int)b);break;
w=*infixexp;
while((GetTop_SeqStackc(S,&c),c)!='#'||w!='=')
{
if(w==' ')
{
infixexp++;
w=*infixexp;
continue;
}//过滤空格字符。
if(w=='.')
{
*postfixexp=w;
postfixexp++;
}
Push_SeqStackf(S,c);
}
ch=*A++;
}
GetTop_SeqStackf(S,&result);
Destroy_SeqStackf(&S);
return (result);
}//后辍表达式求表达式的值,通过一个浮点型栈实现的。
void main()
{
printf("******************************************************************************\n");
表达式求值(数据结构)
结束算法,此时在OPND栈的栈顶得到 运算结果。
① 若ch是操作数,进OPND栈,从中缀表达式 取下一字符送入ch; ② 若ch是操作符,比较栈外icp(ch)的优先级和 栈内isp(OPTR)的优先级: 若icp(ch) > isp(OPTR),则ch进OPTR栈, 从中缀表达式取下一字符送入ch; 若icp(ch) < isp(OPTR),则从OPND栈退出 a2 和 a1 , 从 OPTR 栈 退 出 θ, 形 成 运 算 指 令 (a1)θ(a2),结果进OPND栈; 若icp(ch) == isp(OPTR) 且ch == “)”,则从 OPTR栈退出栈顶的“(”,对消括号,然后从 中缀表达式取下一字符送入ch;
优先级 操作符
1
单目-、!
2
*、/、%
3
+、-
4 <、<=、>、>=
5
==、!=
6
&&
7
||
一般表达式的操作符有4种类型:
1 算术操作符 如双目操作符(+、-、 *、/ 和%)以及单目操作符(-);
2 关系操作符 包括<、<=、==、!=、 >=、>。这些操作符主要用于比较;
3 逻辑操作符 如与(&&)、或(||)、非 (!);
38
icp (栈外) 0 8 6 4
21
isp叫做栈内(in stack priority)优先数。
icp叫做栈外(in coming priority)优先数。
操作符优先数相等的情况只出现在括号 配对或栈底的“;”号与输入流最后的“;” 号配对时。
数据结构表达式求值
数据结构表达式求值最佳答案简易版#include<iostream>using namespace std;#define TRUE 1#define FALSE 0#define Stack_Size 20#define Stack_Float 30/*建立字符栈*/typedef struct{char elem[Stack_Size];//存储定义int top;}Stack_char;void InitStack(Stack_char*S)//初始化顺序栈 {S->top=-1;}int Push(Stack_char *S,char x)//进栈{if(S->top==Stack_Size-1) return (FALSE); S->top++;S->elem[S->top]=x;return (TRUE);}int Pop(Stack_char*S,char*x)//出栈{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];S->top--;return(TRUE);}}int GetTop(Stack_char*S,char*x)// 取栈顶{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];return(TRUE);}}char GetTop(Stack_char S){char x;GetTop(&S,&x);return x;}//建立数字栈typedef struct//建立{float elem[Stack_Float];int top;}Stack_float;void InitStack(Stack_float*S)//初始化{S->top=-1;}int Push(Stack_float*S,float e) //进栈{if(S->top==Stack_Float-1) return(FALSE); else{S->top++;S->elem[S->top]=e;return(TRUE);}}int Pop(Stack_float*S,float*x)//出栈{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];S->top--;return(TRUE);}}int GetTop(Stack_float*S,float*x)// 取栈顶{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];return(TRUE);}}float GetTop(Stack_float S){float x;GetTop(&S,&x);return x;}bool In(char ch)//判断字符{if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#') return (TRUE);else return(FALSE);}float GetNumber(char*ch)//转化数码{return (*ch-48);}float Execute(float a,char op,float b){switch(op){case'+':return(a+b);break;case'-':return(a-b);break;case'*':return(a*b);break;case'/':return(a/b);break;default:cout<<"不能运算";break;}}char Compare(char x,char ch){if(x=='+'||x=='-')if(ch=='+'||ch=='-'||ch==')'||ch=='#') return ('>'); else return ('<');if(x=='*'||x=='/')if(ch=='(') return('<');else return('>');if(x=='(')if(ch==')') return('=');else return('<');if(x==')')if(ch!='(') return('>');if(x=='#')if(ch=='#') return('=');else return('<');}float ExpEvaluation(){float n,v,a,b;char op;Stack_char OPTR;Stack_float OVS;InitStack(&OPTR);InitStack(&OVS);Push(&OPTR,'#');cout<<"请输入一个表达式串(以#结束)"<<endl;char ch;ch=getchar();while(ch!='#'||GetTop(OPTR)!='#'){if(!In(ch)){n=GetNumber(&ch);Push(&OVS,n);ch=getchar();}elseswitch(Compare(GetTop(OPTR),ch)){case'<':Push(&OPTR,ch);ch=getchar();break;case'>':Pop(&OPTR,&op);Pop(&OVS,&b);Pop(&OVS,&a);v=Execute(a,op,b); Push(&OVS,v);break;case'=':Pop(&OPTR,&op);ch=getchar();break;}}v=GetTop(OVS);return(v);}int main(){cout<<ExpEvaluation()<<endl;system("pause");return 0;}完善版#include<iostream>using namespace std;#define TRUE 1#define FALSE 0#define Stack_Size 20#define Stack_Float 30/*建立字符栈*/typedef struct{char elem[Stack_Size];//存储定义int top;}Stack_char;void InitStack(Stack_char*S)//初始化顺序栈{S->top=-1;}int Push(Stack_char *S,char x)//进栈{if(S->top==Stack_Size-1) return (FALSE); S->top++;S->elem[S->top]=x;return (TRUE);}int Pop(Stack_char*S,char*x)//出栈{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];S->top--;return(TRUE);}}int GetTop(Stack_char*S,char*x)// 取栈顶{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];return(TRUE);}}char GetTop(Stack_char S){char x;GetTop(&S,&x);return x;}void ClearStack(Stack_char*S)//清空栈{if(S->top!=-1) S->top=-1;}/*建立数字栈*/typedef struct//建立{float elem[Stack_Float];int top;}Stack_float;void InitStack(Stack_float*S)//初始化{S->top=-1;}int Push(Stack_float*S,float e) //进栈{if(S->top==Stack_Float-1) return(FALSE); else{S->top++;S->elem[S->top]=e;return(TRUE);}}int Pop(Stack_float*S,float*x)//出栈{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];S->top--;return(TRUE);}}int GetTop(Stack_float*S,float*x)// 取栈顶{if(S->top==-1) return(FALSE);else{*x=S->elem[S->top];return(TRUE);}}float GetTop(Stack_float S){float x;GetTop(&S,&x);return x;}void ClearStack(Stack_float*S)//清空栈{if(S->top!=-1) S->top=-1;}/*一些函数*/char a[7]={ '+','-','*','/','(',')', '#'};char p[7][7]= //优先权集合{ {'>','>','<','<','<','>','>'},{'>','>','<','<','<','>','>'},{'>','>','>','>','<','>','>'},{'>','>','>','>','<','>','>'},{'<','<','<','<','<','=','@'},{'>','>','>','>','@','>','>'},{'<','<','<','<','<','@','='} };bool Ins(char ch)//判断数字{if(ch>=48&&ch<=57) return(TRUE);else return(FALSE);}bool Inc(char ch)//判断字符{if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#')return (TRUE);else return(FALSE);}float GetNumber(char*ch)//转化数码{return (*ch-48);}float Execute(float a,char op,float b){switch(op){case'+':return(a+b);break;case'-':return(a-b);break;case'*':return(a*b);break;case'/':return(a/b);break;default:cout<<"不能运算";break;}}char Compare(char x,char ch){//char x;// GetTop(&S,&x);int i,j,k;for(i=0;i<7;i++){if(x==a[i]) j=i;if(ch==a[i]) k=i;}return p[j][k];}Stack_char OPTR;Stack_float OVS;//InitStack(&OPTR);//InitStack(&OVS);void ExpEvaluation(){InitStack(&OPTR);InitStack(&OVS);Push(&OPTR,'#');cout<<"请输入一个表达式串(以#结束)"<<endl;char ch;int w=0,q=0,y=0,z=0,m=0;float n=0,v,a,b;char op;ch=getchar();if(!Ins(ch)){if(ch=='(') z=1;else if(ch=='-') {w=1;ch=getchar();}//记录输入负号 else{cout<<"输入错误,请重新a";fflush(stdin); //清理缓存ClearStack(&OPTR);ExpEvaluation();exit(1);}}//else {}while(ch!='#'||GetTop(OPTR)!='#'){if(Ins(ch)){n=n*10+GetNumber(&ch);q=1;//记录输入数字y=0;//记录输入字符ch=getchar();}//cout<<"n值"<<n<<endl;//system("pause");if(Inc(ch)){if(ch=='(') z=1;if(w==1){// cout<<"z"<<z<<endl;if(q==0){if(z==1){Push(&OPTR,ch);//cout<<"+++"<<GetTop(OPTR)<<endl; z=0;m=2;//记录负的左括号ch=getchar();continue;}else if(ch=='-') {w=0;ch=getchar();} else{cout<<"输入错误,请重新b";fflush(stdin); //清理缓存ClearStack(&OPTR);ExpEvaluation();exit(1); }}else{cout<<"w"<<w<<endl;n=-n;w=0;if(m==2){n=-n;m--;cout<<"m"<<m<<endl;} } }//else {}if(q==1){Push(&OVS,n);cout<<"栈顶"<<GetTop(OVS)<<endl;n=0;q=0;}if(y==1){if(GetTop(OPTR)=='('&&ch=='-'){w=1;ch=getchar();}else if(ch=='(') z=1;//记录左括号else{//cout<<"c"<<ch<<endl;cout<<"输入错误,请重新c";fflush(stdin); //清理缓存ClearStack(&OPTR);ClearStack(&OVS);ExpEvaluation();exit(1);}}if(y==0||z==1){//cout<<"d"<<ch<<endl;//cout<<"o栈顶"<<GetTop(OPTR)<<endl;//cout<<"***"<<Compare(GetTop(OPTR),ch)<<endl; switch(Compare(GetTop(OPTR),ch)){case'<':Push(&OPTR,ch);y=1;z=0;ch=getchar();//cout<<"e"<<GetTop(OPTR)<<endl;break;case'>':Pop(&OPTR,&op);Pop(&OVS,&b);Pop(&OVS,&a);if(op=='/'&&b==0){cout<<"输入错误,请重新d";fflush(stdin); //清理缓存ClearStack(&OPTR);ClearStack(&OVS);ExpEvaluation();exit(1);}v=Execute(a,op,b);if(m==1){v=-v;m=0;}Push(&OVS,v);//cout<<"*栈顶"<<GetTop(OVS)<<endl; break;case'=':Pop(&OPTR,&op);ch=getchar();break;case'@':cout<<"括号不匹配,请重新e"; fflush(stdin); //清理缓存 ClearStack(&OPTR);ClearStack(&OVS);ExpEvaluation();exit(1);}}}if(!Inc(ch)&&!Ins(ch)){cout<<"输入错误,请重新f";fflush(stdin); //清理缓存ClearStack(&OPTR);ClearStack(&OVS);ExpEvaluation();exit(1);}}v=GetTop(OVS);cout<<v<<endl;system("pause");}int main(){ExpEvaluation();return 0;}。
表达式求值(数据结构)(2023版)
表达式求值(数据结构) 表达式求值(数据结构)1.引言1.1 目的1.2 背景1.3 范围2.表达式类型2.1 算术表达式2.1.1 运算符2.1.2 运算数2.2 逻辑表达式2.2.1 逻辑运算符2.2.2 逻辑运算数2.3 字符串表达式2.3.1 字符串连接运算符2.3.2 字符串操作函数3.表达式求值算法3.1 递归下降分析法3.2 栈表达式求值法3.2.1 中缀表达式转后缀表达式3.2.2 后缀表达式求值4.数据结构4.1 操作数栈4.2 运算符栈4.3 后缀表达式栈5.算法实现步骤5.1 输入表达式5.2 初始化栈5.3 处理表达式字符串5.4 根据算法选择相应的方法求值5.5 输出结果6.实例演示6.1 算术表达式求值示例6.2 逻辑表达式求值示例6.3 字符串表达式求值示例7.测试与验证7.1 正常表达式测试7.2 异常表达式测试7.3 性能测试8.总结与展望8.1 本文主要工作8.2 结果评估8.3 存在问题8.4 后续工作附件:附件1、算术表达式求值示例代码附件2、逻辑表达式求值示例代码附件3、字符串表达式求值示例代码法律名词及注释:1.递归下降分析法: 一种基于上下文无关文法进行递归分析的方法,用于处理表达式求值等问题。
2.栈表达式求值法: 使用栈数据结构进行表达式求值的方法。
3.中缀表达式: 常见的数学表达式写法,运算符位于运算数之间。
4.后缀表达式: 也称为逆波兰表达式,运算符位于运算数之后。
5.操作数栈: 用于存储表达式中的操作数的栈。
6.运算符栈: 用于存储表达式中的运算符的栈。
7.后缀表达式栈: 用于存储后缀表达式的栈。
数据结构课程设计之算术表达式求值
1【实验题目及要求】[问题描述]一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
假设操作数是正实数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。
引入表达式起始、结束符是为了方便。
编程利用“算符优先法”求算术表达式的值。
[基本要求](1)从键盘或文件读入一个合法的算术表达式,输出正确的结果。
(2)显示输入序列和栈的变化过程。
(3)考虑算法的健壮性,当表达式错误时,要给出错误原因的提示。
(4) 实现非整数的处理(可选功能)。
2【源代码(C语言)】#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAXSIZE 20#define OK 1#define ERROR 0#define OVERLOW 0#define YES 1#define NO 0typedefstruct{char * base;char * top;int stacksize; //最大存储量}OPTR; //字符存储栈typedefstruct{float *base;float *top;int stacksize; //最大存储量}OPND; //数值存储栈int InitOptrStack(OPTR *); //字符栈初始化函数int OptrPush(OPTR *, char); //进字符栈操作int OptrPop(OPTR*, char *); //出字符栈操作int OptrEmpty(OPTR ); //判断字符栈是否为空char GetOptrTop(OPTR); //返回字符栈顶元素int InitOpndStack(OPND *); //数值栈初始化函数int OpndPush(OPND *, float); //进数值栈操作int OpndPop(OPND*, float*); //出数值栈操作int OpndEmpty(OPND ); //判断数值栈是否为空int JudgeChar(char); //判断是否为字符float GetFloat(char *); //接收一个数字char Precede(char, char); //判断优先级操作float Caculate(float,float,char);//计算数值{char ch, noMean, ci;float num, number1, number2;OPTR optr;OPND opnd;//system("color 30");InitOptrStack(&optr);InitOpndStack(&opnd);while(1){printf(" 请输入表达式以“#”开始,以“#”结束\n ");do{ch = getchar();}while(ch !='#'); //忽略前面非‘#’字符OptrPush(&optr, ch);ch = getchar();while(ch != '#' || GetOptrTop(optr) != '#'){if(!JudgeChar(ch)){ //如果输入的是数字num = GetFloat( &ch );OpndPush(&opnd, num);else{ //输入的是字符switch(Precede(GetOptrTop(optr),ch)){case'<':OptrPush(&optr,ch); //栈顶优先级低ch = getchar();break;case'=':OptrPop(&optr,&noMean); //左右括号,把左括号出栈ch = getchar ();break;case'>': //栈顶优先级高if(OpndPop(&opnd, &number2) && OpndPop(&opnd,&number1)){OptrPop(&optr, &ci);num = Caculate(number1, number2, ci ); //出栈计算OpndPush(&opnd, num);}else{printf(" 输入过多运算符!\n");system ("PAUSE");exit(0);}break;}//witch}//else}if(opnd.top -opnd.base >= 2){printf(" 俩个括号之间缺少运算符!\n ");system ("PAUSE");exit( 0 );}OpndPop(&opnd,&num); //直接把OPND的栈元素赋值给numprintf(" 运算结果为%.3f\n", num);}system ("PAUSE");}int InitOptrStack(OPTR * OP){OP->base = (char*)malloc((MAXSIZE+1)*sizeof(char));OP->top = OP->base;OP->stacksize = MAXSIZE;return OK;}int OptrPush(OPTR *OP, char ch){*(OP->top) = ch;OP->top++;return OK;}int OptrPop(OPTR *OP, char *ch){if(OP->base == OP->top)return ERROR;else{OP->top--;*ch = *(OP->top);return OK;}}int OptrEmpty(OPTR OP){if(OP.top == OP.base )return YES;elsereturn NO;}char GetOptrTop(OPTR OP){return *(OP.top -1);}int InitOpndStack(OPND * OP){if(!(OP->base = (float*)malloc((MAXSIZE+1)*sizeof(float)))) exit(OVERLOW);OP->top = OP->base;OP->stacksize = MAXSIZE;return OK;}int OpndPush(OPND *OP, float number) {*(OP->top) = number;OP->top++;return OK;}int OpndPop(OPND *OP, float* number) {if(OP->top == OP->base)return ERROR;else{OP->top--;*number = *(OP->top);return OK;}}int OpndEmpty(OPND OP){if(OP.top == OP.base )return YES;elsereturn NO;}int JudgeChar(char ch){if(ch>='0'&&ch<= '9')return NO;elsereturn YES;}float GetFloat(char* ch){int i;float num = 0;for( i = 0; *ch>= '0'&& *ch<= '9'; i++){ num = num*10 + *ch - '0';*ch = getchar();}return num;}char Precede(char a, char b){char ch;switch(a){case'+':case'-': if(b == '*' || b == '/' || b == '(')ch = '<';elsech = '>';break;case'*':case'/': if( b == '(')ch = '<';elsech = '>';break;case'(': if(b == ')')ch = '=';elseif(b == '#'){printf(" 缺少反括号\n");system ("PAUSE");exit(0);}elsech = '<';break;case')': if(b == '('){printf(" 两个括号之间没有符号相连!\n");system("PAUSE");exit(0);}ch = '>';break;case'#': if(b == '#')ch = '=';elseif(b == ')'){printf(" 没有左括号!\n ");system("PAUSE");exit(0);}elsech = '<';break;default: printf(" 输入运算符超出范围! \n ");system ("PAUSE");exit(0);break;}return ch;}float Caculate(float number1, float number2, char ci){float num;switch( ci){case'+': num = number1 + number2; break;case'-': num = number1 - number2; break;case'*': num = number1 * number2; break;case'/': num = number1 / number2; break;}return num;}3【算法思想】根据栈的原理,建立数字栈OPND和运算符号栈OPTR,对读入的字符进行判断,存入不同的栈内,每次读入一个字符就把该字符和运算符栈顶的优先级进行比较,然后选择相应的操作,这是这个程序的核心代码,如下:switch(Precede(GetOptrTop(optr),ch)){case '<':OptrPush(&optr,ch); //栈顶优先级低ch = getchar();break;case '=':OptrPop(&optr,&noMean); //左右括号,把左括号出栈ch = getchar ();break;case '>': //栈顶优先级高if(OpndPop(&opnd, &number2) && OpndPop(&opnd, &number1)){OptrPop(&optr, &ci);num = Caculate(number1, number2, ci ); //出栈计算OpndPush(&opnd, num);}else{printf(" 输入过多运算符!\n");system ("PAUSE");exit(0);}break;}//witch4【实现效果】完全可以实现题目的要求,除了下图的错误提示,本程序还可以提示的错误有:输入过多运算符,缺少反括号,两个括号之间缺少运算符相连,缺少左括号,输入的运算符超出范围等提示。
数据结构算术表达式求值&魔王语言解释
一.实验目的1.深入了解栈和队列的特性,以便在实际问题背景下灵活运用他们,同时还将巩固对栈和队列这两种结构的构造方法的理解。
2.加深对mfc的理解。
3.加深对浮点型,字符型,整型之间的转换的熟悉。
二.实验内容1.表达式求值:表达式计算是实现程序设计语言的基本问题,也是栈的应用之一。
设计一个程序,演示用算符优先法对算术表达式求值过程。
2.魔王语言解释:有一个魔王总是使用自己的一种非常精练而抽象的语言讲话,没有人能听得懂,但他的语言是可以逐步解释承认能听懂的语言,因为他的语言是有以下两种形式的规则由人的语言逐步抽象上去的:(1)α→β1β2…βm(2)(θδ1δ2…δn)→θδnθδn-1…θδ1θ在这两种形式中,从左到右均表示解释。
试写一个魔王语言的解释系统,把他的话解释成人能听得懂的话。
三.实验步骤(可选)一.表达式求值:此次实验我用了mfc来做,实现了计算器界面的仿真,拓展了程序的功能,使到该程序不仅可以计算整型,还可以计算浮点型,负数;有判断键入的表达式格式的正误,删除错误输入,清除结果的功能;拓展了运算符,增加了平方的运算,分数化的运算,还有说明界面,计算结果序列化、读取序列化结果的功能。
1.定义栈数据类型;2.定义栈的操作,初始化,出栈,入栈;3.编写运算符优先比较函数precede;4.编写计算表达式的函数express;5.编写序列化函数archieve;6.设计计算器仿真界面;7.添加关联变量,编写相关函数。
具体代码如下://栈定义typedef struct {char* base;char* top;int stacksize;}stack;void initstack(stack &s){s.base=(char*)malloc(sizeof(char)*100);s.top=s.base;s.stacksize=100;}char gettop(stack s){char e;e=*(s.top-1);return e;}void push(stack &s,char e){*s.top++=e;}void pop(stack &s,char &e){e=*--s.top;}bool stackisempty(stack s)//empty?{if(s.top==s.base)return 1;else return 0;}char precede(char a,char b) //比较优先级函数{switch(a){case'+':switch(b){case'+':case'-':case'#':case')':return '>';case'*':case'/':case'^'://scase'(':return '<';}case'-':switch(b){case'+':case'-':case'#':case')':return '>';break; case'*':case'/':case'^'://scase'(':return '<';break; }case'*':switch(b){case'#':case'+':case'-':case')':case'*':case'/':return '>';case'^'://scase'(':return '<';}case'/':switch(b){case'#':case'+':case'-':case')':case'*':case'/':return '>';case'^'://scase'(':return '<';}case'(':if(b==')')return '=';elsereturn '<';case')':return '>';case'#':if(b!='#') return '<';else return '=';case'^'://sswitch(b){case'(':return '<';default:return '>';}}}float operate(float a,char s,float b)//运算符操作结果函数{float res=0;switch(s){case'+':res=a+b;break;case'-':res=a-b;break;case'*':res=a*b;break;case'/':res=a/b;break;case'^':res=a*a;break;}return res;}int check(CString str){int lf=0,rg=0;for(int n=0;n<str.GetLength();n++){if(str[n]=='(')lf++;if(str[n]==')')rg++;if(rg>lf)return 1;if(n<str.GetLength()-1)if(!isnum(str[n])&&!isnum(str[n+1])&&str[n+1]!='-'&&str[n+1]!='('&&str[n]!=')')//两个操作符相连return 2;}if(lf!=rg)return 1;//括号不匹配if(!isnum(str[str.GetLength()-1])&&str[str.GetLength()-1]!=')'||(!isnum(str[0])&&str[0]!='('&&str[0]!='-'))//最后一个或第一个是操作付return 2;return 0;//正确返回零}float expression(CString s)//求值函数{stack shu;//数字栈stack fu;//操作符栈initstack(shu);initstack(fu);int n=0;//表达式索引int oc=0;//字符变浮点控制变量float a=0,b=0;//a暂存操作数1,b暂存操作数2,c暂存操作结果c=0;char tem1,tem2,tem3;//弹出中间变量CString st;//把浮点型变成字符型push(fu,'#');//标志表达式开始push(shu,'a');//a标志数的分隔for(;gettop(fu)!='#'||s[n]!='#';oc=0){if(s[n]>=48&&s[n]<=57||s[n]=='.'||(s[n]=='-'&&n==0))//字符为数字或点则入数字栈{push(shu,s[n]);if(n<s.GetLength())n++;}//ifelseif(s[n]=='-')//判断—是减号还是负号switch(s[n-1]){case'+':case'-':case'*':case'/':case'(':push(shu,s[n]);//s【n-1】是以上结果的话,“—”则是负号,入数字栈if(n<s.GetLength())n++;break;default://其他为负号goto youxian;//去比较优先级}//switchelseyouxian: switch(precede(gettop(fu),s[n]))//比较优先级{case'<':push(fu,s[n]);if(s[n]!='(')push(shu,'a');if(n<s.GetLength())n++;break;case'=':pop(fu,tem1);if(n<s.GetLength())n++;break;case'>':pop(fu,tem1);a=0;for(pop(shu,tem2);tem2!='a';pop(shu,tem2))//字符转换成浮点{if(tem2=='-')a=0-a;elseif(tem2=='.'){a=a/pow(10,oc);oc=0;}elsea=(tem2-48)*pow(10,oc++)+a;}//foroc=0;b=0;for(pop(shu,tem3);tem3!='a';pop(shu,tem3))//字符转换成浮点{if(tem3=='-')b=0-b;elseif(tem3=='.'){b=b/pow(10,oc);oc=0;}elseb=(tem3-48)*pow(10,oc++)+b;}//forc=operate(b,tem1,a);if(a==0&&tem1=='/'){MessageBox(NULL,"除数不能为0!",0,0);c=0;zero=1;return 0;}st.Format("%g",c);if(st.GetLength()>=5&&st[st.GetLength()-5]=='e')//科学计数法则要转换change(st);push(shu,'a');oc=0;for(;oc<st.GetLength();oc++)//压入cpush(shu,st[oc]);}//switch}//maxforc=0;oc=0;for(pop(shu,tem2);tem2!='a';pop(shu,tem2))//字符转换成浮点{st.Format("%g",c);//MessageBox(NULL,st,0,0);if(tem2=='-')c=0-c;elseif(tem2=='.'){c=c/pow(10,oc);oc=0;}elsec=(tem2-48)*pow(10,oc++)+c;}//forreturn c;}二.魔王语言解释:(mfc实现)1.定义栈数据类型;2.定义栈的操作,初始化,出栈,入栈;3.编写魔王语言解释函数及将小写字母和中文建立一一对应关系;4.运行调试。
数据结构之算术表达式求值C语言编写
#include <stdio.h>#include <string.h>#include <stdlib.h>#define MAXLEN 100typedef struct{char ch;int level;}opt;typedef struct //定义操作栈{opt st[MAXLEN];int top;}Tstack;typedef struct //定义数据栈{double D[MAXLEN];int top;}Nstack;void Unit(Tstack *s) //初始化操作栈{s->top=-1;}//Unitvoid DUnit(Nstack *s) //初始化数据栈{s->top=-1;}//DUnitchar Push(Tstack *s,opt c) //入操作栈{s->top++;s->st[s->top]=c;return c.ch;}//Pushdouble DPush(Nstack *s,double c) //入数据栈{s->top++;s->D[s->top]=c;return c;}//DPushopt Top(Tstack *s) //操作栈栈顶{opt error={'$',-2};if(s->top>=0)return s->st[s->top];elsereturn error;}//Topdouble DTop(Nstack *s) //数据栈栈顶{if(s->top>=0)return s->D[s->top];elsereturn 0;}//DTopopt Pop(Tstack *s) //出操作栈{opt i;opt error={'$',-2};if(s->top>=0){i=s->st[s->top];s->st[s->top].ch='\0';s->top--;return i;}elsereturn error;}//Popdouble DPop(Nstack *s) //出数据栈{double i;if(s->top>=0){i=s->D[s->top];s->D[s->top]='\0';s->top--;return i;}else return 0;}//DPopint Empty(Tstack *s) //判断操作栈空{if(s->top<0)return 0;elsereturn s->st[s->top].ch;}//Emptyint NEmpty(Nstack *s) //判断数据栈空{if(s->top<0)return 0;elsereturn (int)(s->D[s->top]);}//NEmptydouble valuate(char *e) //计算{Tstack T;Nstack N;char tmp[MAXLEN]={'\0'};int i=0,leng;double d,dp;opt A={'+',1};opt R={'-',1};opt M={'*',2};opt D={'/',2};opt B={'(',-1};Unit(&T);DUnit(&N);while(*e!='\0'){while(*e >= '0' && *e <= '9' || *e == '.'){while(*e >= '0' && *e <= '9' || *e == '.'){tmp[i++]=*e++;}d=atof(tmp);DPush(&N,d);leng=strlen(tmp);for(i=0;i<leng;i++){tmp[i]='\0';}i=0;}switch(*e){case '+' :if(!Empty(&T) || Top(&T).level < A.level) {Push(&T,A);*e++;}else{while(Empty(&T) && Top(&T).level>=A.level) {switch(Pop(&T).ch){case '*' :dp=DPop(&N)*DPop(&N);DPush(&N,dp);break;case '/' :dp=DPop(&N);dp=DPop(&N)/dp;DPush(&N,dp);break;case '+':dp=DPop(&N)+DPop(&N);DPush(&N,dp);break;case '-':dp=DPop(&N);dp=DPop(&N)-dp;DPush(&N,dp);break;}}Push(&T,A);*e++;}break;case '-':if(!Empty(&T) || Top(&T).level < R.level) {Push(&T,R);*e++;}else{while(Empty(&T) && Top(&T).level>=R.level) {switch(Pop(&T).ch){case '*' :dp=DPop(&N)*DPop(&N);break;case '/' :dp=DPop(&N);dp=DPop(&N)/dp;DPush(&N,dp);break;case '+':dp=DPop(&N)+DPop(&N);DPush(&N,dp);break;case '-':dp=DPop(&N);dp=DPop(&N)-dp;DPush(&N,dp);break;}}Push(&T,R);*e++;}break;case '*':if(!Empty(&T) || Top(&T).level < M.level) {Push(&T,M);*e++;}else{while(Empty(&T) && Top(&T).level>=M.level) {switch(Pop(&T).ch){case '*' :dp=DPop(&N)*DPop(&N);DPush(&N,dp);break;case '/' :dp=DPop(&N);dp=DPop(&N)/dp;break;}}Push(&T,M);*e++;}break;case '/':if(!Empty(&T) ||Top(&T).level < D.level){Push(&T,D);*e++;}else{while(Empty(&T) &&Top(&T).level>=D.level) {switch(Pop(&T).ch){case '*' :dp=DPop(&N)*DPop(&N);DPush(&N,dp);break;case '/' :dp=DPop(&N);dp=DPop(&N)/dp;DPush(&N,dp);break;}}Push(&T,D);*e++;}break;case '(':Push(&T,B);e++;break;case ')':while(Top(&T).level!=-2){switch(Pop(&T).ch){case '*' :dp=DPop(&N)*DPop(&N);DPush(&N,dp);break;case '/' :dp=DPop(&N);dp=DPop(&N)/dp;DPush(&N,dp);break;case '+':dp=DPop(&N)+DPop(&N);DPush(&N,dp);break;case '-':dp=DPop(&N);dp=DPop(&N)-dp;DPush(&N,dp);break;}}Pop(&T);e++;break;}}while(Empty(&T)){switch(Pop(&T).ch){case '*' :dp=DPop(&N)*DPop(&N);DPush(&N,dp);break;case '/' :dp=DPop(&N);dp=DPop(&N)/dp;DPush(&N,dp);break;case '+':dp=DPop(&N)+DPop(&N);DPush(&N,dp);break;case '-':dp=DPop(&N);dp=DPop(&N)-dp;DPush(&N,dp);break;}}return DPop(&N);}//valuatevoid main(){char string[MAXLEN];char *p=string;printf("输入表达式:\n");gets(p);printf("%s=%f\n\n",string,valuate(p)); }。
数据结构表达式求值实验报告
数据结构表达式求值实验报告一、实验目的本次实验的主要目的是通过实现表达式求值的程序,深入理解数据结构和算法在解决实际问题中的应用。
具体包括掌握栈这种数据结构的操作和使用,熟悉表达式的转换和计算过程,提高编程能力和问题解决能力。
二、实验环境本次实验使用的编程语言为C++,开发工具为Visual Studio 2019。
三、实验原理表达式求值是程序设计中的一个常见问题,通常采用栈这种数据结构来实现。
表达式可以分为中缀表达式、后缀表达式和前缀表达式。
中缀表达式是我们日常使用的表达式形式,如“2 +3 4”,但直接对中缀表达式求值比较复杂。
而后缀表达式(如“2 3 4 +”)和前缀表达式(如“+2 3 4”)求值相对简单。
因此,在实现表达式求值时,通常先将中缀表达式转换为后缀表达式,然后对后缀表达式进行求值。
转换过程中,使用两个栈,一个用于存储操作数,另一个用于存储运算符。
求值过程中,根据后缀表达式的特点,从左到右依次处理操作数和运算符,进行相应的计算。
四、实验步骤1、定义数据结构定义栈类,用于存储操作数和运算符。
定义一个结构体来表示操作数和运算符。
2、中缀表达式转后缀表达式从左到右扫描中缀表达式。
遇到操作数,直接输出。
遇到运算符,根据其优先级与栈顶运算符的优先级进行比较,决定入栈或出栈操作。
3、后缀表达式求值从左到右扫描后缀表达式。
遇到操作数,入栈。
遇到运算符,从栈中取出两个操作数进行计算,将结果入栈。
4、主函数输入中缀表达式。
调用转换函数和求值函数,输出计算结果。
五、实验代码```cppinclude <iostream>include <stack>include <string>//定义操作符的优先级int priority(char op) {if (op =='+'|| op =='')return 1;if (op ==''|| op =='/')return 2;return 0;}//中缀表达式转后缀表达式std::string infixToPostfix(std::string infix) {std::stack<char> opStack;std::string postfix ="";for (char c : infix) {if (isdigit(c)){postfix += c;} else if (c =='('){} else if (c ==')'){while (!opStackempty()&& opStacktop()!='('){postfix += opStacktop();opStackpop();}opStackpop();//弹出'('} else {while (!opStackempty()&& priority(opStacktop())>=priority(c)){postfix += opStacktop();opStackpop();}opStackpush(c);}}while (!opStackempty()){postfix += opStacktop();}return postfix;}//后缀表达式求值int evaluatePostfix(std::string postfix) {std::stack<int> operandStack;for (char c : postfix) {if (isdigit(c)){operandStackpush(c '0');} else {int operand2 = operandStacktop();operandStackpop();int operand1 = operandStacktop();operandStackpop();switch (c) {case '+':operandStackpush(operand1 + operand2);break;case '':operandStackpush(operand1 operand2);break;case '':operandStackpush(operand1 operand2);break;case '/':operandStackpush(operand1 / operand2);break;}}}return operandStacktop();}int main(){std::string infixExpression;std::cout <<"请输入中缀表达式: ";std::cin >> infixExpression;std::string postfixExpression = infixToPostfix(infixExpression);int result = evaluatePostfix(postfixExpression);std::cout <<"表达式的计算结果为: "<< result << std::endl;return 0;}```六、实验结果输入不同的中缀表达式,如“2 +3 4”“( 2 + 3 )4”等,程序能够正确地将其转换为后缀表达式,并计算出结果。
数据结构课设 表达式求值
《计算表达式》课程设计报告标题:计算表达式单位:报告人:指导教师:编程环境:VC6时间:2011年12月20日一、设计要求对于输入的一个中缀表达式,判断表达式是否合法。
如果合法,把中缀表达式转换成一棵二叉树,然后通过后根遍历计算表达式的值,输出运算结果。
合法表达式不能为空,可以出现在表达式中的字符有:*运算符“+”、“-”、“*”、“/”;*左右括号“(”、“)”;*整数(可以是多位的);*空格符和制表符。
例如:表达式为“20+(3*(4+46)-6)/2-134”将得到结果-42。
数据结构采用二叉树的链接表示。
二、题目分析由设计要求可以确定程序的几大模块,读入源程序(1)读入中缀表达式(2)从中缀表达式ex(长度为n)创建二叉树(3)后根遍历计算表达式的值(4)输出运算结果进一步确定几个子程序及其相互之间的调用关系为:三.流程图四.全局变量与子程序功能说明(1)int extoBinTree(PBinTree pbtree,const char *ex,int n)从中缀表达式ex(长度为n)创建二叉树。
若是一个合法的表达式,则返回TRUE,且算法结束时*pbtree存放二叉树的根节点的地址;否则返回FALSE(2)int cal(BinTree btree,int*presult)计算二叉树btree所代表的表达式的值。
若是一个合法的表达式,则返回TRUE,且算法结束时*presult中存放计算结果;否则,返回FALSE.(3)void delete_BTree(PBinTree ptree){BinTree temp=(*ptree);if(temp==NULL) return;delete_BTree(&(temp->llink));delete_BTree(&(temp->rlink));free(temp);}作用为,当输入的程序有误时,或者一段表达式已经运算结束时清除储存空间,为下一段表达式的计算作准备。
表达式求值(数据结构)
表达式求值(数据结构)表达式求值(数据结构)一、引言表达式求值是计算机科学中一个重要的概念,它是计算机程序中常见的操作之一。
通过对表达式中的运算符和操作数进行计算,可以得到表达式的结果。
本文将介绍表达式求值的相关知识和算法,并提供一个基于数据结构的表达式求值的范本。
二、基本概念1.表达式:由操作数、运算符和括号组成的符号串,用于表示一个计算过程。
2.操作数:表达式中用于参与计算的数值或变量。
3.运算符:表达式中用于进行运算的符号,如加减乘除等。
4.括号:用于控制运算优先级和改变运算次序的符号。
三、表达式求值的算法表达式求值的基本思路是通过遍历表达式字符串并利用栈来进行计算。
1.建立一个操作数栈和一个运算符栈。
2.从左到右遍历表达式字符串,依次处理每个字符。
3.如果当前字符是操作数,则直接入操作数栈。
4.如果当前字符是运算符,则进行如下处理:●如果运算符栈为空或栈顶运算符是左括号,则将当前运算符入运算符栈。
●如果当前运算符的优先级高于栈顶运算符的优先级,则将当前运算符入运算符栈。
●如果当前运算符的优先级低于或等于栈顶运算符的优先级,则从运算符栈顶取出一个运算符进行计算,并将结果入操作数栈,直到栈顶运算符的优先级低于当前运算符,然后将当前运算符入运算符栈。
5.如果当前字符是左括号,则将其入运算符栈。
6.如果当前字符是右括号,则从运算符栈顶取出一个运算符进行计算,并将结果入操作数栈,直到取出的运算符是左括号。
7.遍历完表达式字符串后,将运算符栈中剩余的运算符依次取出进行计算,并将结果入操作数栈。
8.操作数栈中最后剩下的元素即为表达式的求值结果。
四、示例代码```pythonclass ExpressionEvaluation:def __init__(self, expression):self.expression = expressionself.operators = []self.operands = []self.precedence = {'+': 1, '.': 1, '': 2, '/': 2}def evaluate(self):for char in self.expression:if char.isdigit():self.operands.append(int(char))elif char in self.precedence:while self.operators andself.operators[.1] != '(' and self.precedence[char] <= self.precedence[self.operators[.1]]:lculate()self.operators.append(char)elif char == '(':self.operators.append(char)elif char == ')':while self.operators[.1] != '(':lculate()self.operators.pop()while self.operators:lculate()return self.operands[.1]def calculate(self):operator = self.operators.pop()operand2 = self.operands.pop()operand1 = self.operands.pop()if operator == '+':self.operands.append(operand1 + operand2)elif operator == '.':self.operands.append(operand1 ●operand2) elif operator == '':self.operands.append(operand1 operand2) elif operator == '/':self.operands.append(operand1 / operand2) expression = \。
表达式求值 数据结构
#include<stdio.h>#include<string.h>#include<stdlib.h>#define STACK_INIT_SIZE 100#define STACKINCREMENT 10 typedef struct{char *base;char *top;int stacksize;}OPTRStack;typedef struct{int *base;int *top;int stacksize;}OPNDStack;void InitStack(OPTRStack *s); void InitStack(OPNDStack *s); void push(OPNDStack *s,int e); void push(OPTRStack *s,char e); void pop(OPTRStack *s,char *e); void pop(OPNDStack *s,int *e); int GetTop(OPNDStack s);char GetTop(OPTRStack s);int EvaluateExpression(char *exp); char Precede(char ch1,char ch2); void main(){char exp[100];int result;printf("请输入一个表达式\n");scanf("%s",exp);result=EvaluateExpression(exp);printf("表达式的结果是 result=% d",result);}void InitStack(OPTRStack *s){s->base=(char *)malloc(STACK_INIT_SIZE * sizeof(char));if(!s->base)exit(0);s->top=s->base;s->stacksize=STACK_INIT_SIZE;}void InitStack(OPNDStack *s){s->base=(int *)malloc(STACK_INIT_SIZE * sizeof(int));if(!s->base)exit(0);s->top=s->base;s->stacksize=STACK_INIT_SIZE;}void push(OPTRStack *s,char e){if(s->base-s->base>=s->stacksize) //栈满,追加存储空间{s->base=(char *)realloc(s->base,(s->stacksize+STACKINCREMENT) * sizeof(char));if(!s->base)exit(0);s->top=s->base+s->stacksize;s->stacksize+=STACKINCREMENT;}*s->top++=e;}void push(OPNDStack *s,int e){if(s->base-s->base>=s->stacksize) //栈满,追加存储空间{s->base=(int *)realloc(s->base,(s->stacksize+STACKINCREMENT) * sizeof(int));if(!s->base)exit(0);s->top=s->base+s->stacksize;s->stacksize+=STACKINCREMENT;}*s->top++=e;}void pop(OPTRStack *s,char *e){if(s->top==s->base)exit(0);*e=*--s->top;}void pop(OPNDStack *s,int *e){if(s->top==s->base)exit(0);*e=*--s->top;}int EvaluateExpression(char *exp){OPTRStack OPTR;OPNDStack OPND;char theta,x;int a,b,d=0;InitStack(&OPTR);push(&OPTR,'#');InitStack(&OPND);while(*exp!='#'||(GetTop(OPTR)!='#')){if(*exp>='0'&&*exp<='9'){do{d=10*d+*exp-'0';exp++;}while(*exp>='0'&&*exp<='9');push(&OPND,d);}else{d=0;switch(Precede(GetTop(OPTR),*exp)){case'<':push(&OPTR,*exp);exp++;break;case'=':pop(&OPTR,&x);exp++;break;case'>':pop(&OPTR,&theta);pop(&OPND,&b);pop(&OPND,&a);switch(theta){case '+':push(&OPND,a+b);break;case '-':push(&OPND,a-b);break;case '*':push(&OPND,a*b);break;case '/':push(&OPND,a/b);break;}break;}}}return GetTop(OPND);}char Precede(char ch1,char ch2){char OP[]="+-*/()#";char tab[7][8]={">><<<>>",">><<<>>",">>>><>>",">>>><>>","<<<<<=",">>>> >>","<<<<<=",};for(int i=0;i<7;i++)if(OP[i]==ch1)break;for(int j=0;j<7;j++)if(OP[j]==ch2)break;return tab[i][j];}int GetTop(OPNDStack s){if(s.base==s.top)return 0;elsereturn *(s.top-1);}char GetTop(OPTRStack s){if(s.base==s.top)return 0;elsereturn *(s.top-1);}。
数据结构——表达式求值(堆栈)
数据结构——表达式求值(堆栈)作者:pear ry 时间:10.5.17限于二元运算符的表达式定义:表达式::=(操作数)+(运算符)+(操作数)操作数::=简单变量|表达式简单变量::=标识符|无符号整数在计算机中,表达式可以有三中不同的标识方法设E xp =S1 +OP +S2则,称 op+ S1+ S2为表达式的“前缀表达式”称 S1+ OP+ S2为表达式的“中缀表达式”称 S1 + S2 + OP为表达式的“后缀表示法”可见,它以运算符所在不同位置命名的。
例如: Exp= a * b +(c -d/e)*f前缀式:+ * ab * - c /d e f中缀式: a * b +c - d / e* f后缀式:a b * c de / - f *+结论:2)运算符的相对次序不同;3)中缀式丢去了括弧信息,致使运算次序不正确;4)前缀式的运算规则为:连续出现的两个操作数和在它们之前且紧靠它们的运算符构成一个最小表达式; 5)后缀式的运算规则为:运算符在式中出现的顺序恰为表达式的运算顺序;每个运算符和在它之前出现且紧靠它的两个操作数构成一个最小表达式;由上面可知,后缀式最适合表达式运算的,实际上大多数编译器上用的也是后缀式。
那么如何用后缀式求值?后缀式操作的规则:先找运算符,再找操作数。
也就是碰到操作数,保留,碰到运算符,就运算,运算后结果保留在前操作数位置。
根据操作的规则,自然能想到用栈来存取。
下面来演示下上面的例子:例: Exp= a* b +(c - d/e)*f;后缀式:a b * c de / - f *+;入栈顺序:a b * cd e / - f* +;1.a入栈,b入栈;2.遇到“*”操作符,运算“a*b”表达式,保留在a(前操作数)的位置;3.c,d,e,依次进栈;4.遇到“/”操作符,执行“d/e”运算(最近的两个操作数),存入d的位置;5.遇到“-”操作符,将c与d位置的值(设为x)执行“c-x”运算,存入c,(设为y);6.f入栈;7.遇到“*”操作符,执行“y*f”运算(设为z),存入y的位置;8.遇到“+”操作符,执行“a+z”运算,存入a位置;9.运算结束,退栈,输出结果;OK,现在解决了如行用后缀式求值,One more thin g :如何得到后缀式表达式。
数据结构课程设计-表达式求值【
if (s.top-s.base >= s.stacksize)
{
printf("运算符栈满!\n");
s.base=(char*)realloc (s.base,(s.stacksize+5)*sizeof(char));
候
if(!s.base) exit (OVERFLOW);
s.top=s.base+s.stacksize;
{
e=*--s.top;
return OK;
}
}
int StackTraverse(SqStack&s) //运算符栈的遍历
{
char *t;
t=s.base ;
if (s.top==s.base)
{
printf("运算符栈为空!\n");〃栈为空栈的时候返回ERROR
return ERROR;
}
while(t!=s.top)
s.top=s.base;
s.stacksize=50;
return OK;
}
char GetTop(SqStack s,char &e)//运算符取栈顶元素
{
if (s.top==s.base)//栈为空的时候返回ERROR
{
printf("运算符栈为空!\n");
return ERROR;
}
else
加5个存储空间
if(!s.base) exit (OVERFLOW);
s.top=s.base+s.stacksize;
s.stacksize+=5;
}
*(s.top)++=e;//把e入栈
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//代码部分:
#include<iostream>
using namespace std;
#define MAXSIZE 100
typedef char ElemType;//定义栈
typedef struct{
char a[MAXSIZE];
int top;//栈顶指针
}SqStack;
char op[8]={'+','-','*','/','(',')','#'};//运算符集
char ch[7][7]={ //运算符优先关系集{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='}
};
void InitStack(SqStack &s)
{
for(int i=0;i<MAXSIZE;i++)
s.a[i]=0;
s.top=0;
}
char Push(SqStack &s,ElemType e)
{
if (s.top==MAXSIZE-1) cout<<"Overflow!"<<endl;
else
{ s.top=s.top+1;
s.a[s.top-1]=e;
}
return e;
ElemType Pop(SqStack &s,ElemType &e)
{
if (s.top==0)
{
cout<<"Stack is empty!"<<endl; return(-1);
}
else
{
e=s.a[s.top-1];
s.top=s.top-1;
return e;
}
}
ElemType GetTop(SqStack s,ElemType& e)
{
if (s.top==0) { cout<<"Stack is empty!"<<endl; return(-1); } else
e=s.a[s.top-1];
return e;
}
bool ifnot(char c)//判断是否是运算符
{
for(int i=0;i<8;i++)
{
if (c==op[i])
return 1;}
return 0;
}
int FirstValue(char ch) //判断字符在数组中的位置
{
int k;
switch(ch)
{
case '+':k=0;break;
case '-':k=1;break;
case '*':k=2;break;
case '/':k=3;break;
case '(':k=4;break;
case ')':k=5;break;
case '#':k=6;break;
}
return k;
}
char Precede(char ch1,char ch2)//判断优先关系的函数
{
int i=0,j=0;
i=FirstValue(ch1);//调用函数
j=FirstValue(ch2);//调用函数
return ch[i][j];//返回优先关系的字符
}
char Operate(int ch3,char theta ,int b)
{
int result;
if(theta=='+'){result=(ch3-'0')+(b-'0');}
if(theta=='-'){result=(ch3-'0')-(b-'0');}
if(theta=='*'){result=(ch3-'0')*(b-'0');}
if(theta=='/'){result=(ch3-'0')/(b-'0');}
return (result+'0');
}
int main()
{
char c;//用来接收字符
char x,theta,e,b,a1,m;//定义临时的字符变量
x=m=theta=e=b=a1=NULL;//给临时变量赋值
SqStack OPTR,OPND;//定义运算符栈和操作数栈
InitStack(OPTR) ;Push(OPTR,'#');//初始化,让#是运算符栈底元素InitStack(OPND);//初始化操作数栈
cout<<"请输入表达式,以#结束"<<endl;
c=getchar();
while(c!='#'||GetTop(OPTR,e)!='#')
{
if(!ifnot(c))//判断是否是运算符
{
Push(OPND,c);
c=getchar();
}//不是运算符则进栈
else
switch (Precede(GetTop(OPTR,e),c))
{
case'<':Push(OPTR,c);c=getchar();break;//栈顶元素优先权低
case'=':Pop(OPTR,x);c=getchar();break;//脱括号并接受下一字符
case'>':Pop(OPTR,theta);Pop(OPND,b);Pop(OPND,a1);//退栈并将运算结果入栈
Push(OPND,Operate(a1,theta,b));
break;
}//swith
}//while
m=GetTop(OPND,e);
cout<<"the last result is "<<m-'0'<<endl;//输出最后结果
return 0;
}
//代码结束:
运行结果:。