数据结构表达式的两种计算方法_第1页
数据结构表达式的两种计算方法_第2页
数据结构表达式的两种计算方法_第3页
数据结构表达式的两种计算方法_第4页
数据结构表达式的两种计算方法_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.一、 设计思想(一) 先将输入的中缀表达式转为后缀再计算的设计思想我们所熟知的计算表达式为中缀表达式,这之中包含运算符的优先级还有括号,这对我们来说已经习以为常了,但是在计算机看来,这是非常复杂的一种表达式。因此我们需要有一种更能使计算机理解的不用考虑优先级也不包括括号的表达式,也就是后缀表达式。我们可以借助栈将其实现。首先,我们需要将中缀表达式转换为后缀表达式,这也是这个算法的关键之处。我们将创建两个栈,一个是字符型的,用来存放操作符;另一个是浮点型的,存放操作数。接着,开始扫描输入的表达式,如果是操作数直接进入一个存放后缀表达式的数组,而操作符则按照优先级push进栈(加减为1,乘除为2

2、),若当前操作符优先级大于栈顶操作符优先级或栈为空,push进栈,而当其优先级小于等于栈顶操作符优先级,则从栈内不断pop出操作符并进入后缀表达式数组,直到满足条件,当前操作符才能push进栈。左括号无条件入栈,右括号不入栈,而不断从栈顶pop出操作符进入后缀表达式数组,直到遇到左括号后,将其pop出栈。这样当扫描完输入表达式并从操作符栈pop出残余操作符后并push进栈,后缀表达式数组中存放的就是我们所需要的后缀表达式了。扫描后缀表达式数组,若是操作数,将其转换为浮点型push进数栈;若是操作符,则连续从数栈中pop出两个数做相应运算,将结果push进数栈。当扫描完数组后,数栈顶便为最终结果

3、,将其pop出,输出结果。(二) 一边扫描一边计算的设计思想由于第一种算法需要进行两遍扫描,因此在性能上不会十分优秀。而此种算法只用扫描一遍,当扫描完输入的表达式后便可以直接输出最终结果。是第一种算法的改进版,性能上也得到提升,与第一种算法所不同的是其需要同时使用两个栈,一个操作符栈,一个数栈。当扫描表达式时,若是操作数则将其转换为浮点型后直接push进数栈,而若是操作符则按照优先级规则push进操作符栈(加减为1,乘除为2),若当前操作符优先级大于栈顶操作符优先级或栈为空,push进栈,而当其优先级小于等于栈顶操作符优先级,则从栈内不断pop出操作符,直到满足条件,当前操作符才能push进栈

4、。左括号无条件入栈,右括号不入栈,而不断从栈顶pop出操作符,直到遇到左括号后,将其pop出栈。这中间pop出操作符后直接从数栈中pop出两个数并计算,将结果push进数栈。括号的处理与第一个算法相同。扫描完成后,从操作符栈pop出残余操作符,从数栈中pop出两个数并计算并进行计算,将结果push进数栈。数栈顶便为最终结果,将其pop出,输出结果。两种算法各有各的优缺点,第一种算法过程比较清晰,使我们能够更加容易理解栈的使用规则,但是其性能不如第二种。第二种算法相比第一种来说性能提高了,但是理解起来就不如第一种那么清晰了。二、算法流程图以下是先将输入的中缀表达式转为后缀再计算算法:图1 中缀转

5、后缀算法流程图以下是一边扫描一边计算算法:图2一边扫描一边计算算法流程图三、源代码以下为先将输入的中缀表达式转为后缀再计算算法代码:#include stdio.h#include stdlib.h/*定义存放操作符的结构体*/struct OpStrack char op100;/*存放操作符的数组*/ int top;/*栈顶索引*/ int level100;/*存放操作符优先级的数组*/OpStrackArray;/*定义存放语素的结构体*/struct OdStrack float od100;/*存放操作数的数组*/ int top;/*栈顶索引*/OdStrackArray;/*

