首页 > 编程知识 正文

数据结构表达式求值讲解,数据结构算术表达式求值

时间:2023-05-04 23:51:10 阅读:22257 作者:2840

首先,前缀表达式前面有符号,如- 3456

骑马订式(符号在中间,如(3)4)5-6所示

后缀表达式:符号位于最后,后缀表达式中不显示括号,如34 56-。

骑马订式到后缀式的转换方法:

1 .遇到数字:的直接输出(添加到后缀表达式) ) ) ) ) ) ) ) )。

2 .堆栈为空时,遇到运算符,直接进入堆栈

3 .遇到左括号:放入堆栈

4 .遇到右括号:执行堆栈操作,输出堆栈的所有元素,输出直到弹出堆栈的是左括号

到号码为止,不输出左括号直接删除

5 .遇到其他运算符:加减乘除:如果当前运算符低于堆栈中运算符的优先级,则依次退出堆栈,并将该运算符放入堆栈

6 .最终将堆栈中的符号按顺序从堆栈中提取出来并输出。

运算符的优先级(记住,它与wxdwt匹配) )。

1 [] () ) (兄弟) ) ) ) )。

3 */

4 -

代码//运算符堆栈opstruct{char data[MAXSIZE]; //存储运算符int top的//堆栈顶部指针}op; 语音传输(char exp )、char postexp[] ) ) {char ch; int i,j; //i为骑马订exp下标,j为下标postexp下标op.top=-1; ch=exp[i]; //获取输入的第一个字符I的威尔(ch!=' ' ) {交换机(ch ) (case ) ) ) ://遇到左括号并直接堆栈到op.top; op.data[op.top]=ch; 布雷克; case ' ) ' : //堆栈顶部元素继续堆栈,直到遇到右括号while(op.data(op.top )!=''{postexp[j]=op.data[op.top]; j; op.top----; }op.top----; //遇到左括号时,直接删除break; case ' ': //加减运算子的优先顺序最低,且不比其他运算子大,因此直接堆叠case'-':while(op.top )=-1op.data[op.top]!=' ' () /如果堆栈不为空且未遇到左括号,则postexp[j]=op.data[op.top]; j; op.top----; }op.top; //,即堆栈为空或遇到左括号,当前运算符为op.data[op.top]=ch; 布雷克; case ' * ' : case '/' : while (op.top!=-1op.data[op.top]!=' () (op.data [ op.top ]==' * '|op.data [ op.top ]=)/' ) {postexp[j]=op.data[op.top]; //堆栈不为空,未遇到左括号,遇到同级符号:都出堆栈j; op.top----; }op.top; //如果不满足上述条件,则堆栈op.data[op.top]=ch; 布雷克; case ' ':break; //空格//default通常是最后使用的,表示在任何情况下都会发生,default:while(ch='0'ch='9' ) /或数字postexp[j]=ch //直接进入堆栈j的ch=exp[i]; //遍历下一个数字I; (I----; postexp[j]='# '; //用#表示一个数值列的末尾的j; 布雷克; }ch=exp[i]; I; }while(op.top!=-1 )//此时exp扫描已完成,如果堆栈不空闲,则弹出堆栈放在postexp上的postexp[j]=op.data[op.top]; j; op.top----; }postexp[j]=' '; 添加//结束标记并完成后缀表达式输入}的另一种转换方法是根据运算符的优先级将骑马订表达式括在括号中。 例如,将52*(16 )-(8/2)1)骑马订格式括在括号中,

首先计算2*(16 ),加上括号,得到5 )2* ) 16 )-8/2

再计算除法,得到5(2*(1) )-(8/2)

再计算加法,得到(5)2* (1)6) )-)8/2)

最后进行减法运算,得到((5)2* (1) )-(8/2) ) )

2)用最近的符号替换每个大括号

(5)2)1)6)8)/-

3)去掉所有左括号,5 2 1 6 * 8 2/-

该方法不能用程序实现

前缀表达式求值从右到左扫描公式遇到数字时,将数字推入堆栈,遇到运算符时弹出堆栈顶部的两个数,用运算符计算它们,然后将结果放入堆栈中重复上述过程

