表达式求值(数据结构)
表达式求值源代码(数据结构课程设计)
表达式求值源代码(数据结构课程设计)表达式求值源代码(数据结构课程设计) 数据结构课程设计源代码:表达式求值0900340131 张宁2011.6.26 #include #include /*函数功能:将数字字符串转变成相应的数*/ /*函数参数:char类型数组f,指向int类型变量的指针i*/ /*函数返回值:int类型。
返回数字字符串对应的数*/ int readnumber(char f[],int *i) { int x=0; while(f[*i]>= 0 } opst[top]=e[i]; top++; /*当前元素进栈*/ } i++; /*处理下一个元素*/ } while(top) /*栈中还有的全部运算符赋值到数组f中,包括# */ { f[j++]=opst[--top]; } } main() { int i=0,result,flog=0,flog2=0; char a[100],b[100],x,w; /*数组a用来保存中缀表达式,数组b用来表达后缀表达式,*/printf(“~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~\n“); printf(“ 0代表退出系统\n“); printf(“ 1代表输入算术表达式\n“); printf(“ 2代表判断输入的算术表达式的正确性\n“); printf(“ 3代表查看算术表达式的中缀表达式\n“); printf(“ 4代表查看算术表达式的后缀表达式\n“); printf(“ 5代表给出输入的算术表达式的最终结果\n“); printf(“ 规定:第一步必须先输入算术表达式,然后才能进行其他的操作\n“);printf(“~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~\n“); printf(“版权所有,盗版必究张宁2010/6/24 \n\n\n“); do { printf(“请输入您要操作所对应的数字:“); fflush(stdin); scanf(“%c“, if(48(以#号结尾!) “); i=0; do { scanf(“%c“, }while(a[i++]!= # ); flog=1;printf(“\n\n\n“); break; } else { printf(“请输入正确的选项!\n“); } }while(w!= n } else { printf(“请输入算术表达式:(以#号结尾!) “); do { scanf(“%c“, }while(a[i++]!= # ); flog=1; printf(“\n\n\n“); } break; case 2 : if(flog==0) { printf(“您还没有输入过表达式!\n请您按照规定先输入后判断!\n\n\n“); } else { flog2=1; if(judge(a)) { printf(“表达式符合要求!\n您可以继续下面的操作!\n“); } else { printf(“表达式不符合要求!\n请重新输入!\n“); break; } } break; case 3 : if(flog==0) { printf(“您还没有输入过表达式!\n请您按照规定先输入后算术表达式的中缀表达式\n\n\n“); break; } else if(flog2==0) { printf(“您还没有判断表达式的正确性!\n请您按照规定先判断表达式的正确性后查看算术表达式的中缀表达式\n\n\n“); break; } else { printf(“中缀表达式为:“); i=0; do { printf(“%c“,a[i]); }while(a[i++]!= # ); /*i++;*/printf(“\n\n\n“); } break; case 4 : if(flog==0) { printf(“您还没有输入过表达式!\n请您按照规定先输入后算术表达式的中缀表达式\n\n\n“); break; } else if(flog2==0) { printf(“您还没有判断表达式的正确性!\n请您按照规定先判断表达式的正确性后查看算术表达式的中缀表达式\n\n\n“); break; } else { postfix(a,b); printf(“后缀表达式为:\n“); i=0; do { printf(“%c“,b[i]); }while(b[i++]!= # ); /*i++;*/ printf(“\n\n\n“); } break; case 5 : fflush(stdin); if(f log==0) { printf(“您还没有输入过表达式!\n请您按照规定先输入表达式\n\n\n“); break; } else if(flog2==0) { printf(“您还没有判断表达式的正确性!\n请您按照规定先判断表达式的正确性后查看算术表达式的中缀表达式\n\n\n“); break; } else { /*postfix(a,b);*/ result=evalpost(b); printf(“运算结果为:“); for(i=0;a[i]!= # ;i++) { printf(“%c“,a[i]); } printf(“=%d\n\n\n“,result); } break; } } else { printf(“没有此项操作,请重新输入!\n\n\n“); } }while(x!= 0 ); printf(“\n您已退出系统!\n欢迎下次使用\n“); }。
数据结构课程设计-表达式求值【完整版】
XXXXXX大学《数据结构》课程设计报告班级:学号:姓名:指导老师:目录一算术表达式求值一、需求分析二、程序得主要功能三、程序运行平台四、数据结构五、算法及时间复杂度六、测试用例七、程序源代码二感想体会与总结算术表达式求值一、需求分析一个算术表达式就是由操作数(operand)、运算符(operator)与界限符(delimiter)组成得。
假设操作数就是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号与表达式起始、结束符“#”,如:#(7+15)*(23—28/4)#。
引入表达式起始、结束符就是为了方便.编程利用“算符优先法”求算术表达式得值.二、程序得主要功能(1)从键盘读入一个合法得算术表达式,输出正确得结果。
(2)显示输入序列与栈得变化过程。
三、程序运行平台Visual C++6、0版本四、数据结构本程序得数据结构为栈。
(1)运算符栈部分:struct SqStack //定义栈{char *base; //栈底指针char *top; //栈顶指针intstacksize; //栈得长度};intInitStack (SqStack &s) //建立一个空栈S{if (!(s、base= (char *)malloc(50*sizeof(char))))exit(0);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;}elsee=*(s、top-1); //栈不为空得时候用e做返回值,返回S得栈顶元素,并返回OK returnOK;}int Push(SqStack&s,char e) //运算符入栈{if (s、top—s、base >= s、stacksize)ﻩ{printf("运算符栈满!\n");ﻩs、base=(char*)realloc(s、base,(s、stacksize+5)*sizeof(char));//栈满得时候,追加5个存储空间if(!s、base)exit (OVERFLOW);s、top=s、base+s、stacksize;s、stacksize+=5;}ﻩ*(s、top)++=e;//把e入栈ﻩreturn OK;}int Pop(SqStack &s,char &e) //运算符出栈{if (s、top==s、base) //栈为空栈得时候,返回ERROR{printf("运算符栈为空!\n”);ﻩ return ERROR;}else{ﻩﻩe=*-—s、top;//栈不为空得时候用e做返回值,删除S得栈顶元素,并返回OK return OK;}}int StackTraverse(SqStack&s)//运算符栈得遍历{ﻩchar *t;ﻩt=s、base;ﻩif (s、top==s、base){ﻩ printf(”运算符栈为空!\n”); //栈为空栈得时候返回ERRORreturn ERROR;}while(t!=s、top){ﻩﻩprintf(" %c",*t); //栈不为空得时候依次取出栈内元素t++;ﻩ}return ERROR;}(2)数字栈部分:struct SqStackn//定义数栈{int *base; //栈底指针int*top; //栈顶指针int stacksize; //栈得长度};intInitStackn (SqStackn &s) //建立一个空栈S{s、base=(int*)malloc(50*sizeof(int));if(!s、base)exit(OVERFLOW);//存储分配失败s、top=s、base;s、stacksize=50;return OK;}int GetTopn(SqStackn s,int&e) //数栈取栈顶元素{if(s、top==s、base){printf("运算数栈为空!\n");//栈为空得时候返回ERRORﻩ return ERROR;}elseﻩe=*(s、top-1);//栈不为空得时候,用e作返回值,返回S得栈顶元素,并返回OKreturnOK;}int Pushn(SqStackn &s,int e) //数栈入栈{if(s、top—s、base>=s、stacksize){ﻩﻩprintf("运算数栈满!\n");//栈满得时候,追加5个存储空间ﻩs、base=(int*)realloc (s、base,(s、stacksize+5)*sizeof(int));if(!s、base) exit (OVERFLOW);ﻩs、top=s、base+s、stacksize;//插入元素e为新得栈顶元素s、stacksize+=5;}*(s、top)++=e; //栈顶指针变化returnOK;}int Popn(SqStackn &s,int &e)//数栈出栈{ﻩif (s、top==s、base){ﻩ printf("运算符栈为空!\n");//栈为空栈得视时候,返回ERRORﻩ return ERROR;ﻩ}else{ﻩﻩe=*—-s、top;//栈不空得时候,则删除S得栈顶元素,用e返回其值,并返回OK ﻩreturnOK;}}int StackTraversen(SqStackn &s)//数栈遍历{ﻩint*t;ﻩt=s、base ;ﻩif(s、top==s、base)ﻩ{printf("运算数栈为空!\n”);//栈为空栈得时候返回ERRORﻩ return ERROR;ﻩ}ﻩwhile(t!=s、top)ﻩ{printf(” %d”,*t); //栈不为空得时候依次输出t++;}return ERROR;}五、算法及时间复杂度1、算法:建立两个不同类型得空栈,先把一个‘#’压入运算符栈。
黑龙江大学数据结构考试题
《数据结构课程设计》讲义一、表达式求值问题1.1 问题定义及设计要求表达式求值是程序设计语言编译中的一个最基本问题。
人们在书写表达式时通常采用将运算符放在两个操作数中间的“中缀”表示形式,称为中缀表达式。
但是这种表达式形式对计算机处理来说是不太适合的。
在计算机领域,经常将算术表达式表示成“后缀”表示形式,称为后缀表达式。
如: 中缀表达式3+2*(7-5)对应的后缀表达式为3275-*+。
要求实现(1)算数四则运算中缀表达式到后缀表达式的转换;(2)后缀表达式的求值;(3)中缀表达式的求值。
要求以字符序列的形式从终端输入语法正确的、不含变量的整数表达式。
要求演示在求值过程中运算符栈、操作数栈、输入字符和主要操作过程及运算结果。
要求配备菜单,含如下选项:------------------------------------------------------1. 中缀表达式到后缀表达式的转换2. 后缀表达式的计算3. 中缀表达式的计算4. 退出-------------------------------------------------------1.2 中缀表达式到后缀表达式的转换(1)问题分析假设在算术表达式中只含四种基本运算符,操作数是10以内的整数。
假设一个中缀表达式中没有括号(如4+2*3,它的后缀表达式为423*+)。
在扫描到中缀表达式中的2后,能立即输出+,因为*具有较高优先级,必须必须先运算,因此需先保存+。
也就是说,新扫描运算符优先级必须与前一个运算符的优先级做比较,如果新的运算符优先级高,就要像前一个运算符那样保存它,直到扫描到第二个操作数,将它输出后才能将该运算符输出。
因此,在转化中必须保存两个运算符,后保存的运算符先输出。
用计算机来实现这个转化过程,就需要用到能后进先出的数据结构----栈。
如果在中缀表达式中含小括号,那么由于括号隔离了优先级规则,它在整个表达式的内部产生了完全独立的子表达式。
数据结构课程设计四则运算表达式求值(C语言版)
数据结构课程设计四则运算表达式求值(C语⾔版) 明⼈不说暗话,直接上,输⼊提取码z3fy即可下载。
⽂件中包含程序,程序运⾏⽂件,设计报告和测试样例,应有尽有,欢迎⼩伙伴们在中下载使⽤。
本课程设计为四则运算表达式求值,⽤于带⼩括号的⼀定范围内正负数的四则运算标准(中缀)表达式的求值。
注意事项:1、请保证输⼊的四则表达式的合法性。
输⼊的中缀表达式中只能含有英⽂符号“+”、“-”、“*”、“/”、“(”、“)”、“=”、数字“0”到“9”以及⼩数点“.”,输⼊“=”表⽰输⼊结束。
例如9+(3-1)*3.567+10/2=,特别是请勿输⼊多余空格和中⽂左右括号。
2、输⼊的中缀表达式默认限定长度是1001,可根据具体情况调整字符串数组的长度。
3、请保证输⼊的操作数在double数据类型范围内,单个数字有效数字长度不可超过15位。
本课程设计中操作数是C语⾔中的双精度浮点数类型。
4、本课程设计中的运算数可以是负数,另外如果是正数可直接省略“+”号(也可带“+”号)。
下⾯的程序正常运⾏需要在上⾯的百度⽹盘中下载相应⽂件,否则⽆法正常使⽤哦。
1/*本程序为四则运算表达式求值系统,⽤于计算带⼩括号的四则运算表达式求值。
2具体算法:3先将字符串处理成操作单元(操作数或操作符),再利⽤栈根据四则运算4的运算法则进⾏计算,最后得出结果。
*/56 #include<stdio.h>7 #include<ctype.h>8 #include<stdlib.h>9 #include<string.h>10 #include<stdlib.h>11 #include<ctype.h>1213const int Expmax_length = 1001;//表达式最⼤长度,可根据适当情况调整14struct Ope_unit15 {//定义操作单元16int flag;//=1表⽰是操作数 =0表⽰是操作符 -1表⽰符号单元17char oper;//操作符18double real;//操作数,为双精度浮点数19 };2021void Display();//菜单22void Instru(); //使⽤说明23int Check(char Exp_arry[]);24void Evalua(); //先调⽤Conver操作单元化,再调⽤Calculate函数计算结果并输出25int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[]);//将字符串处理成操作单元26int Isoper(char ch);//判断合法字符(+ - * / ( ) =)27int Ope_Compar(char ope1,char ope2);//操作符运算优先级⽐较28double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag);//⽤栈计算表达式结果29double Four_arithm(double x,double y,char oper);//四则运算3031int main()32 {33int select;34while(1)35 {36 Display();37 printf("请输⼊欲执⾏功能对应的数字:");38 scanf("%d",&select);39 printf("\n");40switch(select)41 {42case1: Evalua(); break;43case2: Instru(); break;44case0: return0;45default : printf("⽆该数字对应的功能,请重新输⼊\n");46 system("pause");47 }48 }49return0;50 }5152int Check(char Exp_arry[])53 {//检查是否有⾮法字符,返回1表⽰不合法,0表⽰合法54int Explength=strlen(Exp_arry),i;55for(i=0;i<Explength;i++)56 {57if(!Isoper(Exp_arry[i]) && Exp_arry[i] != '.' && !isdigit(Exp_arry[i]))58return1;59if(isdigit(Exp_arry[i]))60 {61int Dig_number=0,Cur_positoin=i+1;62while(isdigit(Exp_arry[Cur_positoin]) || Exp_arry[Cur_positoin]=='.')63 {64 Dig_number++;65 Cur_positoin++;66 }67if(Dig_number >= 16)//最多能够计算15位有效数字68return1;69 }70 }71return0;72 }7374void Evalua()75 {//先调⽤Conver函数将字符串操作单元化,再调⽤Calculate函数计算结果并输出76char Exp_arry[Expmax_length];77int flag=0;//假设刚开始不合法,1表达式合法,0不合法78struct Ope_unit Opeunit_arry[Expmax_length];7980 getchar();//吃掉⼀个换⾏符81 printf("请输⼊四则运算表达式,以=结尾:\n");82 gets(Exp_arry);83 flag=Check(Exp_arry);84if(flag)85 printf("该表达式不合法!\n");86else87 {88int Opeunit_count = Conver(Opeunit_arry,Exp_arry);89double ans = Calculate(Opeunit_arry,Opeunit_count,flag);90if(flag)91 {92 printf("计算结果为:\n");93 printf("%s%lf\n",Exp_arry,ans);94 }95else96 printf("该表达式不合法!\n");97 }98 system("pause");99 }100101int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[])102 {//将字符串操作单元化103int Explength=strlen(Exp_arry);104int i,Opeunit_count=0;105for(i=0;i<Explength;i++)106 {107if(Isoper(Exp_arry[i]))//是操作符108 {109 Opeunit_arry[Opeunit_count].flag=0;110 Opeunit_arry[Opeunit_count++].oper=Exp_arry[i];111 }112else//是操作数113 {114 Opeunit_arry[Opeunit_count].flag=1;115char temp[Expmax_length];116int k=0;117for(; isdigit(Exp_arry[i]) || Exp_arry[i]=='.' ;i++)118 {119 temp[k++]=Exp_arry[i];120 }121 i--;122 temp[k]='\0';123 Opeunit_arry[Opeunit_count].real=atof(temp);//将字符转化为浮点数124125//负数126if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0127 && Opeunit_arry[Opeunit_count-1].oper=='-')128 {129 Opeunit_arry[Opeunit_count-1].flag = -1;130 Opeunit_arry[Opeunit_count].real *= -1;131 }// -9132if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0133 && Opeunit_arry[Opeunit_count-1].oper=='-' && Opeunit_arry[Opeunit_count-2].flag==0 134 && Opeunit_arry[Opeunit_count-2].oper !=')')135 {136 Opeunit_arry[Opeunit_count-1].flag = -1;137 Opeunit_arry[Opeunit_count].real *= -1;138 }// )-9139140//正数141if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0142 && Opeunit_arry[Opeunit_count-1].oper=='+')143 {144 Opeunit_arry[Opeunit_count-1].flag = -1;145 }// +9146if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0147 && Opeunit_arry[Opeunit_count-1].oper=='+' && Opeunit_arry[Opeunit_count-2].flag==0148 && Opeunit_arry[Opeunit_count-2].oper !=')')149 {150 Opeunit_arry[Opeunit_count-1].flag = -1;151 }// )+9152 Opeunit_count++;153 }154 }155/*for(i=0;i<Opeunit_count;i++)156 {//查看各操作单元是否正确,1是操作数,0是操作符157 if(Opeunit_arry[i].flag == 1)158 printf("该单元是操作数为:%lf\n",Opeunit_arry[i].real);159 else if(Opeunit_arry[i].flag == 0)160 printf("该单元是操作符为:%c\n",Opeunit_arry[i].oper);161 else162 printf("该单元是负号符为:%c\n",Opeunit_arry[i].oper);163 }*/164return Opeunit_count;165 }166167double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag)168 {//根据运算规则,利⽤栈进⾏计算169int i,dS_pointer=0,oS_pointer=0;//dS_pointer为操作数栈顶指⽰器,oS_pointer为操作符栈顶指⽰器170double Dig_stack[Expmax_length];//操作数栈(顺序存储结构)171char Ope_stack[Expmax_length];//操作符栈172173for(i=0;i<Opeunit_count-1;i++)174 {175if( Opeunit_arry[i].flag != -1 )176 {177if(Opeunit_arry[i].flag)//是操作数178 {179 Dig_stack[dS_pointer++]=Opeunit_arry[i].real;//⼊操作数栈180//printf("%lf\n",Digit[dS_pointer-1]);181 }182else//是操作符 + - * / ( )183 {184//操作符栈为空或者左括号⼊栈185if(oS_pointer==0 || Opeunit_arry[i].oper=='(')186 {187 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;188//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);189 }190else191 {192if(Opeunit_arry[i].oper==')')//是右括号将运算符⼀直出栈,直到遇见左括号193 {194 oS_pointer--;//指向栈顶195 dS_pointer--;//指向栈顶196while(Ope_stack[oS_pointer] != '(' && oS_pointer != 0)197 {198 Dig_stack[dS_pointer-1] = Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 199 Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈200201 dS_pointer--;//前⼀个操作数出栈202//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);203 }204 oS_pointer--;//左括号出栈205206 oS_pointer++;//恢复指向栈顶之上207 dS_pointer++;208 }209else if(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer-1]))//和栈顶元素⽐较210 {211 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;212//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);213 }214else//运算符出栈,再将该操作符⼊栈215 {216 oS_pointer--;//指向栈顶217 dS_pointer--;//指向栈顶218while(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer])==0 && oS_pointer != -1) 219 {//当前操作符⽐栈顶操作符优先级⾼220 Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 221 Ope_stack[oS_pointer--]);222 dS_pointer--;223//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);224 }225 oS_pointer++;//恢复指向栈顶之上226 dS_pointer++;227 Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;228 }229 }230 }231 }232 }233/*for(i=0;i<oS_pointer;i++)234 printf("操作符栈%oS_pointer\Ope_u_count",Operator[i]);235 for(i=0;i<dS_pointer;i++)236 printf("操作数栈%lf\n",Digit[i]);*/237 oS_pointer--;//指向栈顶元素238 dS_pointer--;//指向栈顶元素239while(oS_pointer != -1)240 {241 Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer], 242 Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈243 dS_pointer--;//前⼀个操作数出栈244//printf("操作数栈顶元素为%lf\Ope_u_count",Digit[dS_pointer]);245 }246//printf("%dS_pointer,%dS_pointer\n",oS_pointer,dS_pointer);247if(oS_pointer==-1 && dS_pointer==0)248 flag=1;//为1表⽰表达式合法249return Dig_stack[0];250 }251252int Ope_Compar(char ope1,char ope2)253 {//操作符运算优先级⽐较254char list[]={"(+-*/"};255int map[5][5]={//先⾏后列,⾏⽐列的运算级优先级低为0,⾼为1256// ( + - * /257/* ( */1,0,0,0,0,258/* + */1,0,0,0,0,259/* - */1,0,0,0,0,260/* * */1,1,1,0,0,261/* / */1,1,1,0,0 };262int i,j;263for(i=0;i<5;i++)264if(ope1==list[i]) break;265for(j=0;j<5;j++)266if(ope2==list[j]) break;267return map[i][j];268 }269270double Four_arithm(double x,double y,char oper)271 {//四则运算272switch(oper)//保证不含其它运算符273 {274case'+': return x+y;275case'-': return x-y;276case'*': return x*y;277case'/': return x/y;//y不能为0278default : return0;279 }280 }281282int Isoper(char ch)283 {//判断合法字符 + - * / ( ) =284if(ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='(' || ch==')' || ch=='=')285return1;286return0;287 }288289void Display()290 {//打印菜单291 system("cls");292 printf("/******************************************************************************/\n");293 printf("\t\t 欢迎使⽤本四则运算表达式求值系统\n");294 printf("\n\t说明:建议请您先阅读使⽤说明,再输⼊相应的数字进⾏操作,谢谢配合!\n"); 295 printf("\n\t\t1 四则运算表达式求值\n");296 printf("\n\t\t2 使⽤说明\n");297 printf("\n\t\t0 退出\n");298 printf("/******************************************************************************/\n");299 }300301void Instru()302 {//打印使⽤说明303 FILE *fp;304char ch;305if( ( fp=fopen("使⽤说明.txt","r") ) == NULL)306 {307 printf("⽂件打开失败!\n");308 exit(0);309 }310for(; (ch = fgetc(fp)) != EOF; )311 putchar(ch);312 fclose(fp);313 printf("\n");314 system("pause");315 }。
表达式求值(数据结构)
结束算法,此时在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)优先数。
操作符优先数相等的情况只出现在括号 配对或栈底的“;”号与输入流最后的“;” 号配对时。
表达式求值(数据结构)(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.后缀表达式栈: 用于存储后缀表达式的栈。
数据结构表达式求值
数据结构表达式求值在计算机科学中,数据结构是组织和存储数据的方式,而表达式求值则是一个常见且重要的任务。
表达式求值可以帮助我们计算数学表达式的结果,无论是简单的四则运算,还是复杂的包含函数和变量的表达式。
让我们从一个简单的算术表达式开始,比如“2 +3 4”。
要计算这个表达式的值,我们不能简单地从左到右依次计算,因为乘法的优先级高于加法。
所以,正确的计算顺序应该是先计算 3 4 = 12,然后再计算 2 + 12 = 14。
为了能够正确地处理表达式中不同运算符的优先级,我们需要使用特定的数据结构和算法。
其中,栈(Stack)是一种非常有用的数据结构。
栈就像是一个只能从一端进出的容器,遵循“后进先出”(Last In First Out,LIFO)的原则。
在表达式求值中,我们可以使用两个栈,一个用来存储操作数(Operand Stack),另一个用来存储运算符(Operator Stack)。
当我们读取表达式中的数字时,将其压入操作数栈;当读取到运算符时,需要和运算符栈顶的运算符比较优先级。
如果当前运算符的优先级高于栈顶运算符,那么将其压入运算符栈;如果当前运算符的优先级低于或等于栈顶运算符,就从操作数栈中弹出相应数量的操作数,进行计算,将结果压回操作数栈,然后再将当前运算符压入运算符栈。
例如,对于表达式“2 +3 4”,我们首先读取到数字 2,将其压入操作数栈。
接着读取到“+”号,此时运算符栈为空,所以将“+”号压入运算符栈。
然后读取到数字 3,压入操作数栈。
再读取到“”号,由于“”号的优先级高于“+”号,将“”号压入运算符栈。
接着读取到数字 4,压入操作数栈。
此时,表达式已经读取完毕。
因为“”号的优先级高于“+”号,所以先从操作数栈中弹出 3 和 4 进行乘法运算,得到 12,将 12 压回操作数栈。
然后从运算符栈中弹出“+”号,从操作数栈中弹出 2 和 12 进行加法运算,得到 14,这就是表达式的最终结果。
表达式求值
表达式求值数据结构课程设计报告表达式求值专业计算机科学与技术学生姓名班级学号指导教师完成日期表达式求值目录1 概述 (1)课程设计目的 (1)课程设计内容 (1)2 系统需求分析 (1)系统目标 (1)主体功能 (1)开发环境 (1)3 系统概要设计 (2)系统的功能模块划分 (2)系统流程图 (2)4系统详细设计 (3)5 测试 (3)测试方案 (5)测试结果 (5)6 小结 (7)参考文献 (9)附录1 源程序清单 (10)数据结构课程设计报告(2014)表达式求值1 概述课程设计目的1.要求学生达到熟练掌握C语言的基本知识和技能。
2.了解并掌握数据结构的设计方法,具备初步的独立分析和设计能力。
3.提高程序设计和调试能力。
学生通过上机实习,验证自己设计的算法的正确性。
学会有效利用基本调试方法,迅速找出程序代码中的错误并且修改。
4.培养算法分析能力。
分析所设计算法的时间复杂度和空间复杂度,进一步提高程序设计水平。
5.初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能。
课程设计内容设计一个表达式求值的程序。
该程序必须可以接受包含(,),+,-,*,/,%,和^(求幂运算符,a^b=a b)的中缀表达式,并求出结果。
如果表达式正确,则输出表达式的结果;如果表达式非法,则输出错误信息。
2 系统需求分析系统目标利用栈设计一个程序,该程序能够用于表达式求值,程序将读入的中缀表达式转换为后缀表达式,然后读取后缀表达式,输出结果。
输入要求:程序从“”文件中读取信息,在这个文件中如果有多个中缀表达式,则每个表达式独占一行,程序的读取操作在文件的结尾处停止。
输出要求:对于每一个表达式,将其结果放在“”文件的每一行中。
这些结果可能是值(精确到小数点后两位),也可能是错误信息“ERROR IN INFIX NOTATION”。
主体功能能够处理以字符序列的形式输入的不含变量的实数表达式,正确处理负数与小数,判断表达式是否语法正确(包含分母不能为零的情况),正确实现对算术四则混合运算表达式的求值,能够将计算中遇到的问题和结果以文件的形式予以存储。
数据结构课程设计之算术表达式求值
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【实现效果】完全可以实现题目的要求,除了下图的错误提示,本程序还可以提示的错误有:输入过多运算符,缺少反括号,两个括号之间缺少运算符相连,缺少左括号,输入的运算符超出范围等提示。
表达式求值算法
表达式求值算法表达式求值是一种将数学表达式转换为计算结果的算法。
在计算机程序中,表达式是由操作符和操作数组成的,操作符是执行特定计算操作的符号,操作数是参与计算的数值。
在表达式求值算法中,我们需要处理不同类型的表达式,例如算术表达式、逻辑表达式和位运算表达式等。
算术表达式包含加法、减法、乘法、除法等操作符,逻辑表达式包含与、或、非等操作符,位运算表达式包含位与、位或、位取反等操作符。
实现一个通用的表达式求值算法需要将所有这些操作符纳入考虑,并按照特定的规则进行计算。
在表达式求值算法中,首先需要对表达式进行解析,将其拆分为操作符和操作数。
通过使用逆波兰表达式或分析树等数据结构,我们可以更方便地对表达式进行计算。
逆波兰表达式是一种将操作符放在操作数后面的表达式表示方法。
例如,中缀表达式"3 + 4 * 2"可以转换为逆波兰表达式"3 4 2 * +"。
逆波兰表达式的好处是可以通过一个栈来进行计算。
遍历逆波兰表达式的每个元素,当遇到操作数时,将其压入栈中;当遇到操作符时,从栈中弹出相应数量的操作数进行计算,并将结果压入栈中。
最后,栈中剩下的唯一一个元素就是表达式的结果。
另一种求值算法是使用分析树。
分析树是一种用树结构表示表达式的方法,树的每个节点都是一个操作符,而叶子节点是操作数。
通过遍历分析树,从叶子节点开始计算,并将结果返回给父节点,直到整个树的根节点成为最终结果。
这种方法可以递归地处理任意复杂的表达式。
除了使用逆波兰表达式和分析树,我们还可以使用其他方法来实现表达式求值算法。
例如,我们可以使用栈来存储操作数,并在遍历表达式时进行计算。
当遇到操作符时,从栈中弹出相应数量的操作数进行计算,并将结果压入栈中。
在表达式求值算法中,需要注意处理运算符的优先级和结合性。
不同的运算符可能有不同的优先级,例如乘法和除法的优先级高于加法和减法。
结合性指的是同一级别的运算符如何进行计算,例如加法和减法是左结合的,而赋值运算符是右结合的。
算术表达式求值(C )数据结构实验
数据结构实验报告实验名称:实验2栈和队列及其应用实验目的:通过上机实验,加深理解栈和队列的特性;能根据实际问题的需要灵活运用栈和队列;掌握栈和队列的应用。
实验内容:(2选1)内容1:算术表达式求值问题;内容2:航空客运订票系统。
实验要求:1)在C++系统中编程实现;2)至少实现两种以上操作算法;3)写出算法设计的基本原理或画出流程图;4)算法实现代码简洁明了;关键语句要有注释;5)给出调试和测试结果;6)完成实验报告。
实验步骤:(1)算法设计为了实现算符优先算法。
可以使用两个工作栈。
一个称为OPTR,用以寄存运算符,另一个称做OPND,用以寄存操作数或运算结果。
1.首先置操作数栈为空栈,表达式起始符”#”为运算符栈的栈底元素;2.依次读入表达式,若是操作符即进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应的操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为”#”)。
(2)算法实现typedef struct{int stacksize;char*base;char*top;}Stack;typedef struct{int stacksize;int*base;int*top;}Stack2;int InitStack(Stack*s)//构造运算符栈{s->base=(char*)malloc(STACK_INIT_SIZE*sizeof(char));if(!s->base)return ERROR;s->top=s->base;s->stacksize=STACK_INIT_SIZE;return OK;}int InitStack2(Stack2*s)//构造操作数栈{s->base=(int*)malloc(STACK_INIT_SIZE*sizeof(int));if(!s->base)return ERROR;s->stacksize=STACK_INIT_SIZE;s->top=s->base;return OK;}int In(char ch)//判断字符是否是运算符,运算符即返回1 {return(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#');}int Push(Stack*s,char ch)//运算符栈插入ch为新的栈顶元素{*s->top=ch;s->top++;return0;}int Push2(Stack2*s,int ch)//操作数栈插入ch为新的栈顶元素{*s->top=ch;s->top++;return0;}char Pop(Stack*s)//删除运算符栈s的栈顶元素,用p返回其值{char p;s->top--;p=*s->top;return p;}int Pop2(Stack2*s)//删除操作数栈s的栈顶元素,用p返回其值{int p;s->top--;p=*s->top;return p;}char GetTop(Stack s)//用p返回运算符栈s的栈顶元素{char p=*(s.top-1);return p;}int GetTop2(Stack2s)//用p返回操作数栈s的栈顶元素{int p=*(s.top-1);return p;}char Precede(char c1,char c2){int i=0,j=0;static char array[49]={'>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>','>','<','>','>','>','>','>','>','<','>','>','<','<','<','<','<','=','!','>','>','>','>','!','>','>','<','<','<','<','<','!','='};switch(c1){case'+':i=0;break;case'-':i=1;break;case'*':i=2;break;case'/':i=3;break;case'(':i=4;break;case')':i=5;break;case'#':i=6;break;}switch(c2){case'+':j=0;break;case'-':j=1;break;case'*':j=2;break;case'/':j=3;break;case'(':j=4;break;case')':j=5;break;case'#':j=6;break;}return(array[7*i+j]);}int Operate(int a,char op,int b){switch(op){case'+':return(a+b);case'-':return(a-b);case'*':return(a*b);case'/':return(a/b);}return0;}int num(int n)//返回操作数的长度{char p[10];itoa(n,p,10);//把整型转换成字符串型n=strlen(p);return n;}int EvalExpr(){char c,theta,x;int n,m;int a,b;c=*ptr++;while(c!='#'||GetTop(OPTR)!='#'){if(!In(c)){if(!In(*(ptr-1)))ptr=ptr-1;m=atoi(ptr);//取字符串前面的数字段n=num(m);Push2(&OPND,m);ptr=ptr+n;c=*ptr++;}else{switch(Precede(GetTop(OPTR),c)){case'<':Push(&OPTR,c);c=*ptr++;break;case'=':x=Pop(&OPTR);c=*ptr++;break;case'>':theta=Pop(&OPTR);b=Pop2(&OPND);a=Pop2(&OPND); Push2(&OPND,Operate(a,theta,b));break;}}return GetTop2(OPND);}实验结果:。
数据结构第3章中缀表达式
数据结构第3章中缀表达式数据结构实验报告(第三章)实验类型:综合性实验班级:学号:姓名:实验⽇期:2014年5⽉24⽇⼀、表达式求值1.问题描述表达式是数据运算的基本形式。
⼈们的书写习惯是中缀式,如:11+22*(7-4)/3。
中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进⾏计算。
表达式还有后缀式(如:22 7 4 - * 3 / 11 +)和前缀式(如:+ 11 / * 22 – 7 4 3)。
后缀表达式和前缀表达式中没有括号,给计算带来⽅便。
如后缀式计算时按运算符出现的先后进⾏计算。
本设计的主要任务是进⾏表达式形式的转换及不同形式的表达式计算。
2.基本要求●从⽂件或键盘读⼊中缀表达式。
●设计操作数为多位整数,操作符为加、减、乘、除、求模的中缀表达式求值算法。
●设计将中缀表达式转换为后缀表达式的算法。
●设计将中缀表达式转换为前缀表达式的算法。
●设计后缀表达式求值算法。
●设计前缀表达式求值算法。
●输出各种形式的表达式。
3.数据结构设计任何⼀个表达式都是由操作符,运算符和界限符组成的。
我们分别⽤顺序栈来寄存表达式的操作数和运算符。
栈是限定于紧仅在表尾进⾏插⼊或删除操作的线性表。
顺序栈的存储结构是利⽤⼀组连续的存储单元依次存放⾃栈底到栈顶的数据元素,同时附设指针top指⽰栈顶元素在顺序栈中的位置,base为栈底指针,在顺序栈中,它始终指向栈底,即top=base可作为栈空的标记,每当插⼊新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。
typedef struct{int *base;int *top;int numstacksize; //数字栈}numstack;typedef struct{char *base;char *top;int charstacksize;//字符栈}charstack;4.算法设计(1)中缀表达式求值1.从左到右读⼊中缀表达式,每次⼀个字符。
数据结构实验3后缀表达式求值
int top;
}opstack;
typedef struct
{ float data[Maxle n];
int top;
}stack;
void tran s(char str[],char exp[]) //求后缀表达式
{ opstack op;
char ch;
default:
while(ch>='0' && ch<='9')
{ exp[t]=ch;
t++;
ch=str[i#39;';
t++;
ch=str[i];
i++;
}
while(op.top!=-1)
{ exp[t]=op.data[op.top];
t++;
op.top--;
break;
case'*':
case'/':
while(op.top=='/'||op.top=='*')
{ exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top++;
op.data[op.top]=ch;
break;
case' '://输入为空格,则跳过
break;
-2 -
op.top=-1;
ch=str[i];
i++;
while(ch!='\O')
表达式求值 实验报告
表达式求值实验报告表达式求值实验报告一、引言表达式求值是计算机科学中一个重要的概念,它涉及到对数学表达式的计算和求解。
在本次实验中,我们将探讨表达式求值的相关算法和实现方法,并通过编程实现一个简单的表达式求值器。
二、算法原理1. 表达式的表示方法在计算机中,我们通常使用字符串来表示表达式。
例如,一个简单的数学表达式"2 + 3 * 4"可以表示为字符串"2+3*4"。
在实现表达式求值的算法时,我们需要将字符串中的数字和运算符进行分离,以便进行后续的计算。
2. 中缀表达式转后缀表达式为了方便计算,我们通常将中缀表达式转换为后缀表达式。
后缀表达式也称为逆波兰表达式,它的特点是运算符位于操作数的后面。
例如,上述的中缀表达式"2+3*4"可以转换为后缀表达式"234*+"。
转换的方法可以通过使用栈来实现。
3. 后缀表达式求值得到后缀表达式后,我们可以通过扫描表达式并使用栈来求解。
当遇到操作数时,将其压入栈中;当遇到运算符时,从栈中弹出相应数量的操作数进行计算,并将结果压入栈中。
最终,栈中的唯一元素即为表达式的求值结果。
三、实验过程1. 数据结构设计为了实现表达式求值器,我们需要设计相应的数据结构。
在本次实验中,我们选择使用栈来存储操作数和运算符。
2. 中缀表达式转后缀表达式首先,我们需要编写一个函数来将中缀表达式转换为后缀表达式。
该函数的实现可以通过使用栈和遍历字符串来实现。
具体的步骤如下:- 创建一个空栈和一个空字符串用于存储后缀表达式。
- 从左到右遍历中缀表达式的每个字符。
- 如果遇到操作数,直接将其添加到后缀表达式字符串中。
- 如果遇到运算符,将其与栈顶的运算符进行比较:- 如果栈为空或栈顶为左括号"(",则直接将运算符入栈。
- 如果栈顶的运算符优先级低于当前运算符,则将当前运算符入栈。
- 如果栈顶的运算符优先级高于或等于当前运算符,则将栈顶的运算符弹出并添加到后缀表达式字符串中,直到栈顶的运算符优先级低于当前运算符或栈为空。
数据结构(C语言版)课程设计报告表达式求值说明书
数据结构(C语言版)课程设计报告表达式求值说明书XX大学数据结构课程设计说明书题目:表达式求值院系:计算机科学与工程学院专业班级:计算机班学号:学生姓名:指导教师:2021年X月X日XX大学课程设计(论文)任务书计算机科学与工程学院学号学生姓名专业(班级)设计题目表达式求值设计技术参数系统平台:Windows7/WindowsXP开发工具:VC++6.0设计要求(1)能够计算的运算符包括:加、减、乘、除、圆括号。
(2)能够计算的数要求在实数范围内。
(3)能执行多重括号嵌套运算。
(4)对于异常表达式给出错误提示。
工作量课程设计报告要求不少于3000字。
源程序要求不少于300行工作计划2021.11.21-12.01根据课程设计大纲的要求,查找相关资料,完成需求分析;2021.12.02-12.16进行系统的概要设计;2021.12.17-12.31进行系统的详细设计和源代码的书写;2021.01.01-01.17对系统进行调试分析,写出课程设计报告。
参考资料[1]何钦铭主编.C语言程序设计.北京:高等教育出版社,2021.[2]谭浩强编著.C程序设计(第四版).北京:清华大学出版社,2021.[3]严蔚敏,吴伟民编著.数据结构(C语言版)北京:清华大学出版社,2021.[4]严蔚敏,吴伟民编著.数据结构题集北京:清华大学出版社,2021.指导教师签字教研室主任签字2021年X月X日学生姓名:学号:专业班级:课程设计题目:表达式求值指导教师评语:成绩:指导教师:年月日XX大学课程设计(论文)成绩评定表目录1需求分析12概要设计12.1设计思路12.2存储结构设计12.3功能模块设计13详细设计14运行与测试15总结1参考文献2(要求:给出一级目录和二级目录,宋体,四号字,1.5倍行距,页码使用罗马数字,居中)(报告正文部分):(要求:正文部分一律用小四号字,宋体,行距20磅。
一级标题靠左,加粗。
二级大标题靠左,不加粗。
表达式求值(数据结构)
表达式求值(数据结构)表达式求值(数据结构)一、引言表达式求值是计算机科学中一个重要的概念,它是计算机程序中常见的操作之一。
通过对表达式中的运算符和操作数进行计算,可以得到表达式的结果。
本文将介绍表达式求值的相关知识和算法,并提供一个基于数据结构的表达式求值的范本。
二、基本概念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 = \。
数据结构实验报告五—四则运算表达式求值
问题描述:四则运算表达式求值,将四则运算表达式用中缀表达式,然后转换为后缀表达式,并计算结果。
一、需求分析:1、本程序是利用二叉树后序遍历来实现表达式的转换,同时可以使用实验三的结果来求解后缀表达式的值。
2、输入输出格式:输入格式:在字符界面上输入一个中缀表达式,回车表示结束。
请输入表达式:输入一个中缀表达式输出格式:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。
逆波兰表达式为:输出逆波兰表达式运算结果为:输出运算后的结果3、测试用例输入:21+23*(12-6)输出:21 23 12 6 -*+二、概要设计:抽象数据类型二叉树类BiTree算法的基本思想根据题目要求,利用栈计算,和二叉树存储,来计算表达式该算法的基本思想是:先利用栈进行计算,然后用二叉树进行存储,和实验三算法一样来计算逆波兰表达式的值程序的流程程序由三个模块组成:(1)输入模块:输入一个运算式(2)计算模块:利用栈进行表达式的计算,二叉树来存储。
(3 )输出模块:屏幕上显示出后缀表达式和运算结果。
三、详细设计物理数据类型程序含有两个类,其中栈不再赘述,另一个类为二叉树class BiTree 包含私有成员struct BiTreeNode,根节点BiTreeNode *T;索引index; int number_of_point 优先级比较函数 compare(char a,char b);生成树的函数void InorderCreate(BiTreeNode *&T,char str[30][10],int start,int end);判断数字函数bool IsNumber(char a);求值函数double Operate(BiTreeNode *T);还有显示后缀表达式的函数void display(BiTreeNode *T) ;而公有成员函数则是对私有函数的重载,为方便使用,因为函数中普遍使用了递归的算法。
施磊磊的数据结构课程设计及报告2 表达式求值问题
课程设计题目名称表达式求值问题课程名称数据结构课程设计学生姓名施磊磊学号0813022057班级计082指导教师管致锦数据结构课程设计及报告表达式求值一、问题描述实验题目为表达式求值。
要求接受用户输入一个中缀表达式(运算符为加、减、乘、除),然后通过借助于顺序栈实现将其转换为后缀表达式并将其打印,最后求出其值。
设计主函数,使用户可以重复输入中缀表达式,求得表达式的后缀表达式和表达式的值。
二、数据结构算法设计(一)堆栈ADTADT Stack{数据:0个或多个元素的线性序列(a0,a1,...,an-1),其最大允许长度为MaxStackSize。
运算:Create(): 建立一个空栈。
Destroy(): 撤销一个栈。
IsEmpty(): 若空栈,则返回true;否则返回false。
IsFull(): 若栈满,则返回true;否则返回false。
Top(): 在x中返回栈顶元素。
若操作成功,则返回true;否则返回false。
Push(): 在栈顶插入元素x(入栈)。
若操作成功,则返回true;否则返回false。
Pop(): 从栈中删除栈顶元素(出栈)。
若操作成功,则返回true;否则返回false。
Clear(): 清除堆栈中全部元素。
}(二)顺序栈类在此题目中,借助了c++的模板抽象类来定义栈抽象数据类型,程序如下:顺序堆栈类:includetemplateclass Stack{private:T * stack; //指向数组的指针int top; //栈顶指针int maxTop; //最大栈顶指针public:Stack(); //构建一个构造函数;初始化栈void Push(T item); //进栈T Pop(); //出栈,删除栈顶元素T Peek(); //返回栈顶元素bool EmptyStack(); //判断是否为空栈~Stack() {delete []stack;}; //释放并清空栈的存储空间void Clear(){top=-1;} //清除栈中全部元素三、算法原理(一)头文件名在本程序中,运用的头文件有一些是在平时经常用到的,也有一些是少见甚至是很陌生的。
表达式求值实验报告
表达式求值实验报告西南大学数据结构实验报告学院:专业:班级:姓名:学号:实验报告一、实验题目:表达式表达式二、实验目的和建议:目的:(1)通过该算法的设计思想,熟识栈的特点和应用领域方法;(2)通过对波函数优先法对算术表达式表达式的算法继续执行过程的模拟,认知在继续执行适当栈的操作方式时的变化过程。
(3)通过程序设计,进一步熟识栈的基本运算函数;(4)通过自己动手同时实现算法,强化从伪码算法至c语言程序的同时实现能力。
建议:(1)采用栈的顺序存储则表示方式;(2)采用波函数优先法;(3)用c语言同时实现;(4)从键盘输入一个符合要求的算术表达式,输入恰当的结果。
三、实验过程:#include#include#include#include#include#include#include#include#include#inclu de#include//函数结果状态代码#definetrue1#definefalse0#defineok1#defineerror0#defineinfeasible-1typedefintstatus;//status就是函数的类型,其值就是函数结果状态代码,如ok等typedefintelemtype;constintstack_init_size=100;constintstackincrement=10;typed efstruct{elemtype*base;elemtype*top;intstacksize;}stack;statusinitstack(stack&s){//构造一个空栈ss.base=(elemtype*)malloc(stack_init_size*sizeof(elemtype));if(!s.base)exit(er ror);s.top=s.base;s.stacksize=stack_init_size;returnok;}statuspush(stack&s,ele mtypee){//插入元素e为新的栈顶元素if(s.top-s.base>=s.stacksize){s.base=(elemtype*)realloc(s.base,(s.stacksize+stackincrem ent)*sizeof(elemtype));if(!s.base)exit(overflow);s.top=s.base+s.stacksize;s.st acksize+=stackincrement;}*s.top++=e;returnok;}statuspop(stack&s,elemtype&e){//若栈不空,则删除,用e返回其值,并返回ok;否则返回errorif(s.top==s.base)returnerror;e=*--s.top;returnok;}statusgettop(stack&s){//若栈不空,用e返回s的栈顶元素,并返回ok;否则返回errorif(s.top==s.base)returnerror;return*(s.top-1);}operate.h:#include\statusin(charc){//辨别c与否为运算符if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#')returnok;elsereturnerror;}statusoper ate(inta,charc,intb){//二元运算switch(c){case'+':returna+b;break;case'-':returna-b;break;case'*':returna*b;break;case'/':if(b==0){printf(\(提示信息:存有除数为零错误)\\n\);returnerror;}//除数无法为零elsereturna/b;break;}}charprecede(chara,charb){//波函数间优先关系switch(a){case'+':switch(b){case'+':return'>';break;case'-':return'>';break;case'*':return'';break;case'#':return'>';break;}break;case'-':switch(b){case'+':return'>';break;case'-':return'>';break;case'*':return'';break;case'#':return'>';break;}break;case'*':switch(b){case'+':return'>';break;case'-':return'>';break;case'*':return'>';break;case'/':return'>';break;case'(':return'';break;case'#':return'>';break;}break;case'/':switch(b){case'+':return'>'; break;case'-':return'>';break;case'*':return'>';break;case'/':return'>';break;case'(':return'';break;case'#':return'>';break;}break;case'(':switch(b){case'+':return'';b reak;case'-':return'>';break;case'*':return'>';break;case'/':return'>';break;case')':return'>';break;case'#':return'>';break;}break;case'#':switch(b)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中缀算术表达式求值
使用两个栈,操作符栈OPTR (operator), 使用两个栈,操作符栈OPTR (operator), 操作数栈OPND(operand), 操作数栈OPND(operand), 对中缀表达式求值的一般规则: 对中缀表达式求值的一般规则: (1) 建立并初始化OPTR栈和OPND栈, 建立并初始化OPTR栈和 栈和OPND栈 然后在OPTR栈中压入一个 栈中压入一个“ 然后在OPTR栈中压入一个“#” (2) 从头扫描中缀表达式,取一字符送入 从头扫描中缀表达式, ch (3) 当ch != “#” 时, 执行以下工作, 否则 执行以下工作, 结束算法, 此时在OPND 栈 结束算法 , 此时在 OPND栈 的栈顶得 到运算结果。 到运算结果。
表达式求值
一个表达式由操作数 亦称运算对象) 一个表达式由操作数(亦称运算对象)、操 操作数( 亦称运算符) 分界符(亦称界限符) 作符 (亦称运算符) 和分界符(亦称界限符) 组成。 组成。 算术表达式有三种表示: 算术表达式有三种表示: 中缀(infix)表示 中缀 表示
<操作数> <操作符> <操作数>,如 A+B; 操作数> 操作符> 操作数> ;
① 若ch是操作数,进OPND栈,从中缀表达式 ch是操作数, OPND栈 取下一字符送入ch; 取下一字符送入ch; ch是操作符,比较栈外icp(ch)的优先级和 ② 若ch是操作符,比较栈外icp(ch)的优先级和 栈内isp(OPTR)的优先级 的优先级: 栈内isp(OPTR)的优先级: isp(OPTR), ch进OPTR栈 若icp(ch) > isp(OPTR),则ch进OPTR栈, 从中缀表达式取下一字符送入ch; 从中缀表达式取下一字符送入ch; isp(OPTR),则从OPND栈 若icp(ch) < isp(OPTR),则从OPND栈退出 a2 和 a1 , 从 OPTR 栈 退 出 θ, 形 成 运 算 指 令 (a1)θ(a2),结果进OPND栈; (a1)θ(a2 结果进OPND栈 “)”, 若icp(ch) == isp(OPTR) 且ch == “)”,则从 OPTR栈 退出栈顶的“ (” , 对消括号, OPTR 栈 退出栈顶的 “ (”, 对消括号 , 然后从 中缀表达式取下一字符送入ch; 中缀表达式取下一字符送入ch;
优先级 操作符 1 单目单目-、! 2 *、/、% 3 +、4 <、<=、>、>= <=、 5 ==、 ==、!= 6 && 7 ||
一般表达式的操作符有4种类型: 一般表达式的操作符有4种类型: 1 算术操作符 如双目操作符(+、-、 如双目操作符( *、/ 和%)以及单目操作符(-); 以及单目操作符( 2 关系操作符 包括<、<=、==、!=、 包括< <=、==、!=、 >=、 >=、>。这些操作符主要用于比较; 这些操作符主要用于比较; 3 逻辑操作符 如与(&&)、或(||)、非 如与(&&)、 (||)、 (!); 4 括号‘(’和‘)’ 它们的作用是改变 括号‘(’和 运算顺序; 运算顺序;
应用后缀表示计算表达式的值
从左向右顺序地扫描表达式, 从左向右顺序地扫描表达式 , 并用一个 暂存扫描到的操作数 计算结果; 操作数或 栈暂存扫描到的操作数或计算结果; 在后缀表达式的计算顺序中已隐含了加 在后缀表达式的计算顺序中已 隐含了加 括号的优先次序, 括号的优先次序 , 括号在后缀表达式中 不出现; 不出现; 计算例 a b c d - * + e f ^ g / rst1 rst2 rst3 rst6 rst4 rst5
栈内容 空 A AB ABC ABCD ABr1 Ar2 r3
步 输入 类 型 动 作 9 E 操作数 进栈 10 F 操作数 进栈 11 ^ 操作符 F、 E 退栈 计算 、 退栈, E^F, 结果 r4 进栈 12 G 操作数 进栈 13 / 操作符 G、 r4 退栈 计算 、 退栈, r4/E, 结果 r5 进栈 14 + 操作符 r5、 r3 退栈 计算 、 退栈, r3+r5, 结果 r6 进栈
中缀表达式转换为后缀表达式的算法
操作符栈初始化,将结束符‘ 进栈。 操作符栈初始化,将结束符‘;’进栈。然 后读入中缀表达式字符流的首字符ch; 后读入中缀表达式字符流的首字符ch; 重复执行以下步骤,直到ch 重复执行以下步骤,直到ch = ‘;’,同时 栈顶的操作符也是‘ 停止循环; 栈顶的操作符也是‘;’,停止循环; ch是 操作数直接输出 直接输出, 若 ch 是 操作数 直接输出 , 读入下一个 字符ch。 字符ch。 ch是操作符,判断ch 的优先级 和 的优先级icp 若 ch是 操作符 , 判断 ch的优先级 icp和 位于栈顶的操作符op的优先级 : 的优先级isp 位于栈顶的操作符op的优先级isp:
若 icp (ch) > isp (op),令ch进栈,读入 (op), ch进栈 进栈, 下一个字符ch; 下一个字符ch; (op),退栈并输出; 若 icp (ch) < isp (op),退栈并输出; (op),退栈但不输出, 若 icp (ch) == isp (op),退栈但不输出, 若退出的是“ (”号读入下一个字符 ; 号读入下一个字符ch 若退出的是 “ (” 号读入下一个字符 ch; 算法结束, 算法结束,输出序列即为所需的后缀表 达式。 达式。
栈内容 r3E r3EF r3r4 r3r4G r3r5 r6
利表示转换成它 的前缀表示和后缀表示。 的前缀表示和后缀表示。 为了实现这种转换, 为了实现这种转换 , 需要考虑各操作符 的优先级。 的优先级。
各个算术操作符的优先级
操作符 ch ; 栈内) isp (栈内 0 栈内 栈外) icp (栈外 0 栈外 ( 1 8 ^ *, /, % +, 7 5 3 6 4 2 ) 8 1
通过后缀表示计算表达式值的过程
顺序扫描表达式的每一项, 顺序扫描表达式的每一项,根据它的类 型做如下相应操作: 型做如下相应操作: 若该项是操作数 则将其压栈 操作数, 压栈; 若该项是操作数,则将其压栈; 若该项是操作符 操作符<op>,则连续从栈中 若该项是操作符 , 退出两个操作数Y和 , 退出两个操作数 和X,形成运算指令 X<op>Y,并将计算结果重新压栈。 压栈。 ,并将计算结果重新压栈 当表达式的所有项都扫描并处理完后, 当表达式的所有项都扫描并处理完后, 栈顶存放的就是最后的计算结果。 栈顶存放的就是最后的计算结果。
步 输入 类 型 动 作 1 置空栈 2 A 操作数 进栈 3 B 操作数 进栈 4 C 操作数 进栈 5 D 操作数 进栈 6 - 操作符 D、 C 退栈 计算 、 退栈, C- D, 结果 r1 进栈 7 * 操作符 r1、 B 退栈, 计算 、 退栈 B*r1, 结果 r2 进栈 8 + 操作符 r2、 A 退栈 计算 、 退栈, A*r2, 结果 r3 进栈
isp叫做栈内(in stack priority)优先数。 isp叫做栈内 叫做栈内(in priority)优先数 优先数。 icp叫做栈外(in coming priority)优先数。 icp叫做栈外 叫做栈外(in priority)优先数 优先数。 操作符优先数相等的情况只出现在括号 操作符优先数相等的情况只出现在 括号 配对或栈底的“ 号与输入流最后的“ 配对或栈底的“;”号与输入流最后的“;” 号配对时 号配对时。
a+b*(c-d)-e^f/g
rst1 rst2 rst3 rst6 rst4 rst5
表达式中相邻两个操作符的计算次序为: 表达式中相邻两个操作符的计算次序为 : 优先级高的先计算; 优先级高的先计算; 优先级相同的自左向右计算; 优先级相同的自左向右计算; 当使用括号时从最内层括号开始计算 。
C/C++中操作符的优先级 C/C++中操作符的优先级
前缀(prefix)表示 表示 前缀
<操作符 <操作数 <操作数 ,如 +AB; 操作符> 操作数 操作数 操作符 操作数> 操作数>, ;
后缀(postfix)表示 表示 后缀
<操作数 <操作数 <操作符 ,如 AB+; 操作数> 操作数 操作符 操作数 操作数> 操作符>, ;
表达式的中缀表示