中缀表达式变后缀表达式算法

合集下载

中缀转后缀表达式算法

中缀转后缀表达式算法

中缀转后缀表达式算法
中缀表达式转后缀表达式(也称为逆波兰表达式)是一种将中缀表达式转换为后缀表达式的算法。

它的基本思想是将中缀表达式转换为一个后缀表达式,其中操作符位于操作数之后,而不是操作数之前。

中缀表达式转后缀表达式的算法步骤如下:
1. 从左到右扫描中缀表达式;
2. 如果读取的是操作数,则将其压入堆栈;
3. 如果读取的是运算符,则比较其与栈顶运算符的优先级:
(1)如果栈顶运算符的优先级高于或等于读取的运算符,则将栈顶运算符弹出,并将其压入输出队列;
(2)如果栈顶运算符的优先级低于读取的运算符,则将读取的运算符压入堆栈;
4. 重复步骤2和3,直到表达式末尾;
5. 将栈中所有元素依次弹出,压入输出队列,完成中缀表达式到后缀表达式的转换。

中缀表达式转后缀表达式算法的优点是它可以有效地将中缀表达式转换为后缀表达式,从而简化表达式的计算过程。

它的缺点是它需要记住操作符的优先级,并且需要使用堆栈来存储操作符,这可能会增加算法的复杂度。

总之,中缀表达式转后缀表达式算法是一种有效的算法,它可以有效地将中缀表达式转换为后缀表达式,从而简化表达式的计算过程。

将中缀表达式转换成后缀表达式的三种方法

将中缀表达式转换成后缀表达式的三种方法

将中缀表达式转换成后缀表达式的三种方法中缀表达式是我们平常最常见的表达式形式,但在计算机的运算过程中,我们常常需要将中缀表达式转换成后缀表达式,因为后缀表达式具有易于计算的特点。

那么,接下来我们将介绍三种将中缀表达式转换成后缀表达式的方法。

一、栈的方法这种方法是最常见的一种方法,也是比较易理解的一种方法。

我们可以借助栈来完成中缀表达式转换成后缀表达式的过程。

具体的操作如下:1. 声明一个操作符的栈stack(栈中存放操作符)和一个后缀表达式的列表res(列表中存放转换后的后缀表达式)。

2. 从左到右遍历中缀表达式。

3. 若当前字符为数字,则直接将该数字添加到res中。

4. 若当前字符为左括号“(”,则将其压入stack栈中。

5. 若当前字符为右括号“)”,则依次弹出stack栈中的操作符并加入到res中,直到遇到左括号为止。

6. 若当前字符为操作符,那么则需判断当前操作符与stack栈顶操作符的优先级,若当前操作符的优先级小于等于栈顶操作符,则弹出栈顶操作符并加入到res中,重复此步骤,直到当前操作符大于栈顶操作符优先级,最后将当前操作符压入stack栈。

7. 当遍历完整个中缀表达式后,若stack栈中还有剩余操作符,则依次弹出栈顶操作符并加入到res中。

8. 最终,res中的表达式就是转换后的后缀表达式。

二、递归调用方法这种方法是使用递归的方式来完成。

具体的操作如下:1. 若当前遍历的字符为数字,则直接输出该数字。

2. 若当前遍历的字符为左括号“(”,则递归读取该括号内的表达式。

3. 若当前遍历的字符为右括号“)”,则返回。

4. 若当前遍历的字符为操作符,“x”,“/”,“+”,“-”,则递归调用该表达式右边的操作符,比如“x”,“/”,然后再递归调用左边的操作符,比如“+”,“-”,然后输出左操作数和右操作数,最后输出当前操作符。

5. 最终,输出的表达式即为转换后的后缀表达式。

三、判断法这种方法也是比较常见的一种方法。

数据结构中缀表达式改后缀表达式

