第二章 前缀表达式、中缀表达式、后缀表达式的转换

合集下载

前缀、中缀、后缀表达式

前缀、中缀、后缀表达式

前缀、中缀、后缀表达式在计算机科学中,表达式是由操作符和操作数组成的数学式子。

为了方便计算机进行计算,表达式可以以不同的形式表示,包括前缀、中缀和后缀表达式。

一、前缀表达式前缀表达式,也称为波兰表达式,是将操作符写在操作数之前的一种表达式形式。

例如,加法操作符写在两个操作数之前,减法操作符写在两个操作数之前,以此类推。

前缀表达式的一个特点是,操作符和操作数之间没有括号,而是通过空格或其他分隔符进行分隔。

这种形式的表达式可以直接被计算机解析和计算。

例如,表达式"+ 2 3"可以被解析为2加3,得到结果5。

同样地,表达式"- 5 3"可以被解析为5减去3,得到结果2。

二、中缀表达式中缀表达式是我们平时最常见的表达式形式,操作符位于两个操作数之间。

例如,"2 + 3"就是一个中缀表达式。

中缀表达式的一个特点是使用了括号来表示优先级,以及操作符的结合性。

例如,"(2 + 3) * 4"表示先计算括号内的加法,再将结果乘以4。

中缀表达式的解析和计算相对复杂,需要考虑操作符的优先级和结合性,以及括号的使用。

为了方便计算机进行计算,通常需要将中缀表达式转换为其他形式。

三、后缀表达式后缀表达式,也称为逆波兰表达式,是将操作符写在操作数之后的一种表达式形式。

例如,"2 3 +"就是一个后缀表达式。

后缀表达式的一个特点是,操作符和操作数之间也没有括号,而是通过空格或其他分隔符进行分隔。

这种形式的表达式同样可以直接被计算机解析和计算。

后缀表达式的解析和计算相对简单,不需要考虑操作符的优先级和结合性,也不需要使用括号。

计算机可以通过从左到右依次处理操作数和操作符,最终得到结果。

例如,表达式"2 3 +"可以被解析为2加3,得到结果5。

同样地,表达式"5 3 -"可以被解析为5减去3,得到结果2。

“中序表达式”转换为“前序表达式”、“后序表达式”

“中序表达式”转换为“前序表达式”、“后序表达式”

“中序表达式”转换为“前序表达式”、“后序表达式” 上周末参照书本写了个“计算器”的程序,其中最令我费解的就是“前序表达式”、“后续表达式”,好像记得⽼师在上课的时候讲过,估计当时也没听懂,看的稀⾥糊涂的,不过现在⼤概明⽩了…… 在此仅做以笔记。