直到表达式最左端,最后运算得出的值即为表达式的结果

示例:
计算前缀表达式的值:- + 1 × + 2 3 4 5

从右至左扫描,将5,4,3,2压入堆栈;
2)遇到+运算符,弹出2和3(2为栈顶元素,3为次顶元素),计算2+3的值,得到5,将5压入栈;
3)遇到×运算符,弹出5和4,计算5×4的值,得到20,将20压入栈;
4)遇到1,将1压入栈;
5)遇到+运算符,弹出1和20,计算1+20的值,得到21,将21压入栈;
6)遇到-运算符,弹出21和5,计算21-5的值,得到16为最终结果

可以看到,用计算机计算前缀表达式是非常容易的,不像计算后缀表达式需要使用正则匹配

后缀表达式求值

与前缀表达式类似,只是顺序是从左至右:

从左至右扫描表达式遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算,并将结果入栈重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果

示例:
计算后缀表达式的值:1 2 3 + 4 × + 5 -

1)从左至右扫描,将1,2,3压入栈;
2)遇到+运算符,3和2弹出,计算2+3的值,得到5,将5压入栈;
3)遇到4,将4压入栈
4)遇到×运算符,弹出4和5,计算5×4的值,得到20,将20压入栈;
5)遇到+运算符,弹出20和1,计算1+20的值,得到21,将21压入栈;
6)遇到5,将5压入栈;
7)遇到-运算符,弹出5和21,计算21-5的值,得到16为最终结果

代码  struct{float data[MAXSIZE];int top; //栈顶指针 };float compvalue(char postexp[]){float d;char ch;int i=0; //i作为postexp下标 st.top=-1;ch=postexp[i];i++;while(ch!=''){switch(ch){case '+':st.data[st.top-1]=st.data[st.top-1]+st.data[st.top];st.top--;break;case '-':st.data[st.top-1]=st.data[st.top-1]-st.data[st.top];st.top--;break;case '*':st.data[st.top-1]=st.data[st.top-1]*st.data[st.top];st.top--;break;case '/':if(st.data[st.top]!=0){st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];}else{printf("除零错误!n");exit(0); //异常退出 }st.top--;break;default:d=0;while(ch>='0'&&ch<='9'){d=d*10+ch-'0'; //将数字字符转换成对应的数字存入d ch=postexp[i];i++;}st.top++;st.data[st.top]=d;}ch=postexp[i];i++;}return st.data[st.top];} 测试  #define MAXSIZE 100#include <stdio.h>int main(){int i = 0;char exp[] = {"(2*2)*1+3*2/1"};char postexp[MAXSIZE];trans(exp,postexp);while (postexp[i] != ''){printf("%c",postexp[i]);i++;}printf("n");printf("运算结果为:%f.n", compvalue(postexp));return 0;}


中缀表达式求值 口诀:

操作数直入左栈
运算符入栈有规则
若遇栈空直接入栈
若栈不空看优先级
栈顶元素优先级只有大于扫描元素的优先级才出栈
否则遇到都入栈
左括号入栈直到遇到右括号吐出来

中缀表达式求值过程: 例:求5+7*3*(2+1)

(1)准备两个空栈,数字入左栈,符号入右栈

(2)5进左栈,+进右栈

(3)7进左栈,*的优先级大于+,直接进右栈

(4)3进左栈

(5)*的优先级等于*,第一个*出栈,并且左栈要弹出两个元素进行运算,即3*7=21,并将新的运算结果压入左栈

(6)第二个*进右栈,左括号(直接进栈

(7)2进左栈

(8)+直接进右栈

(9)1进左栈

 

(10)遇到右括号,之前的元素全部弹出进行运算直到遇见左括号

(11)1+2=3,将3压入左栈,(左括号删除

(12)21*3=63,将63压入左栈

(13)63+5=68,最后的左栈元素为68

总结 前缀表达式和后缀表达式计算的时候都是从一个方向扫描表达式,遇到数字压入栈,遇到运算符弹出栈顶的两个数进行运算并将结果入栈,重复知道结束前缀和后缀表达式已经内在地包含运算顺序,因此不用括号来确定优先级

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。