数据结构中缀表达式改后缀表达式
例如,整个 表达式的括号要省略,不影响计算顺序括号要省略。 输入形式:
程序从标准输入读入一行字符串,是一个合法的后缀表达式,数字和运 算符之间
由空格分隔。数字可以是带小数部分的浮点数。
输出形式: 向标准输出打印结果,输出只有一行,是转换后的中缀表达式。 并且 : 1、各分量(包括括号)紧密输出,不使用空格进行分隔; 2、在转换后的各运算数的出现顺序不变; 3、浮点数保留输入时的小数位数。
Node p,q,f;
//连接两个链表
if(flag==0) {
printf("错误\n"); exit(0); }
E->Lists[flag-1]->c=ch;
p=E->Lists[flag-1]; f=E->Lists[flag]->next;
while(p->next!=NULL) p=p->next;
*/
#include<stdio.h> #include<stdlib.h>
struct Expression; typedef struct Expression *Node;
struct Expressionlist; typedef struct Expressionlist *Elist;
struct Expression {
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出 栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前 6 张图的栈底的“+”是指中缀 表达式中开头的 9 后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指 “9+(3-1)*3+”中的最后一个“+”。 8. 紧接着数字 10,输出,总表达式变为 9 3 1-3 * + 10。

中缀表达式转后缀表达式---栈--二叉树---四则运算

中缀表达式转后缀表达式---栈--二叉树---四则运算

中缀表达式转后缀表达式---栈--⼆叉树---四则运算 我们平常书写的四则运算表达式属于中缀表达式,形式为"9+(3-1)*3+10/2",因为所有的运算符号都在两操作数之间,所以称为中缀表达式。

我们使⽤中缀表达式来计算表达式的值,不过这种形式并不适合计算机求解。

接下来,我们将中缀表达式转化为后缀表达式,所谓的后缀表达式就是操作符位于操作数后⾯的不包含括号的算数表达式,也叫做逆波兰表达式。

1)⾸先介绍⼀种⼈⼯的转化⽅法()。

以"9+(3-1)*3+10/2"为例,按照运算的规则,找出⾸先计算的部分,这部分包含两个操作数和⼀个操作符,将操作符移动到两个操作数右侧,这就完成了第⼀部分的转换,将这部分看作⼀个操作数,按照运算规则,以相同的⽅法转换,转换过程如下:2)还可以利⽤⼆叉树求得后缀表达式,⾸先利⽤中缀表达式构造⼆叉树,数字是叶⼦节点,操作符为根节点。

每次找到“最后计算”的运算符,作为当前根节点,运算符左侧表达式作为左节点,右侧表达式作为右节点,然后递归处理()。

9+(3-1)*3+10/2对应的⼆叉树的构造过程如下图所⽰: 此⼆叉树做后序遍历就得到了后缀表达式。

对应代码:3)还可以利⽤栈来实现中缀表达式转化为后缀表达式。

转化⽅法如下所述:a.从左向右扫描表达式,如果是数字就输出,否则转b。

b.如果当前扫描的字符是")",则栈顶元素出栈并输出⼀直到栈顶元素为"(",然后删除栈顶元素"(",并不输出。