6、声明需要用到的函数*/int judge(char,char,int,int);int stackIsEmpty();void pushOp(char,int);char popOp();void pushOd(float);float popOd();void compute(char);/*主函数*/void main() char data100;/*声明存放中缀表达式的字符串*/ char tempdata200;/*声明存放后缀表达式的字符串*/ int i=0;/*作为遍历字符串的索引*/ int j=0;/*作为输出后缀表达式的索引*/ int z=0;/*作为存放后缀表达式的索

7、引*/ int k=0;/*作为将后缀表达式赋给临时转float的索引*/ int eq=0;/*判断括号是否正确的条件*/ float result;/*声明存放最终结果的float*/ scanf(%s,data);/*输入中缀表达式*/ /*中缀转后缀,并将结果放入tempdata*/ while(datai!=0) if(datai=0&datai=9)|datai=.)/*如果是语素则存放至temp数组*/ tempdataz=datai; z+; else switch(datai) case +: z+=judge(datai,tempdata,i,1); break; case

8、 -: z+=judge(datai,tempdata,i,1);/*加减优先级为1*/ break; case *: z+=judge(datai,tempdata,i,2);/*乘除优先级为2*/ break; case /: /*返回出栈操作符的数量,以便将z索引向后推相应步*/ z+=judge(datai,tempdata,i,2); break; case (: pushOp(datai,-1);/*(直接入栈,但入栈后优先级最小*/ eq+;/*有一个(eq+1*/ break; case ): while(OpStrackArray.opOpStrackArray.top-1!

9、=()/*)不入栈*/ /*不断弹出操作符并进入后缀表达式数组,直到遇到(*/ tempdataz=popOp(); z+;/*索引+1*/*如果发现还没碰到与之匹配的(时栈已空则说明表达式不合法*/ if(stackIsEmpty()=1) printf(Expression is not valid!Press any key to continue.); getch(); return; popOp();/*弹出(*/ eq-;/*如有与(配队的)则eq-1*/ break; i+; if(eq!=0)/*如果eq!=0说明(与)不能完全配队,输入的表达式不合法*/ printf(Exp

10、ression is not valid!Press any key to continue.); getch(); return; /*将操作符栈内存留的操作符放入tempdata*/ while(stackIsEmpty()=0)/*如果操作符栈不空则不断弹出操作符并进入后缀表达式数组*/ tempdataz=popOp(); z+; /*扫描后缀表达式,计算后放入操作数栈*/ while(k=0&tempdatak=9)|tempdatak=.) tempt=tempdatak; k+; t+; if(temp0!=0)/*判断temp数组是否为空,是则将其转换为float并压栈*/ f

11、=atof(temp);/*字符串转float*/ pushOd(f);/*操作数入栈*/ if(tempdatak=+|tempdatak=-|tempdatak=*|tempdatak=/) compute(tempdatak);/*如果扫描到操作符则作相应计算*/ k+; /*输出后缀表达式*/ printf(The postfix expression is:); for(j=0;jz;j+) printf(%c,tempdataj); printf(n); /*从操作数栈内弹出最终结果并输出*/ result=popOd(); printf(The result is:%.2f,re

12、sult);/*结果取两位小数*/ printf(n); printf(Press any key to continue.); getch();/*判断操作符优先级并作出相应处理,返回出栈操作符数量*/int judge(char op,char tempdata,int index,int level) int cont=0; if(stackIsEmpty()=1|OpStrackArray.levelOpStrackArray.top-1=level) /*操作符不断出栈并入后缀表达式数组直到栈为空或栈顶操作符优先级大于等于当前操作符优先级*/ tempdataindex=popOp(

13、); index+;/*后缀表达式数组索引+1*/ cont+;/*出栈操作符数量+1*/ pushOp(op,level);/*将当前操作符压栈*/ return cont;/*判断操作符栈是否为空,是则返回1,否返回0*/int stackIsEmpty() if(OpStrackArray.op0=0) return 1; return 0;/*将操作符压入栈*/void pushOp(char op,int level) OpStrackArray.opOpStrackArray.top=op;/*操作符进入数组*/ OpStrackArray.levelOpStrackArray.t

14、op=level;/*为对应操作符附优先级*/ OpStrackArray.top+;/*top索引+1*/*操作符出栈,返回栈顶操作符*/char popOp() char c=OpStrackArray.opOpStrackArray.top-1;/*取得栈顶操作符*/OpStrackArray.opOpStrackArray.top-1=0;/*分别将op数组与level数组还原为默认值*/ OpStrackArray.levelOpStrackArray.top-1=0; OpStrackArray.top-;/*top索引-1*/ return c;/*返回栈顶操作符*/*将操作数压

15、入栈*/void pushOd(float f) OdStrackArray.odOdStrackArray.top=f;/*操作数进入数组*/ OdStrackArray.top+;/*top索引+1*/*操作符出栈,返回栈顶操作数*/float popOd() float f=OdStrackArray.odOdStrackArray.top-1;/*取得栈顶操作数*/ OdStrackArray.odOdStrackArray.top-1=0.0;/*将od数组还原为默认值*/ OdStrackArray.top-;/*top索引-1*/ return f;/*返回栈顶操作数*/*根据传

16、入操作符运算,并将结果压入操作数栈*/void compute(char op) float tempresult;/*临时计算结果*/ float od1=popOd(); float od2=popOd();/*连续pop出两个操作数*/ switch(op)/*根据传入操作符计算*/ case +: tempresult=od2+od1; break; case -: tempresult=od2-od1; break; case *: tempresult=od2*od1; break; case /: tempresult=od2/od1; break; pushOd(tempres

17、ult);/*将计算结果压栈*/以下为一边扫描一边计算算法代码:#include stdio.h#include stdlib.h/*定义存放操作符的结构体*/struct OpStrack char op100;/*存放操作符的数组*/ int top;/*栈顶索引*/ int level100;/*存放操作符优先级的数组*/OpStrackArray;/*定义存放语素的结构体*/struct OdStrack float od100;/*存放操作数的数组*/ int top;/*栈顶索引*/OdStrackArray;/*声明需要用到的函数*/void pushOp(char,int);c

18、har popOp();void pushOd(float);float popOd();int stackIsEmpty();void judge(char,int);void compute(char);/*主函数*/void main() char data100;/*声明存放中缀表达式的字符串*/ int i=0;/*作为遍历字符串的索引*/ int eq=0;/*判断括号是否正确的条件*/ float result;/*声明存放最终结果的float*/ scanf(%s,data);/*输入中缀表达式*/ /*扫描输入的表达式并作出相应处理*/ while(datai!=0) cha

19、r temp20=0;/*声明临时的存放操作数的数组并附初值*/ int j=0;/*作为temp数组的索引*/ float f;/*存放转换为float的数*/ while(datai=0&datai=9)|datai=.)/*如果是语素则存放至temp数组*/ tempj=datai; j+; i+; if(temp0!=0)/*判断temp数组是否为空,是则将其转换为float并压栈*/ f=atof(temp);/*字符串转float*/ pushOd(f);/*操作数入栈*/ switch(datai) case +: judge(datai,1); break; case -: j