⾸先看下⾯所⽰表格:中序表达式2*3/(2-1)+3*(4-1)前序表达式+/*23-21*3-41后序表达式23*21-/341-*+ 中序表达式对我们⽽⾔是很直观的(我们平时接触的就是这个),但计算机处理起来⽐较⿇烦(括号、优先级之类的),前序和后序表达式中没有括号,⽽且在计算中只需单向扫描,不需要考虑运算符的优先级。

以前序表达式“+/*23-21*3-41”为例,从右往左,先取出两个操作数“1”、“4”和⼀个运算符“-”,计算“4-1”,将结果3回填到字符串中,现在字符串变为“+/*23-21*33”。

再从右⾄左取两个数“3”、“3”和“*”,计算“3*3”,将结果“9”回填到字符串,得“+/*23-219’”, 再取数,连续取出“9”、“1”、“2”,直到取出⼀个运算符“-”,将与运算符最近的两个操作数进⾏计算,即“2-1”得“1”,回填字符串中,现在为“+/*239” 重复上述步骤,取出“2*3”=6,回填字符串得到“+/619”, 再取“6/1”=6,得到“+69”, 再取“6+9”=15。

运算完毕。

即从右⾄左取数,直到取出⼀个运算符,将刚取出的紧挨着运算符的两个操作数按运算符进⾏计算,结果回填⾄运算符。

重复该步骤,直到最后只剩下⼀个字符串则剩下的字符串即为结果。

后序表达式的字符串扫描⽅式正好和前序相反,是从左往右扫描,规则类似。

中序表达式转前序表达式步骤1、反转输⼊字符串,如“2*3/(2-1)+3*(4-1)” 反转后为“ )1-4(*3+)1-2(/3*2”,2、从字符串中取出下⼀个字符 2.1.如果是操作数,则直接输出 2.2.如果是“)”,压⼊栈中 2.3.如果是运算符但不是“(”,“)”,则不断循环进⾏以下处理 2.3.1.如果栈为空,则此运算符进栈,结束此步骤 2.3.2.如果栈顶是“)”,则此运算符进栈,结束此步骤 2.3.2.如果此运算符与栈顶优先级相同或者更⾼,此运算符进栈,结束此步骤 2.3.4.否则,运算符连续出栈,直到满⾜上述三个条件之⼀,然后此运算符进栈 2.4、如果是“(”,则运算符连续出栈,直到遇见“)”为⽌,将“)”出栈且丢弃之3、如果还有更多的字符串,则转到第2步4、不在有未处理的字符串了,输出栈中剩余元素5、再次反转字符串得到最终结果 我第⼀次看到这个的时候就没看懂是什么意思,在⽹上查了点,⼜瞪了它好久才明⽩了,就以“2*3/(2-1)+3*(4-1),”为例做以下说明: 2*3/(2-1)+3*(4-1),反转得“ )1-4(*3+)1-2(/3*2 ”; 取第⼀个字符串为“)”,⼊栈(此时栈中为“)”); 取下⼀个“1”,是操作数,直接输出(⽬前输出“1”); 取下⼀个“-”,既不是“)”,也不是“(”,则转到2.3,此时栈顶为“)”,则该运算符进栈(栈中为“-、)”); 取下⼀个“4”,直接输出(⽬前输出的是“14”); 取下⼀个“(”,运算符连续出栈(栈中此时为“-、)”),直到遇见“)”,此时输出“-”(⽬前输出“14-”,栈为空); 取下⼀个“*”,既不是“)”,也不是“(”,则转到2.3,进栈(栈为空); 取下⼀个“3”,直接输出(⽬前输出“14-3”); 取下⼀个“+”,此时栈顶为“*”,“+”的优先级⽐“*”低(2.3.4),则运算符连续出栈(只有⼀个*出栈,此时栈为空符合2.3.1,继续下⼀步),“+”进栈; 取下⼀个“)”,进栈(此时栈中为“)、+”); 取下⼀个“1”直接输出(⽬前输出为14-3*1); 取下⼀个“-”,此时栈顶为“)”,“-”进栈(栈中此时为“-、)、+”); 取下⼀个“2”,直接输出(⽬前输出“14-3*12”); 取下⼀个“(”,运算符连续出栈,直到遇见“)”,此时栈中为“-、)、+”,输出-,且抛弃“)”,此时输出为“14-3*12-”,栈中为“+”; 取下⼀个“/”,优先级⽐栈顶“+”⾼,此运算符进栈; 取下⼀个“3”,直接输出(此时输出“14-3*12-3”); 取下⼀个“*”,优先级⽐栈顶“+”⾼,此运算符进栈; 取下⼀个“2”,输出(此时输出“14-3*12-32”); 不在有未处理的运算符,输出栈中剩余元素,结果的“14-3*12-32*/+”; 反转字符串的“+/*23-21*3-41”。

前缀中缀后缀相互转换

前缀中缀后缀相互转换

前缀中缀后缀相互转换符号说明•为了表示简便,程序中符号如下•¬, 非•∨,或•∧, 与•→, 推出•=, 等价中缀转后缀•例:P∨Q∧R∨(T=S)输出:PQR∧∨TS=∨算法流程:1.初始化两个栈:运算符栈S1,储存中间结果的栈S2;2.从左至右扫描中缀表达式:1.遇到操作数2.遇到运算符3.遇到括号P∨Q∧R∨(T=S)中缀转后缀算法流程:1.初始化两个栈:运算符栈S1,储存中间结果的栈S2;2.从左至右扫描中缀表达式:1.遇到操作数:直接压入S22.遇到运算符3.遇到括号P∨Q∧R∨(T=S)P中缀转后缀算法流程:1.初始化两个栈:运算符栈S1,储存中间结果的栈S2;2.从左至右扫描中缀表达式:1.遇到操作数2.遇到运算符:1.如果S1为空,或S1栈顶为左括号“(”,该运算符压入S1;P∨Q∧R∨(T=S)2.若优先级高于栈顶运算符,该运算符压入S1;3.否则,S1栈顶运算符弹出并压入S2,重新进行2-2操作。

3.遇到括号∨P中缀转后缀算法流程:1.初始化两个栈:运算符栈S1,储存中间结果的栈S2;2.从左至右扫描中缀表达式:1.遇到操作数:直接压入S22.遇到运算符3.遇到括号P∨Q∧R∨(T=S)QP∨中缀转后缀算法流程:1.初始化两个栈:运算符栈S 1,储存中间结果的栈S 2;2.从左至右扫描中缀表达式:1.遇到操作数2.遇到运算符:1.如果S 1为空,或S 1栈顶为左括号“(”,该运算符压入S 1;2.若优先级高于栈顶运算符,该运算符压入S 1;3.否则,S 1栈顶运算符弹出并压入S 2,重新进行2-2操作。

3.遇到括号P ∨Q ∧R ∨(T =S)P ∨Q ∧中缀转后缀算法流程:1.初始化两个栈:运算符栈S 1,储存中间结果的栈S 2;2.从左至右扫描中缀表达式:1.遇到操作数:直接压入S 22.遇到运算符:3.遇到括号P ∨Q ∧R ∨(T =S)P ∨Q ∧R中缀转后缀算法流程:1.初始化两个栈:运算符栈S 1,储存中间结果的栈S 2;2.从左至右扫描中缀表达式:1.遇到操作数2.遇到运算符:1.如果S 1为空,或S 1栈顶为左括号“(”,该运算符压入S 1;2.若优先级高于栈顶运算符,该运算符压入S 1;3.否则,S 1栈顶运算符弹出并压入S 2,重新进行2-2操作。

前缀中缀后缀表达式转换 题目

前缀中缀后缀表达式转换 题目

前缀中缀后缀表达式转换题目摘要:1.前缀表达式转换成中缀表达式的方法2.中缀表达式转换成后缀表达式的方法3.常见的前缀、中缀和后缀表达式示例4.实践操作:转换实例正文:一、前缀表达式转换成中缀表达式的方法前缀表达式是指由运算符和操作数组成的一种表达式,其中运算符放在操作数之前。

将前缀表达式转换为中缀表达式,主要是将运算符插入到相应的操作数之间。

以下是一个简单的转换方法:1.遍历前缀表达式,遇到运算符,将其插入到操作数之间。

2.若遇到左括号,将其与当前操作数一起放入一个队列。

3.遇到右括号,从队列中弹出两个操作数,进行运算,并将结果放入队列。

4.直到队列为空,依次弹出队列中的操作数,进行运算,得到中缀表达式。

二、中缀表达式转换成后缀表达式的方法中缀表达式是指由运算符和操作数组成的一种表达式,其中运算符放在操作数之间。

将中缀表达式转换为后缀表达式,主要是根据运算符的优先级和结合性进行排序。

以下是一个简单的转换方法:1.遍历中缀表达式,遇到操作数,将其放入一个栈。

2.遇到运算符,根据其优先级和结合性,从栈中弹出相应的操作数进行运算,并将结果放入栈。

3.直到栈为空,依次弹出栈中的操作数,得到后缀表达式。

三、常见的前缀、中缀和后缀表达式示例前缀表达式:+(a*b)中缀表达式:a*b+后缀表达式:ab*+四、实践操作:转换实例1.转换前缀表达式:+(a*(b+c))中缀表达式:a*(b+c)+后缀表达式:abc*+2.转换前缀表达式:-a*(b-c)中缀表达式:-a*(b-c)后缀表达式:-abc*+通过以上内容,我们可以掌握前缀表达式、中缀表达式和后缀表达式的转换方法。

中缀式和后缀式的相互转换

中缀式和后缀式的相互转换

中缀式和后缀式的相互转换中缀式和后缀式是数学表达式的两种常见表示方式。

中缀式是我们常见的表达式形式,例如"3 + 4 * 5",而后缀式是将运算符放在操作数后面表示,例如"3 4 5 * +"。

将中缀式转换为后缀式可以通过使用栈和优先级规则来完成。

具体步骤如下:1. 创建一个空栈和一个空字符串后缀表达式2. 从左到右扫描中缀表达式的每个元素3. 如果遇到操作数,则将其添加到后缀表达式中4. 如果遇到运算符,则将其与栈顶运算符进行比较:- 如果栈为空或栈顶是左括号"(",则将运算符入栈- 如果运算符优先级高于栈顶运算符,则将运算符入栈- 否则,将栈顶运算符弹出并添加到后缀表达式中,直到栈为空或栈顶是左括号为止,然后将当前运算符入栈5. 如果遇到左括号"(",则将其入栈6. 如果遇到右括号")",则将栈顶运算符弹出并添加到后缀表达式中,直到遇到左括号为止,然后将左括号弹出(左括号不添加到后缀表达式中)7. 扫描完整个中缀表达式后,将栈中剩余的运算符依次弹出并添加到后缀表达式中8. 后缀表达式即为转换结果例如,将中缀式"3 + 4 * 5"转换为后缀式的过程如下:中缀表达式: 3 + 4 * 5初始化:栈为空,后缀表达式为空扫描 3:后缀表达式:3扫描 +:栈为空,运算符入栈扫描 4:后缀表达式:3 4扫描 *:栈顶运算符优先级低于当前运算符,运算符入栈扫描 5:后缀表达式:3 4 5扫描完毕,将栈中剩余运算符弹出:后缀表达式:3 4 5 * +因此,中缀式"3 + 4 * 5"转化为后缀式"3 4 5 * +"。

将后缀式转换为中缀式可以通过使用栈和逆序扫描后缀表达式的方式来完成。

具体步骤如下:1. 创建一个空栈2. 从左到右逆序扫描后缀表达式的每个元素3. 如果遇到操作数,则将其入栈4. 如果遇到运算符,则从栈中弹出两个操作数,并将运算符与操作数组合成一个中缀表达式,并将该中缀表达式入栈5. 扫描完整个后缀表达式后,栈顶的中缀表达式即为转换结果例如,将后缀式"3 4 5 * +"转换为中缀式的过程如下:后缀表达式:3 4 5 * +初始化:栈为空从右到左逆序扫描:扫描 +:弹出操作数5和4,组合为中缀表达式"4 + 5",入栈扫描 *:弹出操作数4和中缀表达式"4 + 5",组合为中缀表达式"(4 + 5) * 4",入栈扫描 3:入栈扫描完毕,栈顶的中缀表达式即为转换结果:中缀表达式:"(4 + 5) * 3"因此,后缀式"3 4 5 * +"转化为中缀式"(4 + 5) * 3"。

C#算术表达式求值(后缀法),看这一篇就够了

C#算术表达式求值(后缀法),看这一篇就够了

C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。

⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。

1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。

因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。

⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。

⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。

举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。

2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。

在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。

3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。

他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。

因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。

注意:逆波兰记法并不是简单的波兰表达式的反转。

因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。

信息学竞赛前中后缀表达式精讲

信息学竞赛前中后缀表达式精讲

信息学竞赛前中后缀表达式精讲一、前缀表达式前缀表达式,也称为波兰表达式,是一种将运算符置于操作数之前的表示方法。

在前缀表达式中,运算符在操作数之前,且每个运算符和操作数之间都用空格隔开。

例如,"+ 3 4"表示的是3和4的和。

前缀表达式的计算过程是从右到左进行的。

以"+ 3 4"为例,首先是加法运算符"+",后面是两个操作数3和4,所以结果是7。

前缀表达式的优点是可以直接通过栈来计算,不需要考虑运算符的优先级。

具体计算过程是,从右到左遍历表达式,遇到操作数就入栈,遇到运算符就取出栈顶的两个操作数进行运算,再将结果入栈。

最终,栈中的唯一元素就是表达式的结果。

二、中缀表达式中缀表达式是我们常见的数学表达式的表示方式,运算符在操作数的中间,例如"3 + 4"。

中缀表达式的计算过程是从左到右进行的,遇到运算符时需要考虑优先级。

为了解决中缀表达式中运算符优先级的问题,我们可以使用括号来改变运算的顺序。

括号中的表达式优先计算,然后再根据运算符的优先级进行计算。

例如,"(3 + 4) * 5",首先计算括号中的表达式"3 + 4",结果是7,然后再将结果乘以5,最终结果是35。

中缀表达式的计算过程比较复杂,需要考虑运算符的优先级和括号的影响。

一种常见的方法是使用栈和队列来计算中缀表达式。

具体过程是,从左到右遍历表达式,遇到操作数就入队列,遇到运算符则与栈顶的运算符进行比较,如果栈顶的运算符优先级较高,则将栈顶的运算符出栈并入队列,直到栈为空或者栈顶的运算符优先级较低。

然后将当前的运算符入栈。

最终,队列中的唯一元素就是表达式的结果。

三、后缀表达式后缀表达式,也称为逆波兰表达式,是一种将运算符置于操作数之后的表示方法。

在后缀表达式中,运算符在操作数之后,且每个运算符和操作数之间都用空格隔开。

例如,"3 4 +"表示的是3和4的和。

前缀、中缀、后缀表达式的相互转换方法

前缀、中缀、后缀表达式的相互转换方法

前缀、中缀、后缀表达式的相互转换⽅法前缀式、中缀式、后缀式相互转换⼀. 中缀式转化成前缀式和后缀式:⼀个中缀式到其他式⼦的转换⽅法这⾥我给出⼀个中缀表达式a +b *c - (d +e )第⼀步:按照运算符的优先级对所有的运算单位加括号式⼦变成:( ( a + ( b * c ) ) - ( d + e ) )第⼆步:转换前缀与后缀表达式中缀转前缀:把运算符号移动到对应的括号前⾯则变成:- ( + ( a * ( b c ) ) + ( d e ) )把括号去掉:- + a * b c + d e 前缀式⼦出现中缀转后缀:把运算符号移动到对应的括号后⾯则变成:( ( a ( b c ) * ) + ( d e ) + ) -把括号去掉:a b c * + d e + - 后缀式⼦出现⼆. 前缀式转化成中缀式:+ a * b c + d e从后往前遇到运算符,将其与后⾯两个运算数结合,加上括号,当成新的运算数(例如:* b c 加上括号,变成 ( * b c )⼀个整体,作为运算数)变成:( - ( + a ( * b c ) ) ( + d e ) )将运算符加在括号内运算数中间。

变成:( ( a + ( b * c ) ) - ( d + e ) )去掉部分括号:a + b * c - ( d + e )(最后去掉的是不影响运算式含义的多余括号)三. 后缀式转化成中缀式:a b c * + d e + -从前往后遇到运算符,将其与前⾯两个运算数结合,加上括号,当成新的运算数变成:( ( a ( b c * ) + ) ( d e + ) - )将运算符加在括号内运算数中间。

变成:( ( a + ( b * c ) ) - ( d + e ) )去掉部分括号:a + b * c - ( d + e )(最后去掉的是不影响运算式含义的多余括号)。

前中后缀表达式的转化例题

前中后缀表达式的转化例题

前中后缀表达式的转化例题【最新版】目录1.前中后缀表达式的转化例题介绍2.前缀表达式的定义和性质3.中缀表达式的定义和性质4.后缀表达式的定义和性质5.表达式转换的方法和步骤6.表达式转换的实际应用案例正文一、前中后缀表达式的转化例题介绍前缀表达式、中缀表达式和后缀表达式是计算机科学中常见的三种表达式表示方法。

它们分别对应着不同的语法结构,具有各自的特点和应用场景。

在实际问题中,有时需要将一种表达式转换为另一种表达式,以便进行相应的操作和分析。

下面我们将通过一个具体的例题来介绍表达式转换的方法。

例题:将中缀表达式 "a + b" 转换为后缀表达式。

二、前缀表达式的定义和性质前缀表达式是一种特殊的二叉树,它的每个内部节点都有一个前缀,即该节点的左子树或右子树的一个路径。

前缀表达式的性质如下:1.前缀表达式只有一个根节点;2.每个节点只有一个前缀;3.前缀表达式的每个叶子节点对应一个变量;4.前缀表达式的每个节点对应一个运算符。

三、中缀表达式的定义和性质中缀表达式是另一种特殊的二叉树,它的每个内部节点都有一个中缀,即该节点的左子树、右子树或该节点本身。

中缀表达式的性质如下:1.中缀表达式只有一个根节点;2.每个节点可以有一个或多个中缀;3.中缀表达式的每个叶子节点对应一个变量;4.中缀表达式的每个节点对应一个运算符。

四、后缀表达式的定义和性质后缀表达式是一种特殊的二叉树,它的每个内部节点都有一个后缀,即该节点的左子树、右子树或该节点本身。

后缀表达式的性质如下:1.后缀表达式只有一个根节点;2.每个节点可以有一个或多个后缀;3.后缀表达式的每个叶子节点对应一个常数或变量;4.后缀表达式的每个节点对应一个运算符。

五、表达式转换的方法和步骤1.首先,根据中缀表达式构建一棵二叉树;2.遍历二叉树,将每个节点转换为对应的前缀表达式或后缀表达式;3.对于前缀表达式,遍历二叉树的每个节点,将该节点的左子树或右子树转换为前缀表达式,并将该节点对应的运算符添加到前缀表达式中;4.对于后缀表达式,遍历二叉树的每个节点,将该节点的左子树或右子树转换为后缀表达式,并将该节点对应的运算符添加到后缀表达式中;5.最后,将所有的前缀表达式或后缀表达式按照一定的顺序连接起来,得到最终的表达式。

C语言实现中缀、后缀、前缀表达式 相互转化并求值

C语言实现中缀、后缀、前缀表达式 相互转化并求值

C语言实现中缀、后缀、前缀表达式相互转化并求值1.问题描述(1)表达式求值问题表达式是数据运算的基本形式。

人们的书写习惯是中缀式,如:11+22*(7-4)/3。

中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。

表达式还有后缀式(如:22 7 4 - * 3 / 11 +)和前缀式(如:+ 11 / * 22 –7 4 3)。

后缀表达式和前缀表达式中没有括号,给计算带来方便。

如后缀式计算时按运算符出现的先后进行计算。

本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。

2.数据结构设计(1)表达式求值问题由于表达式中有字符与数字两种类型,故定义结点一个标志域data,标志结点存储的为字符data=2还是数字data=1,再寻找结点中对应的存储位置,读取数字域data1,字符域data2。

而在前缀表达式时,存在表达式逆序,因表达式类型不统一,用栈逆序极不方便,选择构建双向链表,存储表达式。

typedef struct Node //定义存储中缀表达式的结点类型{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2 //定义存储前缀表达式的结点类型{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;3.运行、测试与分析(1)表达式求值问题(1)按提示输入中缀表达式,如图1.1所示。

如输入中缀表达式不正确,提示输入有误,如图1.2,1.3所示。

图1.1图1.2图1.3(2)选择表达式转换并求值方式。

按“1”选择中缀表达式求值,如图1.4所示。

图1.4(3)按“2”选择中缀表达式转变为后缀表达式并求值,如图1.5所示。

图1.5(4)按“3”选择中缀表达式转变为前缀表达式并求值,如图1.6所示。

前缀算术表达式转换及表达式计算

前缀算术表达式转换及表达式计算

一、概述在数学运算中,算术表达式是一种描述数学运算的方式,常通过符号和数字的组合表示特定的计算过程。

前缀算术表达式是一种特殊的算术表达式,它的操作符位于操作数之前,例如"+ 3 4"表示加法运算,操作数为3和4。

前缀表达式的计算机实现在计算机科学和编程中具有广泛的应用。

本文将介绍前缀算术表达式的转换和表达式的计算方法。

二、前缀算术表达式转换1. 中缀表达式转前缀表达式中缀表达式是我们常见的数学表达式,例如"3 + 4 * 5"。

中缀表达式转前缀表达式的关键在于将操作符移动到操作数之前。

转换方法如下:- 从右向左遍历中缀表达式的每个字符。

- 如果是操作数,则直接输出。

- 如果是运算符,则与运算符栈顶的运算符比较优先级,如果优先级高于栈顶运算符,则入栈;否则弹出栈顶运算符并输出,直到满足条件入栈。

- 遍历完成后,弹出栈中所有运算符并输出,即得到前缀表达式。

中缀表达式"3 + 4 * 5"转换为前缀表达式为"+ 3 * 4 5"。

2. 后缀表达式转前缀表达式后缀表达式是操作数位于操作符之前的算术表达式,例如"3 4 + 5 *"。

后缀表达式转前缀表达式的方法如下:- 从左向右遍历后缀表达式的每个字符。

- 如果是操作数,则入栈。

- 如果是运算符,则弹出栈顶的两个操作数,并将运算符与操作数组合,得到新的前缀表达式,并将结果入栈。

- 遍历完成后,栈内剩下的元素即为前缀表达式。

后缀表达式"3 4 + 5 *"转换为前缀表达式为"* + 3 4 5"。

3. 中缀表达式转后缀表达式再转前缀表达式有时候,我们将中缀表达式转换为后缀表达式,然后再将后缀表达式转换为前缀表达式。

这种方法的具体步骤如下:- 将中缀表达式转换为后缀表达式。

- 将后缀表达式转换为前缀表达式。

这种方法的优点在于简化了中缀表达式到前缀表达式的转换过程。

中缀表达式与前缀表达式的转换_

中缀表达式与前缀表达式的转换_
ຫໍສະໝຸດ 中缀表达式与前缀表达式的转换
中缀表达式与前缀表达式的转换
中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3;
后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:2 1 + 3 *;
6)假如是开括号,栈中运算符逐个出栈并输出,直到遇到闭括号。闭括号出栈并丢弃。
7)假如输入还未完毕,跳转到步骤2。
8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
9)求输出串的逆序。*/
#include<iostream>
#include<string>
stack[t
op]=s[i];
break;
}
else
{
output=output+stack[top];
top--;
}
}
if(s[i]=='(')//6)假如是开括号,栈中运算符逐个出栈并输出,直到遇到闭括号。闭括号出栈并丢弃。
for(int i=s.length()-1;i>=0;)//1)求输入串的逆序。
{
if(s[i]>=48&&s[i]<=57)
output=output+s[i];//3)假如是操作数,把它添加到输出串中。
if(s[i]==')')//4)假如是闭括号,将它压栈。
{
case'+':

中缀、前缀、后缀表达式的运算

中缀、前缀、后缀表达式的运算

中缀、前缀、后缀表达式的运算 中缀表达式,就是在表达式中,操作符在操作数的中间,⽐如 (1+2)*3,+和*在1, 2, 3的中间。

前缀表达式,就是操作符在操作数的前⾯,⽐如 +12,+在1, 2的前⾯。

后缀表达式,就是操作符在操作数的后⾯,⽐如 12+,+在1, 2的后⾯。

为什么会有这么多表达式呢?它们⽬的不同。

中缀表达式,便于我们书写,也符合我们的阅读习惯,在计算机程序中,都是写中缀表达式,但它却不利于计算机进⾏算术计算,因为涉及到优先级和括号。

前缀表达式和后缀表达式中没有括号,并且运算符的优先级也通过它们在表达式中的顺序体现出来了,有利于计算机进⾏算术运算。

前缀表达式也叫波兰表达式,因为它是由⼀个波兰⼈发明的,相应的,后缀表达式也称为逆波兰表达式。

举个例⼦来说明⼀下三者的运算过程,假设计算(3+4)*5-6 使⽤中缀表达式进⾏计算 1,创建两个栈,⼀个是数字栈,⽤来存放操作数,⼀个是字符栈,⽤来存放操作符。

2,算术表达式是⼀个字符串,从左到右循环遍历表达式,依次取出每⼀个字符。

当取出的字符是操作数时,⼊数字栈。

当取出的字符是操作符时,这时还要看操作符的优先级和字符栈是否为空 如果字符栈为空,直接把取出的字符放⼊到字符栈中。

如果字符栈不为空,则要⽐较字符的优先级 如果取出的字符的优先级⼤于等于字符栈中栈顶的字符的优先级,直接把取出的字符放⼊到字符栈中。

如果取出的字符的优先级⽐字符栈中栈顶的字符的优先级低,则要循环进⾏如下操作,直到取出的字符的优先级⼤于等于字符栈中栈顶字符的优先级或者栈为空,此时,把取出的字符放⼊到字 符栈中。

如下操作就是: 1,从字符栈中弹出操作符 2,从数字栈中弹出两个操作数。

3,操作数结合操作符进⾏计算,要注意操作数顺序,后⾯pop出的数在求值的表达式中是前⾯的操作数,尤其是在做减法的时候 4,计算出的值放⼊到数字栈。

为什么要⽐较操作符的优先级呢?因为要确定操作数属于哪个操作符,相邻两个操作符之间的数字是共享的。

算术表达式的前缀表达式,中缀表达式和后缀表达式

算术表达式的前缀表达式,中缀表达式和后缀表达式

算术表达式的前缀表达式,中缀表达式和后缀表达式这里所谓的前缀,中缀,后缀是根据操作符的位置来定的,如果操作符在操作数前面,则称为前缀表达式,例如“- + 1 × + 2 3 4 5”;如果操作符在操作数之间,则称为中缀表达式,例如“1+((2+3)×4)-5”;如果操作符在操作数后面,则称为后缀表达式,例如“1 2 3 + 4 × + 5 -”。

虽然中缀表达式符合人类的日常思维习惯,但是计算机在存储中缀表达式时,需要使用树这种数据结构,如果表达式过于复杂,那么树的高度会变得很高,大大增加了时间复杂度和空间复杂度。

如果转换成线性结构,那么效率将变得高很多,所以需要将中缀表达式先转换成前缀或者后缀表达式,然后依靠栈这种线性数据结构来进行计算。

前缀表达式又叫波兰表达式,后缀表达式又叫逆波兰表达式。

前缀表达式基本没有在商业计算机中使用过,所以现实中用的更多的是后缀表达式。

如何将中缀表达式转化成后缀表达式呢?利用两个栈S1,S2:其中S1存放操作符,S2存放操作数从左往右遍历中缀表达式,如果遇到数字,则放入S2中,如果遇到操作符,则放入S1中。

在放操作符的时候有一定的规则,如果栈为空或栈顶元素为(,则直接压栈。

如果是(,也直接压栈;如果栈顶元素为普通操作符,则比较优先级,如果待压栈的操作符比栈顶操作符优先级高,则直接压栈,否则将S1中的栈顶元素出栈,并压入S2中,再接着比较S1栈顶元素的优先级。

如果遇到),则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃。

最后将S1中剩余的运算符依次弹出并压入S2,逆序输出S2(从栈底到栈顶)便得到了后缀表达式。

(注意:等号的优先级最低,因为要到最后才进行赋值操作)得到后缀表达式之后,计算就变得方便多了,遇到数字就压栈,遇到操作符的时候,pop出栈顶的两个元素,进行计算后将结果又压入栈中,这样一直下去,直到得到最终结果。

前缀表达式、中缀表达式、后缀表达式的定义及实现

前缀表达式、中缀表达式、后缀表达式的定义及实现

前缀表达式、中缀表达式、后缀表达式的定义及实现定义1. 中缀表达式:平常我们⼿动输⼊的表达式、计算式,都是中缀表达式,按照我们理解的运算优先顺序进⾏计算。

按照⼈的思维⽅式进⾏表达式的输⼊,最终输出预期结果。

⽐如 1 + (2 + 3) × 4 - 52. 后缀表达式、前缀表达式:虽然中缀表达式是按照我们⾁眼的运算符优先级写出的,但是最终实现这个运算的,⽐如计算器是没有这么智能的,计算器只会按照输⼊的运算符⼀个⼀个的进⾏计算。

这时候就⽤到了后缀、前缀表达式。

⽐如:后缀表达式针对于上⾯的就是 1 2 3 + 4 × + 5 -⼿动实现1. 那么我们怎么实现中缀转换为后缀呢?⼿动实现:把所有运算按照优先级加上括号,然后把运算符号移动到括号前⾯,然后去除括号。

⽐如:1 + (2 + 3) × 4 - 5加括号:1 +( (2 + 3) × 4 ) - 5(1 +( (2 + 3) × 4 )) - 5((1 +( (2 + 3) × 4 )) - 5)运算符号后移,并去除括号:1 2 3 + 4 × + 5 -前缀表达式,就是符号前移,⼀样的2.计算机怎么去识别后缀呢使⽤⼤名⿍⿍的栈就很⽅便的实现了栈的特点是先进后出,后进先出针对于后缀表达式1. 遇到数字⼊栈2. 遇到运算符,弹出栈的两个数字,然后和运算符进⾏运算3. 重复过程4. 因为后缀表达式,其实已经是把运算符优先级顺序换⼀种表⽰形式,展现出来了⽽已程序实现说了⼀⼤推,我们⾸先来看⼀下程序上的实现⼀个对中缀表达式进⾏输⼊,然后进⾏转换,并进⾏结果的输出步骤1. 中缀表达式转化为后缀表达式2. 进⾏后缀表达式的计算第⼀步程序思路:1. 定义栈S1,存储运算符。

定义栈S2,存储数字和运算符,存储最终的后缀表达式2. 对于新字符进⾏判断只要新字符不等于‘\0’,⼀直进⾏下⾯的循环:1. 如果S1的⼤⼩为空, 字符⼊S12. 如果是( ⼊栈3. 如果是),将S1知道(之前的运算符出栈,添加到S2中4. 如果S1的⼤⼩不为空,并且S1栈顶的运算符优先级⼤于当前的新字符或者两个字符是相等的那么当前的S1栈顶就可以出栈,添加到S2中新字符⼊栈S15. 如果新字符的范围是‘0’ - ’9‘之间,那么新字符添加进S2中6. 否则,添加到S1中3. 跳出循环后,如果S1的size不为空,把S1的运算符⼀⼀弹出,添加到S2中,最终S2就是排列好的后缀表达式4. 然后就可以进⾏运算代码,使⽤c++int weight(const char code) {if((code == '+')|| (code == '-')) {return 1;}else if((code == '*')|| (code == '/')) {return 2;}}bool priority(const char left, const char right) {if(left == '(') {return false;}else if(weight(left) < weight(right)) {return false;}else {return true;}}bool caculation(const char* input, LinkStack<char>& S2) {if(input == NULL) {return false;}bool ret = true;LinkStack<char> S1;int i = 0;int out_index = 0;while(ret && (input[i] != '\0')) {if(input[i] == '(') {S1.push(input[i]);}else if((S1.size() > 0) && (input[i] == ')')) {char code = S1.get();while(code != '(') {S2.push(code);S1.pop();code = S1.get();}if(code == '(') {S1.pop();}}else if((S1.size() > 0) && priority(S1.get(), input[i])) {std::cout << "13" << std::endl;char code = S1.get();S2.push(code);S1.pop();S1.push(input[i]);}else if( (input[i] >= '0') && (input[i] <= '9')) {S2.push(input[i]);}else {S1.push(input[i]);}i++;}while(S1.size() > 0) {char code = S1.get();S2.push(code);S1.pop();}return ret;}4. 核⼼函数就是上⾯的两个,输⼊参数1是中缀表达式,输⼊参数2是栈,最终栈中存储排序好的后缀表达式5. 拿⼀个例⼦来演⽰⼀下:6.说明后缀表达式,这种⽅式后计算优点也很⼤,直接从上到下,数字就⼊栈,符号就把当前栈中的连续两个弹出,然后和当前符号进⾏运算,然后再⼊数字栈。

前缀中缀后缀表达式转换 题目

前缀中缀后缀表达式转换 题目

前缀中缀后缀表达式转换题目摘要:1.表达式的基本概念2.前缀、中缀和后缀表达式的定义3.表达式转换的方法和应用4.总结正文:一、表达式的基本概念在计算机科学中,表达式是指用运算符连接操作数的式子。

表达式可以是数字、字符、变量或者函数调用等。

根据运算符的优先级和结合性,表达式可以按照特定的顺序进行计算,得到一个结果。

二、前缀、中缀和后缀表达式的定义1.前缀表达式:前缀表达式是一种特殊的表达式,它的每个操作都只有一个前驱。

也就是说,我们可以从左到右依次计算每个操作的值,而不需要考虑运算符的优先级。

例如,表达式"a+b"就是一个前缀表达式。

2.中缀表达式:中缀表达式是包含了运算符优先级的表达式。

它的每个操作都可以有零个或多个前驱和后继。

例如,表达式"a*b+c"就是一个中缀表达式。

3.后缀表达式:后缀表达式是一种特殊的中缀表达式,它的每个操作符都有一个后驱,但没有前驱。

后缀表达式的计算顺序是按照运算符的顺序进行的,这样可以避免运算符优先级的问题。

例如,表达式"ab+c"就是一个后缀表达式。

三、表达式转换的方法和应用表达式转换是一种将一种类型的表达式转换为另一种类型的表达式的操作。

常见的表达式转换有前缀表达式转换为中缀表达式,中缀表达式转换为后缀表达式等。

1.前缀表达式转换为中缀表达式:可以通过递归地将前缀表达式的每个操作转换为中缀表达式来实现。

例如,对于前缀表达式"a+b",我们可以转换为中缀表达式"a,+,b"。

2.中缀表达式转换为后缀表达式:可以通过将中缀表达式的每个操作转换为后缀表达式,并将运算符转换为后缀表达式的操作符来实现。

例如,对于中缀表达式"a*b+c",我们可以转换为后缀表达式"ab,+,c"。

表达式转换在编译原理、计算理论等领域有广泛的应用。

例如,在编译器中,将源代码转换为目标代码的过程中,就需要进行表达式的转换和优化。

前缀表达式、中缀表达式和后缀表达式

前缀表达式、中缀表达式和后缀表达式

前缀表达式、中缀表达式和后缀表达式前缀、中缀、后缀表达式前缀、中缀、后缀表达式是对表达式的不同记法,其区别在于运算符相对于操作数的位置不同,前缀表达式的运算符位于操作数之前,中缀和后缀同理举例:中缀表达式:1 + (2 + 3) × 4 - 5前缀表达式:- + 1 × + 2 3 4 5后缀表达式:1 2 3 + 4 × + 5 -中缀表达式中缀表达式是⼀种通⽤的算术或逻辑公式表⽰⽅法,操作符以中缀形式处于操作数的中间。

中缀表达式是⼈们常⽤的算术表⽰⽅法。

虽然⼈的⼤脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进⾏求值。

对计算机来说,计算前缀或后缀表达式的值⾮常简单。

前缀表达式前缀表达式的运算符位于两个相应操作数之前,前缀表达式⼜被称为前缀记法或波兰式前缀表达式的计算机求值1. 从右⾄左扫描表达式2. 遇到数字时,将数字压⼊堆栈,遇到运算符时,弹出栈顶的两个数,⽤运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果⼊栈3. 重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果⽰例:计算前缀表达式的值:- + 1 × + 2 3 4 51. 从右⾄左扫描,将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. 遇到数字时,将数字压⼊堆栈,遇到运算符时,弹出栈顶的两个数,⽤运算符对它们做相应的计算(次顶元素op 栈顶元素 ),并将结果⼊栈3. 重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果⽰例:计算计算后缀表达式的值: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为最终结果中缀表达式转化为前缀和后缀表达式转化步骤:1. 按照运算符的优先级对所有的运算单位加括号2. 将运算符移动到对应括号的前⾯(前缀表达式)或后⾯(后缀表达式)3. 去掉括号,得到前缀或后缀表达式⽰例:中缀表达式:1+(2+3)×4-51)加括号式⼦变成 ((1+((2+3)×4))-5)2)移动运算符对于前缀表达式,变成了 -(+(1×(+(23)4))5)对于后缀表达式:变成了((1((23)+4)×)+5)-3)去掉括号前缀表达式: - + 1 × + 2 3 4 5后缀表达式:1 2 3 + 4 × + 5 -⼩结前缀、中缀、后缀是根据运算符与操作数的相对位置来划分的中缀表达式符合⼈的计算习惯,⽽前缀和后缀表达式适合计算机计算前缀表达式和后缀表达式计算的时候都是从⼀个⽅向扫描表达式,遇到数字压⼊栈,遇到运算符弹出栈顶的两个数进⾏运算并将结果⼊栈,重复知道结束前缀和后缀表达式已经内在地包含运算顺序,因此不⽤括号来确定优先级。

前序表达式中序表达式后序表达式

前序表达式中序表达式后序表达式

前序表达式中序表达式后序表达式前序表达式 , 中序表达式 , 后序表达式中序表达式中序表达式即我们⽇常使⽤的表达式,从左往右阅读,结构清晰,但是需要括号改变优先级,对计算机不友好eg:(1+4)*3+10/5,2*3/(2-1)+3*(4-1)前序表达式(波兰表⽰法Polish notation,或波兰记法)前序表达式的特点是操作符置于操作数前⾯,如果操作符的元数(+是⼆元操作符,故元数是2),则语法上不需要括号仍然能被⽆歧义的解释,不需要⼝号改变优先级。

eg:中序表达式: (1+4)*3+10/5前序表达式: + * + 1 4 3 / 10 5前序表达式的计算:eg:+ * + 1 4 3 / 10 5step1: 10 / 5 => 2new expression: + * + 1 4 3 2step2: 1 + 4 => 5new expression: + * 5 3 2step3: 5 * 3 => 15new expression: + 15 2step4: 15 + 2 => 17前序表达式的求值:⾸先要从右⾄左扫描表达式,从右边第⼀个字符开始判断,如果当前字符是数字则继续扫描,如果当前字符是运算符,将运算符右边最近的两个数字做运算,结果作为新的字符记录下来。

⼀直扫描到表达式的最左端时,最后运算的值也就是表达式的值。

后序表达式(逆波兰表⽰法(Reverse Polish notation,RPN,或逆波兰记法)后序表达式所有的操作符置于操作数后⾯,因此也被称为后缀表⽰法。

逆波兰表⽰法不需要括号标识操作符的优先级。

eg:中序表达式: (1+4)*3+10/5后序表达式: 1 4 + 3 * 10 5 / +后序表达式的计算:eg:1 4 + 3 * 10 5 / +step1: 1 + 4 => 5new expression: 5 3 * 10 5 / +step2: 5 * 3 => 15new expression: 15 10 5 / +step3: 10 / 5 => 2new expression: 15 2 +step4: 15 + 2 => 17后序表达式的求值:后序表达式的求值和前序表达式⼗分相似,后序表达式是从左⾄右扫描表达式,从左边第⼀个字符开始判断,如果的那个字符是数字继续扫描,如果是运算符,将运算符左边最近的两个数字做运算,结果作为新的字符记录下来。

c语言实现中缀、后缀、前缀表达式相互转化并求值

c语言实现中缀、后缀、前缀表达式相互转化并求值

1.问题描述(1)表达式求值问题表达式是数据运算的基本形式。

人们的书写习惯是中缀式,如:11+22*(7-4)/3 。

中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。

表达式还有后缀式(如:2274-*3/11+)和前缀式(如: + 11 / * 22–7 4 3)。

后缀表达式和前缀表达式中没有括号,给计算带来方便。

如后缀式计算时按运算符出现的先后进行计算。

本设计的主要任务是进行表达式形式的变换及不相同形式的表达式计算。

2.数据结构设计( 1)表达式求值问题由于表达式中有字符与数字两各种类,故定义结点一个标志域 data ,标志结点储藏的为字符 data=2 还是数字 data=1 ,再搜寻结点中对应的储藏地址,读取数字域 data1, 字符域 data2 。

而在前缀表达式时,存在表达式逆序,因表达式种类不一致,用栈逆序极不方便,选择成立双向链表,储藏表达式。

typedef struct Node//定义储藏中缀表达式的结点种类{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2//定义储藏前缀表达式的结点种类{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;3. 运行、测试与解析( 1)表达式求值问题(1)按提示输入中缀表达式,以下列图。

如输入中缀表达式不正确,提示输入有误,如图 , 所示。

图图图(2)选择表达式变换并求值方式。

按“1”选择中缀表达式求值,以下列图。

图(3)按“ 2”选择中缀表达式转变为后缀表达式并求值,以下列图。

图(4)按“ 3”选择中缀表达式转变为前缀表达式并求值,以下列图。

图附录:源代码( 1)表达式求值问题#include<>#include<>#define MAXNUM 100typedef struct Node//定义储藏中缀表达式的结点种类{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2//定义储藏前缀表达式的结点种类{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;typedef int selemtype1;//定义运算数栈的结点typedef struct //定义运算数栈的种类{selemtype1 *base;selemtype1*top; }sqstack1;void InitStack1(sqstack1 &s) //新建一个空运算数栈{=(selemtype1 *)malloc(MAXNUM*sizeof(selemtype1));=;if(! printf("出错:申请空间失败!\n");}void Push1(sqstack1 &s,selemtype1 &e)//运算数栈,入栈:插入元素 e 为新的栈顶元素{ if printf("出错:表达式过长!1\n");*++=e;}void GetTop1(sqstack1 s,selemtype1 &e) //运算数栈,用e返回栈顶元素{e=*;}void Popopnd1(sqstack1 &s,selemtype1 &e) // 运算数栈,退栈:删除栈顶元素,并用 e 返回其值{e=*;}int stackempy1(sqstack1 s) // 运算数栈,若为空栈返回 1,否则返回 0 {if== return 1;else return 0;}typedef char selemtype2;//定义运算符栈的结点种类typedef struct //定义运算符栈种类{selemtype2 *base;selemtype2*top; }sqstack2;void InitStack2(sqstack2 &s) //新建一个空运算符栈{=(selemtype2 *)malloc(MAXNUM*sizeof(selemtype2));=;if(! printf("出错:申请空间失败!\n");}void Push2(sqstack2 &s,selemtype2 &e)//运算符栈,入栈:插入元素 e 为新的栈顶元素{ if printf("出错:表达式过长!2\n");*++=e;}void GetTop2(sqstack2 s,selemtype2 &e) //运算符栈,用e返回栈顶元素{e=*;}void Popopnd2(sqstack2 &s,selemtype2 &e) // 运算符栈,退栈:删除栈顶元素,并用 e 返回其值{e=*;}int stackempy2(sqstack2 s) // 运算符栈,若为空栈返回 1,否则返回 0 {if== return 1;else return 0;}void priority(char c,int &i)//确定运算符优先级{if (c=='*'||c=='/'||c=='%') i=2 ;else if (c=='+'||c=='-') i=1 ;else i=0;}int compare(char a,char b) //比较栈顶元素运算符与外面运算符优先级大小,外面优先级大则返回1,反之返回 0{int in,out;priority(a,in);priority(b,out);if(out>in) return 1;else return 0;}void Operat(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num2);Popopnd1(OPND,num1);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}void Operatqianzhui(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num1);Popopnd1(OPND,num2);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}//后缀表达式求值void houzhuiqiuzhi(Lnode *p,int &e){sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operat(OPND,OPTR);break;default:printf("结点有误 ");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void zhongzhui(Lnode *p)//中缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c,c2;Lnode *first;first=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(!stackempy2(OPTR)||p){while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else { switch(c){case '(': Push2(OPTR,c);break;case ')': GetTop2(OPTR,c2);while(c2!='('){Operat(OPND,OPTR);GetTop2(OPTR,c2);}Popopnd2(OPTR,c2);break;default: GetTop2(OPTR,c2);if(compare(c2,c)) Push2(OPTR,c);else { Operat(OPND,OPTR);Push2(OPTR,c);}break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR))Operat(OPND,OPTR);}Popopnd1(OPND,n);p=first->next;while(p){if(p->data==1) printf("%d ",p->data1);if(p->data==2) printf("%c",p->data2);p=p->next;}printf("=%d ",n);}void houzhui(Lnode*p)//中缀表达式转变为后缀表达式{sqstack2 OPTR; //运算符栈Lnode *r,*q,*head;int n;char c,c2;InitStack2(OPTR);p=p->next;q=(Lnode*)malloc(sizeof(struct Node));head=q;while(p){ switch(p->data){case 1:n=p->data1;r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=1;q->data1=n;break;case 2:c=p->data2; if(stackempy2(OPTR))Push2(OPTR,c); else { switch(c){ case '(': Push2(OPTR,c);break;case ')': Popopnd2(OPTR,c2);while(c2!='('){r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(structNode));q->next=r;q=q->next;q->data=2;q->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;}q->next=NULL;q=head->next;while(q){if(q->data==1) printf("%d ",q->data1);if(q->data==2) printf("%c",q->data2);q=q->next;}houzhuiqiuzhi(head,n);printf("=%d ",n);}void qianzhuiqiuzhi(Lnode2 *p,int &e)//前缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;Lnode2 *head;head=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p!=head){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operatqianzhui(OPND,OPTR);break;default:printf("结点有误 ");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void qianzhui(Lnode *p)//中缀表达式转变为前缀表达式{sqstack2 OPTR; //运算符栈InitStack2(OPTR);int n;char c,c2;Lnode *first;Lnode2 *q,*head,*r,*head2,*s;first=p;p=p->next;q=(Lnode2*)malloc(sizeof(struct Node2));//成立存中缀表达式的双向循环链表head=q;while(p){r=(Lnode2*)malloc(sizeof(struct Node2));q->next=r;r->prior=q;q=q->next;q->data=p->data;q->data1=p->data1;q->data2=p->data2;p=p->next;}q->next=head;head->prior=q;s=(Lnode2*)malloc(sizeof(struct Node2));//成立存前缀表达式的双向循环链表head2=s;while(q!=head){switch(q->data){case 1:n=q->data1;r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=1;s->data1=n;break;case 2:c=q->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else{ GetTop2(OPTR,c2);if(c2==')') Push2(OPTR,c);else{ switch(c){ case ')':Push2(OPTR,c);break;case '(': Popopnd2(OPTR,c2);while(c2!=')'){r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}}break;default:printf("结点有误 ");break;}q=q->prior;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next; s->data=2; s->data2=c2;}s->next=head2;head2->prior=s;while(s!=head2){if(s->data==1) printf("%d ",s->data1);if(s->data==2) printf("%c",s->data2);s=s->prior;}qianzhuiqiuzhi(head2,n);printf("=%d ",n);}int main(){ char n[10];char c;int i,j,k,a,b,z,y,e; Lnode *p,*q,*first;i=0;e=1;a=0;b=1;z=0;y=0;p=(Lnode*)malloc(sizeof(struct Node)); first=p;printf("请输入中缀表达式 ");do{ c = getchar();if('0'<=c&&c<='9'){ n[i]=c;i++;}else{ switch (c){ case '+':case '-':case '*':case '/':case '%':case '(':case ')':case '\n':{ if(n[0]>'0'&&n[0]<='9'){ q=(Lnode*)malloc(sizeof(struct Node));p->next=q;p=p->next;for(k=0;k<i;k++){ for(j=0;j<=i-k-2;j++)e=e*10;a=a+(n[k]-'0')*e;e=1;n[k]='0';}p->data=1;p->data1=a;i=0;a=0;}if(c!='\n'){ if(p->data==2){ if(p->data2!=')'&&c!='(')b=0;}q=(Lnode*)malloc(sizeof(struct Node));p->next=q;p=p->next;p->data=2;p->data2=c;if(c=='(') z++;if(c==')') y++;}}default:if(c!='+'&&c!='-'&&c!='*'&&c!='/'&&c!='%'&&c!='\n'&&c!='('&&c!=')')b=0;}}}while (c != '\n');if(z!=y) b=0;p->next=NULL;if(b==0)printf("输入中缀表达式有误 ");else{printf(" 输入 1 中缀表达式求值,输入 2 后缀表达式求值,输入 3 前缀表达式求值 ");scanf("%d",&b);if(b==1) zhongzhui(first); if(b==2) houzhui(first); if(b==3) qianzhui(first); }return 1;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Stack
* ( +
a b c
Outpu t
* + d e
a+b*c+(d*e+f)*g
11. 读到“+”,弹出“*”并输出,然后将“+”压入栈中。 12.读到f,直接输出。 此时栈和输出的情况如下:
Stack
* ( +
a b c * +d e * f
Outpu t
a+b*c+(d*e+f)*g
Stack
++ a * b c * + * d e f g
Outpu t
任务二:将下列中缀表达式转换为前缀表达式
中缀表达式 前表达式
• 1+((2+3)*4)-5 • a-(b + c/d)*e • a + b*(c + d/e) • a*(b + c)-d
•? •? •? •?
思考
中缀表达式到前缀表达式、 后缀表达式是否还有其他的转换 方法?
Stack
* +
a b c
Outpu t
a+b*c+(d*e+f)*g
6.读到“+”,因为栈顶元素“*”优先级比“+”高,所以弹出“*” 并输出,同理,栈中下一个元素“+”优先级与读到的操作符“+”一样, 所以也要弹出并输出。然后再将读到的“+”压入栈中。
此时栈和输出的情况如下:
Stack
+
a b c
前缀表达式的计算机求值举例
前缀表达式“-*+3456” (1)从右至左扫描,将6、5、4、3压入堆栈; (2)遇到+运算符,因此弹出3和4(3为栈顶元素、4为次顶元素), 计算出3+4的值,得7,再将7入栈;
(3)接下来是*运算符,因此弹出7和5,计算出7*5=35,将35入栈;
(4)最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
• *乘法运算符、/除法运算符、%取余运算符 • +加法运算符、-减法运算符 • 左移运算符、右移运算符 • <、<=、>、>=四种关系运算符 • ==等于运算符、!=不等于运算符 两种关系运算符 • &按位运算符
左结合
左结合
左结合 左结合
左结合
9级
• ^按位异或运算符
左结合
10级
• |按位或运算符
当从左到右顺序扫描完整个中缀表达式后,检测运算符栈,如果非空,则依次弹 栈,将弹出的运算符依次压入到后缀表达式中,最终得到中缀表达式对应的后缀表达 式。
转换过程需要用到栈,具体过程如下
如果遇到操作数,我们就直接将其输出。
如果遇到运算符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
如果遇到一个右括号,则将栈元素弹出,将弹出的运算符输出直到遇到左括号为止。 (注意,左括号只弹出并不输出) 如果遇到任何其他的运算符,如(“+”、“*”、“(”)等,从栈中弹出元素直 到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的运 算符压入到栈中。(需要注意,只有遇到“)”的情况下我们才弹出“(”,其他情况 我们都不会弹出“(”。 如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
* +
Stack
g f e d * + * c b
Outpu t
a+b*c+(d*e+f)*g
14.读到“+”,因为栈顶元素“*”优先级比“+”高,因此,弹出 栈顶元素再入栈。
15.读到a,直接输出。
此时栈和输出的情况如下:
+ +
Stack
g f e d * + * c b * a
Outpu t
a+b*c+(d*e+f)*g
后缀表达式的计算机求值
与前缀表达式类似,只是顺序是从左至右,从左至右扫描 表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出 栈顶的两个数,用运算符对它们做相应的计算,并将结果入栈; 重复上述过程直到表达式最右端,最后运算得出的值即为表达 式的结果。
后缀表达式的计算机求值举例
例如 后缀表达式“34+5*6-” (1)从左至右扫描,将3和4压入堆栈; (2)遇到+运算符,因此,弹出4和3(4为栈顶元素、3为次栈顶元素, 注意与前缀表达式做比较),计算3+4的值,得7,再将7入栈; (3)将5入栈;
将中缀表达式转换为前缀表达式
a+b*c+(d*e+f)*g
1.首先读到g,直接输出。
2.读到“*”,将其放入到栈中。 3.读到“)”,因为栈顶元素“*”优先级比“)”低,所以将“)” 直接压入栈中。 此时栈和输出的情况如下:
Stack
) *
g
Outpu t
a+b*c+(d*e+f)*g
4.读到f,直接输出。 5.读到“+”,直接入栈。 6.读到e,直接输出。 此时栈和输出的情况如下:
Outpu t
* +
a+b*c+(d*e+f)*g
7. 下一个读到的为“(”,它优先级最高,所以直接放入到栈中。 8.读到d,将其直接输出。 此时栈和输出的情况如下:
Stack
( +
a b c
Outpu t
* + d
a+b*c+(d*e+f)*g
9. 读到“*”,由于只有遇到“)”的时候,左括号“(”才会弹 出,所以“*”直接压入栈中。 10.读到e,直接输出。 此时栈和输出的情况如下:
双面运算符
运算所需变量为两 个的运算符叫做双目 运算符。
三目运算符
运算所需变量为三 个的运算符叫做三目 运算符。
+、-、*、/、%、,、>=
?:
前缀表达式的计算机求值
从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇 到运算符,弹出栈顶的两个数,用运算符对它们做相应的计算, 并将结果入栈,重复上述过程直到表达式最左端,最后运算得 出的值即为表达式的结果。
(4)接下来是*运算符,因此,弹出5和7,计算出7*5=35,将35入栈;
(5)将6入栈; (6)最后是-运算符,计算出6-35的值,即-29,由此得出最终结果。
新课讲授
1.中缀表达式转后缀表达式的思想、实例、习题
2. 中缀表达式转前缀表达式的思想、实例、习题
一、中缀表达式转后缀表达式
设置一个运算符栈,如果遇到操作数,则直接将操作数放进后缀表达式中,如果 遇到非操作数,则:如果是左括号,则将左括号入栈;如果是右括号,则从运算符中 将运算符弹栈,放入后缀表达式中,直至栈空或遇到栈中的左括号,并将左括号弹栈; 如果是其他运算符,则比较其优先级与栈中运算符优先级情况,如果栈中的运算符的 优先级大于等于当前运算符,则将栈中运算符弹栈,直至栈空,或栈中运算符优先级 小于当前运算符的优先级,将当前运算符压栈。
第二章 前缀表达式、中缀表达 式、后缀表达式的转换
授课教师:邵红蒙
日期:2018年5月3日
课前复习
1.运算符及其优先级和结合性
2.前缀表达式的计算机求值
3.后缀表达式的计算机求值
运算符及其优先级和结合性
运算符的分类:算术运算符、关系运算符、逻辑运算符、 按位运算符。 运算符的级别:15级。从1级到15级优先级逐渐减低,1 级最高、15级最低。 注意:在表达式求值时,当运算符优先级相同时,根据其 结合性依次计算。
乘后赋值运算符 除后赋值运算符 取模后赋值运算符 左移后赋值运算符
«=
»= &=
^= |=
右移后赋值运算符 按位与后赋值运算符
按位异或后赋值运算符 按位或后赋值运算符
单目运算符
运算所需变量为一 个的运算符叫单目运 算符,又叫一元运算 符。
逻辑非运算符、按位取 反运算符、自增自减运算符、 负号运算符、类型转换运算符、 指针运算符和取地址运算符、 长度运算符。
Stack
+ ) *
g
Outpu t
f
e
a+b*c+(d*e+f)*g
7.读到“*”,因为栈顶元素是“+”优先级比“*”低,所以,直接 入栈。
8.读到d,直接输出。
此时栈和输出的情况如下:
Stack
* + ) *
g
Outpu t
f
e
d
a+b*c+(d*e+f)*g
9.读到“(”,将栈中的操作符依次弹栈,直到遇到“)”。 此时栈和输出的情况如下:
实例
a+b*c+(d*e+f)*g
1.首先读到a,直接输出。 2.读到“+”,将其放入到栈中。 3.读到b,直接输出。 此时栈和输出的情况如下:
Stack
+
a
b
Outpu t
a+b*c+(d*e+f)*g
4.读到“*”,因为栈顶元素“+”优先级比“*”低,所以将“*” 直接压入栈中。 5.读到c,直接输出。 此时栈和输出的情况如下:
左结合 右结合 左结合 左结合
1级
2级 3级 4级 5级 6级 7级 8级
• ()圆括号、[
]下标运算符、->指向结构体成员运算符、. 结构体成员运算符
• !逻辑非运算符、~按位取反运算符、++前缀增量运算符、--前缀减量运算符、-负号运算符、 (类型)类型转换运算符、*指针运算符、&地址运算符、size of长度运算符
相关文档
最新文档