c.如果扫描的字符或者栈顶元素是“(”,扫描的字符直接⼊栈。

即使扫描的字符是")"也不会⼊栈,因为如果是")",会出栈⾄栈顶元素是"("。

d.如果扫描字符是"+"或者"-",则⼀直出栈⾄栈顶元素为"+"或者"-"或者"("。

中缀表达式转后缀表达式

中缀表达式转后缀表达式

中缀表达式转后缀表达式逆波兰表达式先说⼀下中缀表达式,平时我们使⽤的运算表达式就是中缀表达式,例如1+3*2,中缀表达式的特点就是:⼆元运算符总是置于与之相关的两个运算对象之间⼈读起来⽐较好理解,但是计算机处理起来就很⿇烦,运算顺序往往因表达式的内容⽽定,不具规律性后缀表达式,后缀表达式的特点就是:每⼀运算符都置于其运算对象之后,以上⾯的中缀表达式1+2*3为例⼦,转为后缀表达式就是123*+下⾯先分析怎么把中缀表达式转换为后缀表达式,这⾥我们考虑六种操作符'+'、'-'、'*'、'/'、'('、')',完成中缀转后缀我们需要两个数组,都以栈的⽅式来操作,⼀个数组⽤来存放后缀表达式(char num[100]),⼀个数组⽤来临时存放操作数(char opera[100])(这⾥说临时存放,是因为最后都要⼊栈到后缀表达式数组num中,这个数组就相当于⼀个中转站)1、从左往右扫描中缀表达式(这⾥我们以1*(2+3)为例)2、如果是数字那么将其直接⼊栈到数组num中3、如果是操作数,需要进⼀步判断(1)如果是左括号'('直接⼊栈到数组opera中(2)如果是运算符('+'、'-'、'*'、'/'),先判断数组opera的栈顶的操作数的优先级(如果是空栈那么直接⼊栈到数组opera),如果是左括号那么直接⼊栈到数组opera中,如果栈顶是运算符,且栈顶运算符的优先级⼤于该运算符那么将栈顶的运算符出栈,并⼊栈到数组num中,重复步骤3,如果栈顶运算符优先级⼩于该运算符,那么直接将该运算符⼊栈到opera中(3)如果是右括号')',那么说明在opera数组中⼀定有⼀个左括号与之对应(在你没输错的情况下),那么将opera中的运算符依次出栈,并⼊栈到num中,直到遇到左括号'('(注意左括号不⽤⼊栈到num)4、如果中缀表达式扫描完了,那么将opera中的操作数依次出栈,并⼊栈到num中就可以了,如果没有没有扫描完重复1-3步上⾯就是中缀表达式转后缀表达式的步骤了,下⾯⽤图来直观的了解⼀下这个过程需要注意的是:opera中操作数,越靠近栈顶,优先级越⾼,下⾯附上实现代码View Code后缀表达式的计算完成了中缀表达式转后缀表达式,接下来就是后缀表达式的计算了,后缀表达式的计算⽐中缀转后缀要稍微简单⼀点,只需要对我们转换好的后缀表达式从左往右依次扫描,并依次⼊栈就⾏了,意思是只需要⽤⼀个数组(double num[100])就OK了需要考虑的情况如下1、如果是数字,那么直接⼊栈到num中2、如果是运算符,将栈顶的两个数字出栈(因为我们考虑的运算符加、减、乘、除都是双⽬运算符,只需要两个操作数),出栈后对两个数字进⾏相应的运算,并将运算结果⼊栈3、直到遇到'\0'下⾯⽤⼏张图,来直观了解下这个过程,以上⾯转换好的后缀表达式"123+*"为例(这⾥⽤ss来存储后缀表达式,num来存储计算结果,注意不要与上⾯图中num搞混淆了)(注意:这⾥将计算结果5⼊栈后,栈顶从之前的[3]变成[2])到这⾥后缀表达式的计算就结束了,下⾯附上实现代码[](javascript:void(0)1 #include <stdio.h>2 #include <stdlib.h>34 #define MAX 10056 void JudgeFopen_s(errno_t err); /* 判断⽂件打开是否成功 */7 void ReadFile(FILE *fp, char *ss); /* 读取⽂件内容 */8 double TransformCtoD(char ch); /* 将char类型数组的每⼀个元素转换为double */9 void CalculateAndPush(double *num, int *i, int *j, char mm); /* 计算结果并⼊栈 */1011 int main()12 {13 FILE *fp;14 errno_t err;1516 char ss[MAX]; /* 存储逆波兰表达式 */17 int i = 0;18 int j = 0;19 double num[MAX]; /* 栈 */2021 err = fopen_s(&fp, "E:\\ww.txt", "r");2223 JudgeFopen_s(err); /* 判断⽂件打开是否成功 */24 ReadFile(fp, ss); /* 读取⽂件内容,存储到ss中*/2526 while (ss[i] != '\0')27 {28 if (ss[i] >= '0' && ss[i] <= '9') /* 如果是数字 */29 {30 /* 因为num是char类型的,需要转换为double类型⽅便计算 */31 num[j] = TransformCtoD(ss[i]); /* 将数字存储到栈中 */32 j++;33 i++;34 }35 else if (ss[i] == '+' || ss[i] == '-' || ss[i] == '*' || ss[i] == '/')36 {37 CalculateAndPush(num, &i, &j, ss[i]); /* 计算结果并⼊栈 */38 }39 else if (ss[i] == '\n') /* 如果是换⾏符,结束循环*/40 {41 break;42 }43 }4445 printf("%lf", num[0]);4647 return 0;48 }4950 /* Function: 计算结果并⼊栈 */51 void CalculateAndPush(double *num, int *i, int *j, char mm)52 {53 switch (mm)54 {55 case '+':56 {57 num[(*j)-2] = num[(*j)-1] + num[(*j)-2];58 (*j)--;59 (*i)++;60 break;61 }62 case '-':63 {64 num[(*j)-2] = num[(*j)-1] - num[(*j)-2];65 (*j)--;66 (*i)++;67 break;68 }69 case '*':70 {71 num[(*j)-2] = num[(*j)-1] * num[(*j)-2];72 (*j)--;73 (*i)++;74 break;75 }76 case '/':77 {78 num[(*j)-2] = num[(*j)-1] / num[(*j)-2];79 (*j)--;80 (*i)++;81 break;82 }83 default:84 {85 exit(0);86 }87 }88 }89 /* Function: 判断⽂件打开是否成功 */90 void JudgeFopen_s(errno_t err)91 {92 if (err != 0)93 {94 printf("⽂件打开失败\n");95 system("pause");96 exit(0);97 }98 }99100 /* Function: 读取⽂件内容*/101 void ReadFile(FILE *fp, char *ss)102 {103 int i = 0;104105 while (!feof(fp))106 {107 fscanf_s(fp, "%c", &ss[i]);108 i++;109 }110 ss[i-1] = '\0';111 }112113 /* Function: 将char类型数组的每⼀个元素转换为double */ 114 double TransformCtoD(char ch)115 {116 return (double)(ch - '0');117 }。

中缀转后缀表达式计算报告

中缀转后缀表达式计算报告

目录一、设计思想 (01)二、算法流程图 (02)三、源代码 (04)四、运行结果 (14)五、遇到的问题及解决 (16)六、心得体会 (16)一、设计思想(1)中缀表达式转后缀表达式并计算创建一个数组存储输入的计算表达式。

另创建一个数组储存将要生成的后缀表达式。

创建一个栈储存操作符。

对已存储的表达式数组扫描。

判断当前节点,如果是操作数或’.’,直接加入后缀表达式中,如果是操作符,则比较前一个操作符与当前操作符的优先级。

如果前一个操作符的优先级较高,则将前一个操作符加入后缀表达式中,否则将操作符压入操作符栈。

如果遇到左括号’(’,直接入栈;如果遇到右括号’)’,则在操作符栈中反向搜索,直到遇到匹配的左括号为止,将中间的操作符依次加到后缀表达式中。

当执行完以上操作,发现栈中仍有剩余操作符,则将操作符依次加到后缀表达式中。

此时中缀表达式已经转换成了后缀表达式。

对后缀表达式进行计算。

如果后缀表达式为大于0小于9的字符,则将它转换成浮点型数据并存入数栈中。

如果遇到操作符,则从数栈中提取两个数,进行相应的运算。

依次进行下去,当没有运算符是,运算结束得到最后的结果。

(2)直接表达式求值创建一个数组存储输入的计算表达式。

创建两个栈,一个字符型的栈,一个双精度型的栈。

分别用来存储字符和数。

对已存储的表达式数组扫描。

判断当前节点,如果是操作数和’.’,将字符型的操作数转换为浮点型的数后存入操作数栈。

如果是操作符则判断操作符的优先级。

如果字符栈中已存储符号的优先级小于要存入的字符的优先级,则直接让字符入操作符栈。

如果字符栈中已存储符号的优先级大于或等于要存入的字符的优先级,则取出操作符栈中的一个字符和操作数栈中的两个数进行计算,然后将结果存入操作数栈中,同上进行下去,直到字符栈中已存储符号的优先级小于要存入的字符的优先级时,将操作符存入操作符栈中。

当遇到左括号’(’,将左括号直接存入操作符栈中。

当遇到右括号’)’,则在操作符栈中反向搜索,并且每搜到一个字符就在操作数栈中取两个数进行相应的计算。

(完整版)数学表达式计算(c语言实现)

(完整版)数学表达式计算(c语言实现)

一、设计思想计算算术表达式可以用两种方法实现:1.中缀转后缀算法此算法分两步实现:先将算术表达式转换为后缀表达式,然后对后缀表达式进行计算.具体实现方法如下:(1)中缀转后缀需要建一个操作符栈op和一个字符数组exp,op栈存放操作符,字符数组用来存放转换以后的后缀表达式。

首先,得到用户输入的中缀表达式,将其存入str数组中。

对str数组逐个扫描,如果是数字或小数点,则直接存入exp数组中,当扫描完数值后,在后面加一个#作为分隔符。

如果是操作符,并且栈为空直接入栈,如果栈不为空,与栈顶操作符比较优先等级,若比栈顶优先级高,入栈;如果比栈顶优先级低或相等,出栈将其操作符存到exp数组中,直到栈顶元素优先等级低于扫描的操作符,则此操作符入栈;如果是左括号,直接入栈,如果是右括号,出栈存入exp数组,直到遇到左括号,左括号丢掉。

然后继续扫描下一个字符,直到遇到str中的结束符号\0,扫描结束。

结束后看op栈是否为空,若不为空,继续出栈存入exp数组中,直到栈为空.到此在exp数组最后加结束字符\0。

我们就得到了后缀表达式。

(2)后缀表达式计算此时需要一个数值栈od来存放数值。

对exp数组进行逐个扫描,当遇到数字或小数点时,截取数值子串将其转换成double类型的小数,存入od栈中。

当遇到操作符,从栈中取出两个数,进行计算后再放入栈中。

继续扫描,知道扫描结束,此时值栈中的数值就是计算的结果,取出返回计算结果。

2。

两个栈实现算法此算法需要两个栈,一个值栈od,一个操作符栈op。

将用户输入的数学表达式存入str数组中,对其数组进行逐个扫描。

当遇到数字或小数点,截取数值子串,将其转换成double类型的数值存入od栈中;当遇到左括号,直接入op栈;遇到右括号,op栈出栈,再从值栈od中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到操作符栈栈顶为左括号,将左括号丢掉。

如果遇到操作符,若op栈为空,直接入栈;若栈不为空,与栈顶元素比较优先等级,若比栈顶操作符优先等级高,直接入op栈,如果低于或等于栈顶优先等级,op栈出栈,再从值栈中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到栈顶优先等级低于扫描的操作符等级,将此操作符入op 栈。

论中缀表达式与后缀表达式的转换

论中缀表达式与后缀表达式的转换

论中缀表达式与后缀表达式的转换为了处理方便,编译程序常把中缀表达式首先转换成等价的后缀表达式。

介绍如何使用顺序栈这样一种数据结构实现中缀表达式向后缀表达式的转换。

标签:堆栈;中缀表达式;后缀表达式1 中缀表达式求值首先我们来看一下什么叫作中缀表达式?所谓中缀表达式是指:每个二目运算符在两个运算量的中间。

例如:a+b。

这里假设所讨论的算术运算符包括:+ 、-、*、/和括号()。

根据算术四则运算的规则:先乘除后加减、先括号内再括号外、同级别时先左后右,可以得出运算符的优先级为:()→*、/ →+、-。

如:a+b×c-(d+e)。

我们根据优先级,计算出d+e的值x,再计算出b×c的值y,然后从左到右计算a+x-y。

它的的求值过程为:自左向右扫描表达式,当扫描到a+b时不能马上计算,因为后面可能还有更高的运算。

我们可以用两个栈来处理这样的问题:对象栈s1和算符栈s2。

当自左至右扫描表达式的每一个字符时,若当前字符是运算对象,入对象栈,是运算符时,若这个运算符比栈顶运算符高则入栈,继续向后处理,若这个运算符比栈顶运算符低则从对象栈出栈两个运算量,从算符栈出栈一个运算符进行运算,并将其运算结果入对象栈,继续处理当前字符,直到遇到结束符。

2 后缀表达式求值所谓后缀表达式,是指运算符在运算对象之后。

在后缀表达式中,不再引入括号,所有的计算按运算符出现的顺序,严格从左向右进行,而不用再考虑运算规则和级别。

例如:abcd/-e*+。

从左向右,首先计算/,即c/d的值x,然后计算b-x的值y,再计算y*e的值z,最后计算a+z。

计算一个后缀表达式,算法上比计算一个中缀表达式简单的多。

这是因为表达式中即无括号又无优先级的约束。

具体做法:只使用一个对象栈,当从左向右扫描表达式时,每遇到一个操作数就送入栈中保存,每遇到一个运算符就从栈中取出两个操作数进行当前的计算,然后把结果再入栈,直到整个表达式结束,这时送入栈顶的值就是结果。

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

❖lf((x1=gettopqstack(s))==NIL) ・:・exit(O);
❖while(1)
•if(x2!='+'&& x2!='・'&& x2!=*&&
x2!=7'&& x2!=t(t && x2!=')' && x2!='#') •{ printf("% c",x2);
•x2=expression[++j];
•:・)
・:♦else if(proceed(x1,x2)==t<t) ・:・{if(!pushqstack(s,x2))
・:・e xit(O);
・:・if((x1=gettopqstack(s))==NIL) ・:・e xit(O);
♦x2= expression[++j];
•:・)
♦else if(proceed(x1,x2)==t>t)
♦{if((x=popqstack(s))==NIL)
・:・exit(O);
❖printf("%c”,x);
❖if((x1 =gettopqstack(s))==NIL)
・:・exit(O);
.:・}
❖else if(proceed(x1 ,x2)==-{&& x仁'('&& x2=')')
❖{if(popqstack(s)==NIL)
・:・exit(O);
❖if((x1 =gettopqstack(s))==NIL)
・:・exit(O);
•x2= expression[++j];
.:・}
•else if(proceed(x1 ,x2)==-c&& x仁# && x2=#)
•{ return 1;
.:・)
•else if(proceed(x1,x2)==c')
•break;
・:・}
•Printf(An错误!” );
•return 0;
•:・proceed(x1,x2)完成算符比较功能•char proceed(char x1 ,char x2)
❖Midstring[0]=x2;
・:・midstring[1]=t\0,;
•:・if(((x1=='+'||x1='・')&&strstr("+・)#,,,midstring)!=NULL||
((x1=*||x 仁'/')&&strstr("+・*/)#”,midstring)!=NULL)
||(x1 ==')')&&strstr("+・
*/)#”,midstring)!=NULL)) .:・{
❖result。

';
❖Else if((x1==t&&x2==y)|| ❖(x1==*&& x2=#))・:.{
❖result—;
.:・)
❖Else if((x1 ='('&& x2==#)|| ❖(x1==t),&& x2=t(,)|| •:・(x1==t#,&&x2==t)>)) ❖{ result^'
❖Return result;
.:・}
•:•主函数如下:
"include <stdio.h>
❖#include <string.h>
❖#include<stdlib.h>
❖#define MAXNUM 100
❖#define NIL 0
• typedef char elemtype; •Typedef struct
.:・{
・:・elemtype stack[MAXNUM]; •int top;
•)qstype;
❖elemtype gettopqstack(qstype *s);
❖char proceed(char x1 ,char x2);
❖Int postfix(qstype *s,char ^expression); ❖main()
・:.{
❖char expression[80]={tt A+(B-C/D)*E,}; ❖qstype s;
❖printf(t,\n,^);
• Postfix(&s,strcat(expression,"#"));
・:.}
•char result;
•char midstring[2];
•result*’;
•void initiateqstack(qstype *s);
•int pushqstack(qstype*s,elemtype x); •elemtype popqstack(qstype *s);。

相关文档
最新文档