20、udge(datai,1);/*加减优先级为1*/ break; case *: judge(datai,2); break; case /: judge(datai,2);/*乘除优先级为2*/ break; case (: pushOp(datai,-1);/*(直接入栈,但入栈后优先级最小*/ eq+;/*有一个(eq+1*/ break; case ): while(OpStrackArray.opOpStrackArray.top-1!=()/*)不入栈*/ compute(popOp();/*不断弹出操作符并计算,直到遇到(*/*如果发现还没碰到与之匹配的(时栈已空则说明表达式不合

21、法*/ if(stackIsEmpty()=1)/ printf(Expression is not valid!Press any key to continue.); getch(); return; popOp();/*弹出(*/ eq-;/*如有与(配队的)则eq-1*/ break; i+; /*扫描操作符栈内残余操作符并做相应计算*/ while(stackIsEmpty()=0) compute(popOp();/*如果操作符栈不空则弹出操作符并计算*/ /*从操作数栈内弹出最终结果并输出*/ if(eq=0)/*如果eq=0说明(与)可以完全配队,输入的表达式合法*/ resu

22、lt=popOd(); printf(The result is:%.2f,result);/*结果取两位小数*/ else/*如果eq!=0说明(与)不能完全配队,输入的表达式不合法*/ printf(Expression is not valid!Press any key to continue.); printf(n); printf(Press any key to continue.); getch();/*将操作符压入栈*/void pushOp(char op,int level) OpStrackArray.opOpStrackArray.top=op;/*操作符进入数组*/

23、 OpStrackArray.levelOpStrackArray.top=level;/*为对应操作符附优先级*/ OpStrackArray.top+;/*top索引+1*/*操作符出栈,返回栈顶操作符*/char popOp() char c=OpStrackArray.opOpStrackArray.top-1;/*取得栈顶操作符*/ OpStrackArray.opOpStrackArray.top-1=0; OpStrackArray.levelOpStrackArray.top-1=0;/*分别将op数组与level数组还原为默认值*/ OpStrackArray.top-;/*

24、top索引-1*/ return c;/*返回栈顶操作符*/*将操作数压入栈*/void pushOd(float f) OdStrackArray.odOdStrackArray.top=f;/*操作数进入数组*/ OdStrackArray.top+;/*top索引+1*/*操作符出栈,返回栈顶操作数*/float popOd() float f=OdStrackArray.odOdStrackArray.top-1;/*取得栈顶操作数*/ OdStrackArray.odOdStrackArray.top-1=0.0;/*将od数组还原为默认值*/ OdStrackArray.top-;

25、/*top索引-1*/ return f;/*返回栈顶操作数*/*判断操作符栈是否为空,是则返回1,否返回0*/int stackIsEmpty() if(OpStrackArray.op0=0) return 1; return 0;/*判断操作符优先级作出相应处理*/void judge(char op,int level) if(stackIsEmpty()=1|OpStrackArray.levelOpStrackArray.top-1=level) /*操作符不断出栈并计算直到栈为空或栈顶操作符优先级大于等于当前操作符优先级*/ compute(popOp(); pushOp(op,

26、level);/*将当前操作符压栈*/ /*根据传入操作符运算,并将结果压入操作数栈*/void compute(char op) float tempresult;/*临时计算结果*/ float od1=popOd(); float od2=popOd();/*连续pop出两个操作数*/ switch(op)/*根据传入操作符计算*/ case +: tempresult=od2+od1; break; case -: tempresult=od2-od1; break; case *: tempresult=od2*od1; break; case /: tempresult=od2/o

27、d1; break; pushOd(tempresult);/*将计算结果压栈*/四、运行结果图3中缀转后缀算法运算结果图4 一边扫描一边计算算法运算结果五、遇到的问题及解决这部分我主要遇到了如下几个问题,其内容与解决方法如下所列:中缀转后缀算法:l 问题1:扫描完成后输出的后缀表达式会带有(,从而导致计算不正确。解决方法:在遇到)后,程序会调用pop方法不断从操作符栈内弹出操作符存入后缀表达式数组,直到遇到(。就是在这里,在遇到(后应该直接弹出(而不应该将其存入后缀表达式数组,改正后后缀表达式中自然就不再存在(。l 问题2:虽然解决了第一个问题,但是有时后缀表达式仍然输出不正确,不是掉个操作符就是少个数字。解决方法:经过深入研究,我最终发现凡是当遇到)需要连续从操作符栈pop出操作符时就会出现这个问题。原来输入表达式字符串和存储后缀表达式字符串的索引相同,因为我想数字与数字之间有操作符自然分割,但是在这种情况下,输入表达式字符串索引的确是向后推1,而存储后缀表达式字符串的索引就不止

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论