数据结构之中缀表达式转后缀表达式
中缀转后缀表达式
中缀转后缀表达式中缀表达式是我们平时最常见的表达式形式,例如:1 + 2 * 3。
但是在计算机中,我们更常使用后缀表达式来进行计算。
因此,将中缀表达式转换为后缀表达式是非常重要的。
一、中缀表达式中缀表达式是指运算符位于两个操作数之间的表达式。
例如:1 + 2 * 3。
在中缀表达式中,运算符的优先级是由括号来确定的。
括号内的表达式优先计算,同级别的运算符按照从左到右的顺序计算。
二、后缀表达式后缀表达式是指运算符位于两个操作数之后的表达式。
例如:1 2 3 * +。
在后缀表达式中,运算符的优先级是由运算符本身来确定的。
同级别的运算符按照从左到右的顺序计算。
三、中缀转后缀中缀表达式转换为后缀表达式的过程可以使用栈来实现。
具体步骤如下:1. 初始化两个栈:运算符栈和结果栈。
2. 从左到右扫描中缀表达式。
3. 如果遇到操作数,直接将其压入结果栈。
4. 如果遇到运算符,比较其与运算符栈栈顶的优先级。
5. 如果运算符栈为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈。
6. 否则,若优先级比栈顶运算符的优先级高或相等,也将运算符压入运算符栈。
7. 否则,将运算符栈顶的运算符弹出并压入结果栈中,再次转到步骤4与新的栈顶运算符比较。
8. 如果遇到括号,如果是左括号“(”,则直接压入运算符栈;如果是右括号“)”,则依次弹出运算符栈顶的运算符,并压入结果栈中,直到遇到左括号为止,此时将这一对括号丢弃。
9. 重复步骤2至8,直到表达式的最右边。
10. 将运算符栈中剩余的运算符依次弹出并压入结果栈中。
11. 最后将结果栈中的元素依次弹出,即可得到后缀表达式。
四、总结中缀表达式转换为后缀表达式是一个非常重要的算法,它可以使我们更方便地进行计算。
在实际应用中,我们可以使用栈来实现这个算法。
通过这个算法的学习,我们可以更深入地理解计算机中的表达式计算过程。
中缀转后缀表达式算法
中缀转后缀表达式算法
中缀表达式转后缀表达式(也称为逆波兰表达式)是一种将中缀表达式转换为后缀表达式的算法。
它的基本思想是将中缀表达式转换为一个后缀表达式,其中操作符位于操作数之后,而不是操作数之前。
中缀表达式转后缀表达式的算法步骤如下:
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 }。
数据结构之中缀表达式转后缀表达式
return NULL;
}
S->Next = NULL;
MakeEmpty(S);
return S;
}
//清空栈
void MakeEmpty(Stack S)
{
if(S == NULL)
{
printf("Use CreateStack First!");
{
return 3;
}
else
{
fprintf(stderr,"Input char is invalid!\n");
return -1;
}
}
/****************************************************************
*判断一个字符是不是运算符
*如果是合法的运算符+、-、*、/、(、)则返回0,否则返回1
}
else
{
while(!IsEmpty(S))
{
Pop(S);
}
}
}
//进栈
void Push(ElementType X,Stack S)
{
PtrToNode Tmp;
Tmp = malloc(sizeof(struct Node));
if(Tmp != NULL)
{
Tmp->Element = X;
遇到a,直接输出:
遇到+,此时栈为空,入栈:
遇到b,直接输出:
遇到*,优先级大于栈顶符号优先级,入栈:
遇到c,输出:
遇到+,目前站内的*与+优先级都大于或等于它,因此将栈内的*,+依次弹出并且输出,并且将遇到的这个+入栈:
中缀转后缀数据结构
将中缀表达式转换为后缀表达式需要使用栈数据结构。
具体步骤如下:1. 读入中缀表达式,遇到数字时将其输出,遇到左括号时将其压入栈中。
2. 读入运算符,如果该运算符优先级高于栈顶运算符的优先级,则将栈顶元素弹出并输出,直到遇到优先级更高的运算符或遇到右括号为止。
3. 如果该运算符优先级等于栈顶运算符的优先级,则将该运算符压入栈中。
4. 如果该运算符优先级低于栈顶运算符的优先级,则忽略该运算符。
5. 重复上述步骤,直到读完整个中缀表达式。
6. 将栈中的元素依次弹出并输出,即为转换后的后缀表达式。
例如,对于中缀表达式a + b * c + (d * e + f) * g,其转换成后缀表达式的步骤如下:1. 读到a,直接输出。
2. 读到+,将+ 压入栈中。
3. 读到b,直接输出。
4. 读到*,将* 压入栈中。
5. 读到c,直接输出。
6. 读到+,将栈顶的* 弹出并输出,然后将+ 压入栈中。
7. 读到(,将( 压入栈中。
8. 读到d,直接输出。
9. 读到*,将* 压入栈中。
10. 读到e,直接输出。
11. 读到+,将栈顶的* 弹出并输出,然后将+ 压入栈中。
12. 读到f,直接输出。
13. 读到),将栈顶的+ 弹出并输出,直到遇到左括号为止。
此时右括号")" 的优先级最高,所以直接将其弹出并输出。
然后继续弹出并输出左括号"(" 前遇到的运算符和操作数,直到遇到右括号为止。
此时右括号")" 前已经没有运算符和操作数了,所以直接将其弹出并输出。
14. 读到*,将* 压入栈中。
15. 读到g,直接输出。
16. 中缀表达式已经读完,将栈中的元素依次弹出并输出,得到后缀表达式a b * c + d * e + f * g + 。
中缀表达式转后缀表达式
中缀表达式转后缀表达式 先看⼏个中缀表达式和它们对应的后缀表达式的例⼦ 可以看到操作数a, b, c 在中缀表达式中的顺序和在后缀表达式中的顺序是⼀致的,但操作符的顺序可能不⼀致,因为在中缀表达式中操作符有优先级,括号也能改变运算的优先级,这些都要在后缀表达式中体现出来,后缀表达式中没有括号。
那怎么转化呢? 1,创建⼀个变量,初始化为空的字符串,来表⽰要完成的后缀表达式,创建⼀个字符栈,⽤来存储操作符 2,从左向右依次扫描中缀表达式, 遇到操作数,直接加到后缀表达式的后⾯,因为,在中缀表达式和后缀表达式中,操作数的顺序是⼀样的, 遇到操作符,要先存起来,存到栈中,因为操作符有优先级,它要和后⾯的操作符⽐较优先级,然后才能决定把它放到什么哪个位置。
如果栈为空,直接把操作符放⼊栈中 如果栈不为空,⽐较优先级。
如果遇到的操作符⽐栈顶中的操作符优先级⾼,把遇到的操作符放⼊栈中。
如果遇到的操作符和栈顶操作符的优先级相等,这要考虑操作符的结合性,它是从左到右结合,还是从右到左结合。
从左到右接合,就是操作数属于它前⾯的操作符⽽不是它后⾯操作符。
+, - , * , / 就是从左向右结合,⽐如a-b+c中的b 是-的操作数,⽽不是+的操作数,整个表达式,也是从左向右计算的。
从右向左结合,操作数属于它前⾯的操作符⽽不是它后⾯操作符,⽐如阶乘。
a ^ b ^ c, b是第⼆个^的操作数,⽽不是第⼀个^的操作数,整个表达式也是从右向左计算,a ^ (b ^ c)。
如果从左向右接合,那就弹栈,把操作符放到后缀表达式中,如果从右向左结合,则把遇到的操作符放⼊栈中(和优先级⾼的情况⼀致) 如果遇到的操作符⽐栈顶中的操作符优先级低,那就弹栈,把操作符放到后缀表达式中 遇到(,放到字符栈,因为要等到)才能知道怎么操作。
遇到),依次从字栈中弹栈,放到后缀表达式中,直到遇到(, 遇到(, 要把它弹栈,然后舍弃掉。
3,循环完毕,如果字符栈中还有操作符,依次弹栈放到后缀表达式中,最终栈为空,得到完整的后缀表达式。
中缀式和后缀式的相互转换
中缀式和后缀式的相互转换中缀式和后缀式是数学表达式的两种常见表示方式。
中缀式是我们常见的表达式形式,例如"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"。
算法笔记--中缀表达式转后缀表达式后缀表达式计算
算法笔记--中缀表达式转后缀表达式后缀表达式计算中缀表达式转后缀表达式规则中缀表达式a + b*c + (d * e + f) * g,转换成后缀表达式则为a b c * + d e * f + g * +转换过程需要⽤到栈,具体过程如下:1 如果遇到操作数,我们就直接将其输出。
2 如果遇到操作符,则我们将其放⼊到栈中,遇到左括号时我们也将其放⼊栈中。
3 如果遇到⼀个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为⽌。
注意,左括号只弹出并不输出。
4 如果遇到任何其他的操作符,如+, *, (等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为⽌。
弹出完这些元素后,才将遇到的操作符压⼊到栈中。
有⼀点需要注意,只有在遇到 )的情况下我们才弹出( ,其他情况我们都不会弹出( 。
即:若操作符op的优先级⾼于栈顶操作符的优先级,则压⼊操作符栈若操作符op的优先级⼩于等于栈顶操作符的优先级,则将操作栈的操作符不断弹出到后缀表达式中,直到op的优先级⾼于栈顶操作符的优先级5 如果我们读到了输⼊的末尾,则将栈中所有元素依次弹出。
实例a +b *c + (d *e + f) * g1. ⾸先读到a,直接输出。
2. 读到“+”,将其放⼊到栈中。
3. 读到b,直接输出。
此时栈和输出的情况如下:4. 读到“*”,因为栈顶元素"+"优先级⽐" * " 低,所以将" * "直接压⼊栈中。
5. 读到c,直接输出。
此时栈和输出情况如下:6. 读到" + ",因为栈顶元素" * "的优先级⽐它⾼,所以弹出" * "并输出,同理,栈中下⼀个元素" + "优先级与读到的操作符" + "⼀样,所以也要弹出并输出。
然后再将读到的" + "压⼊栈中。
中缀表达式转后缀表达式最难例题
中缀表达式转后缀表达式最难例题以下是一个较复杂的中缀表达式转后缀表达式的示例:中缀表达式:(3+4*2)/(1-5)^2^3后缀表达式:342*+15-23^^/首先,我们可以使用运算符优先级来决定操作符的顺序。
一般来说,乘法和除法的优先级最高,然后是加法和减法,最后是幂运算。
在同一优先级下,操作符从左到右处理。
接下来,我们使用一个栈来辅助转换。
按照从左到右的顺序扫描中缀表达式:1. 如果遇到数字,直接将其添加到后缀表达式中。
2. 如果遇到运算符,首先将栈顶的运算符与当前运算符进行优先级比较:- 如果栈为空,或者栈顶运算符为左括号"(",则将当前运算符直接入栈。
- 如果当前运算符的优先级高于栈顶运算符,则将当前运算符入栈。
- 如果当前运算符的优先级低于或等于栈顶运算符,则将栈顶运算符弹出并添加到后缀表达式中,然后继续比较当前运算符与新的栈顶运算符的优先级,直到当前运算符可以入栈。
3. 如果遇到左括号"(",直接将其入栈。
4. 如果遇到右括号")",则将栈顶运算符弹出并添加到后缀表达式中,直到遇到左括号"("。
注意,左括号"("只弹出并丢弃,不添加到后缀表达式中。
5. 最后,如果中缀表达式扫描完成,但栈中仍有运算符,则依次弹出并添加到后缀表达式中。
根据上述规则,将中缀表达式“(3+4*2)/(1-5)^2^3”转换为后缀表达式的过程如下:中缀表达式: (3+4*2)/(1-5)^2^3后缀表达式:遍历字符"(",将其入栈。
中缀表达式: 3+4*2)/(1-5)^2^3后缀表达式:遍历数字"3",将其添加到后缀表达式中。
中缀表达式: +4*2)/(1-5)^2^3后缀表达式: 3遍历字符"+",将其入栈。
中缀表达式: 4*2)/(1-5)^2^3后缀表达式: 3遍历数字"4",将其添加到后缀表达式中。
中缀表达式转后缀表达式详解
中缀表达式转后缀表达式详解中缀表达式和后缀表达式是两种常见的数学表达式形式。
中缀表达式是我们通常使用的表达式形式,即运算符位于操作数的中间,例如:'2 + 3'。
而后缀表达式(也称为逆波兰表达式)是一种更为简洁和易于计算机处理的表达式形式,其中运算符位于操作数的后面,例如:'2 3 +'。
将中缀表达式转换为后缀表达式的主要目的是减少表达式的复杂性,使其更容易被计算机处理。
转换过程涉及使用栈来保存运算符,并按照一定的规则重新排列表达式中的元素。
下面是将中缀表达式转换为后缀表达式的步骤:1. 创建一个空栈和一个空列表,用于保存转换后的后缀表达式。
2. 从左到右遍历中缀表达式的每个元素。
3. 如果遇到操作数(数字),将其添加到后缀表达式列表中。
4. 如果遇到左括号'(',将其推入栈中。
5. 如果遇到操作符,比较其与栈顶操作符的优先级。
a. 如果栈为空或栈顶为左括号'(',则将操作符推入栈中。
b. 如果操作符的优先级大于栈顶操作符的优先级,将其推入栈中。
c. 如果操作符的优先级小于或等于栈顶操作符的优先级,将栈顶操作符弹出并添加到后缀表达式列表中,然后将操作符推入栈中。
6. 如果遇到右括号')',将栈中的操作符弹出并添加到后缀表达式列表中,直到遇到左括号'('。
注意,左右括号不会被添加到后缀表达式中。
7. 当中缀表达式遍历完毕后,将栈中剩余的操作符依次弹出并添加到后缀表达式列表中。
8. 后缀表达式列表即为转换后的后缀表达式。
例如,将中缀表达式 '2 + 3 * 4' 转换为后缀表达式的步骤如下:中缀表达式:2 + 3 * 4后缀表达式列表(初始为空):[]遍历中缀表达式的每个元素:1. 遇到操作数2,添加到后缀表达式列表中:[2]2. 遇到操作符+,将其推入栈中:[+]3. 遇到操作数3,添加到后缀表达式列表中:[2, 3]4. 遇到操作符*,将其推入栈中:[+, *]5. 遇到操作数4,添加到后缀表达式列表中:[2, 3, 4]6. 中缀表达式遍历完毕,将栈中剩余的操作符弹出并添加到后缀表达式列表中:[2, 3, 4, *]最终转换后的后缀表达式为:'2 3 4 * +'后缀表达式的计算可以通过遍历列表中的元素来完成。
数据结构实验——中缀表达式向后缀表达式的转化(包括四则运算和幂运算)——详细注释
//处理加减
else if(temp->ch=='+'||temp->ch=='-')
{
pointer=plus_minus(stack);//加减时先考虑优先级低的
if(pointer==NULL)
{
pointer=power(stack,tail);
freenode=stack;
stack=stack->next;
free(freenode);
}
printf("%c",stack->ch);
stack->ch=temp->ch;
}
}
//处理括号
else if(temp->ch=='('||temp->ch==')')
{
if(temp->ch=='(')
{
temp->next=stack;
stack=temp;
temp=(hi*)malloc(sizeof(hi));
// tail->next=NULL;
}
else if(temp->ch)
{
pointer=sign(stack);
')
{
//处理幂运算
if(temp->ch=='^')//如果是幂运算符就直接压栈
【Java数据结构】中缀表达式转后缀表达式,后缀表达式的计算(多位数)
【Java数据结构】中缀表达式转后缀表达式,后缀表达式的计算(多位数)中缀表达式转后缀表达式,后缀表达式的计算(多位数)中缀表达式转后缀表达式思路(1)初始化两个栈stack1与stack2,分别存储数和操作符(2)从左到右扫描中缀表达式(3)遇到数字时,直接将其压⼊stack1中(4)遇到操作符时,先进性⽐较优先级,如果优先级⽐栈顶元素的⾼,则直接⼊栈如果优先级⽐栈顶元素的低,则将栈顶元素弹出压⼊数栈,再将操作符与栈顶重复⽐较,直到可以⼊栈如果符号栈为空或者栈顶是左括号(,则直接⼊栈如果操作符是右括号),则将操作符依次出栈放⼊数栈中,直到遇到左括号,⼆者直接丢弃(5)扫描完成,将操作符栈stack2依次出栈并压⼊stack1中后缀表达式计算器思路(1)初始化⼀个栈(2)遇到数字时,直接将数字压⼊栈(3)遇到运算符时,将栈顶的两个数弹出,并且计算,将结果⼊栈Java代码如下1import java.util.ArrayList;2import java.util.Deque;3import java.util.LinkedList;4import java.util.List;56public class Main {7public static void main(String[] args) {8 String str ="11+(2*4)+3*(61-1)";//结果为11+8+180=1999//将字符串转成list10 List<String> List = toInfixExpressionList(str);11 System.out.println(List);12//中缀表达式转后缀表达式13 List<String> suffixList = prefixToSuffix(List);14 System.out.println(suffixList);15//计算后缀表达式的结果16 System.out.println("后缀表达式的计算结果为:"+toCalculation(suffixList));17 }1819/**20 * 将表达式每⼀个部分转换成list21 * @param str 计算表达式22 * @return List23*/24public static List<String> toInfixExpressionList(String str){25 List<String> list = new ArrayList<>(str.length());26int i = 0;//⽤于遍历表达式的指针27char c;//⽤于存储每⼀个遍历到的字符28 StringBuilder s;//⽤于多位数的拼接29while (i<str.length()){30 c = str.charAt(i);31//如果是⾮数字,直接加⼊到list32if(c < 48 || c > 57){33 list.add(""+c);34 i++;35 }else {36 s = new StringBuilder();37while (c >= 48 && c <= 57){38 s.append(c);39 i++;40 c = str.charAt(i);41 }42 list.add(s.toString());43 }44 }45return list;46 }4748/**49 * 计算后缀表达式50 * @return计算结果51*/52public static Integer toCalculation(List<String> list){53 Deque<String> stack = new LinkedList<>();54for(String item: list){55if(isNumeric(item)){56 stack.push(item);57 }else {58int x = Integer.parseInt(stack.pop());59int y = Integer.parseInt(stack.pop());60switch (item){61case "+":62 stack.push((y+x)+"");63break;64case "-":65 stack.push((y-x)+"");66break;67case "*":68 stack.push((y*x)+"");69break;70case "/":71 stack.push((y/x)+"");72break;73default:74throw new RuntimeException("输⼊错误!");75 }76 }77 }78return Integer.parseInt(stack.pop());79 }8081/**82 * 中缀表达式转后缀表达式83 * @return List84*/85public static List<String> prefixToSuffix(List<String> list){86//初始化两个栈,stack1为数栈,stack2为操作符栈87 List<String> stack1 = new ArrayList<>();88 Deque<String> stack2 = new LinkedList<>();89for(String item: list){90if(isNumeric(item)){91//数字直接⼊栈92 stack1.add(item);93 }else if(item.equals("(")) {94//左括号或者空直接⼊栈95 stack2.push(item);96 }else if(item.equals(")")){97//右括号将符号栈中左括号前的所有符号⼊数栈98while (!stack2.peek().equals("(")){99 stack1.add(stack2.pop());100 }101 stack2.pop();//清除括号102 }else if(stack2.peek()==null||judgePriority(item)>judgePriority(stack2.peek())){ 103//优先级⽐栈顶元素⾼,直接⼊栈104 stack2.push(item);105 }else {106//优先级⽐栈顶元素低或者相等,将栈顶优先级⾼的⼊数栈107while (stack2.peek()!=null&&judgePriority(stack2.peek())<=judgePriority(item)){ 108 stack1.add(stack2.pop());109 }110 stack2.push(item);111 }112 }113while (stack2.peek()!=null){114 stack1.add(stack2.pop());115 }116117return stack1;118 }119120/**121 * 返回运算符优先级,加减为1,乘除为2122 * @param str 运算符123 * @return优先级124*/125public static int judgePriority(String str){126switch (str){127case "+":128return 1;129case "-":130return 1;131case "*":132return 2;133case "/":134return 2;135case "(":136return 0;137case ")":138return 0;139default:140throw new RuntimeException("输⼊有误!"+str); 141 }142 }143144/**145 * 判断字符串是否是正整数146 * @param str 字符串147 * @return boolean148*/149public static boolean isNumeric(String str){150for (int i = str.length();--i>=0;){151if (!Character.isDigit(str.charAt(i))){152return false;153 }154 }155return true;156 }157 }。
练手系列(3)中缀表达式转后缀表达式
练⼿系列(3)中缀表达式转后缀表达式 最近在看数据结构和算法时,看到了中缀表达式和后缀表达式,感觉蛮有意思的,于是⾃⼰实现了⼀下,算是⼀种锻炼。
①⾸先,中缀表达式就是我们平时见惯了的算术式,⽐如:5+3这样的就是中缀表达式,⽽后缀表达式呢,就是53+这样的。
因为转为后缀表达式后,算术式的计算会相对简单⼀些,可以⽤栈来实现。
分析图如下:这种后缀表达式计算的最⼤的优点就是不⽤知道什么优先级。
②好,下⾯我们来看⼀下怎么从中缀表达式(5+3)变为后缀表达式(53+):好了,以上两张图⽚就是后缀表达式的相关分析。
下⾯上具体代码:1import java.util.Stack;23public class Calculate {4// 定义操作符号5private static final char PLUS = '+';6private static final char MINUS = '-';7private static final char MULTIPLY = '*';8private static final char DIVIDE = '/';9private static final char LEFT_PARENTHESIS = '(';10private static final char RIGHT_PARENTHESIS = ')';1112public static void main(String[] args) {13 String infix = "(3+(2-1))*5";14 String postfix = convert(infix);15 System.out.println(postfix);16 analysePostfix(postfix);17 }1819// 计算后缀表达式20public static void analysePostfix(String postfix) {21 Stack<Double> stack = new Stack<Double>();22char[] chs = postfix.toCharArray();23for (int i = 0; i < chs.length; i++) {24if (chs[i] != PLUS && chs[i] != MINUS && chs[i] != MULTIPLY25 && chs[i] != DIVIDE) {26// 如果读取到的是数字,则加到栈中27 stack.push(Double.valueOf(String.valueOf(chs[i])));28 } else {29// 如果读取到的是操作符,则从栈中弹出两个数字,并执⾏运算30double b = (double) stack.pop();31double a = (double) stack.pop();32char operator = chs[i];33double result = calculate(a, b, operator);34 stack.push(result);35 }36 }37 System.out.println("result is : " + stack.pop());38 }3940public static double calculate(double a, double b, char operator) {41switch (operator) {42case PLUS:43return a + b;44case MINUS:45return a - b;46case MULTIPLY:47return a * b;48case DIVIDE:49return a / b;50 }51return 0;52 }5354// 中缀到后缀的转换55public static String convert(String infix) {56 Stack<Character> vector = new Stack<Character>();57char[] chs = infix.toCharArray();58 StringBuffer postfix = new StringBuffer();59for (int i = 0; i < chs.length; i++) {60// 如果是数字,直接插⼊表达式中61if (chs[i] != PLUS && chs[i] != MINUS && chs[i] != MULTIPLY62 && chs[i] != DIVIDE && chs[i] != LEFT_PARENTHESIS63 && chs[i] != RIGHT_PARENTHESIS) {64 postfix.append(String.valueOf(chs[i]));65 } else {66// 如果是左括号,直接压⼊栈中67if (LEFT_PARENTHESIS == chs[i]) {68 vector.push(chs[i]);69continue;70 }71// 如果是右括號,則去除棧裏⾯的左括號之上的所有操作符號72if (RIGHT_PARENTHESIS == chs[i]) {73while (LEFT_PARENTHESIS != vector.peek()) {74 postfix.append(vector.pop());75 }76 vector.pop();77 }78// 如果当前读到的操作符和栈⾥⾯的操作符⼀样,那么直接加到后缀表达式中 79if (vector.size() > 0 && chs[i] == vector.peek()) {80 postfix.append(String.valueOf(chs[i]));81 } else if (vector.size() == 0 || chs[i] != vector.peek()) {82// 如果是乘号或者除号,直接压⼊栈中83if (MULTIPLY == chs[i] || DIVIDE == chs[i]) {84 vector.push(chs[i]);85 }86if (PLUS == chs[i] || MINUS == chs[i]) {87if (vector.size() > 088 && (vector.peek() == MULTIPLY || vector.peek() == DIVIDE)) {89 postfix.append(vector.pop().toString());90 vector.push(chs[i]);91 } else {92 vector.push(chs[i]);93 }94 }95 }96 }97// 如果已经读完了中缀表达式,则弹出栈中所有操作符并加⼊到后缀表达式中 98if (i == chs.length - 1) {99for (int j = vector.size(); j > 0; j--) {100 postfix.append(vector.pop().toString());101 }102 }103 }104return postfix.toString();105 }106 }。
数据结构中缀式中缀表达式改后缀表达式并求值
《数据结构》课程设计报告课程设计题目:中缀表达式改后缀表达式并求值一. 实验目的·掌握栈的特征及基本操作,如入栈、出栈等,栈的顺序存储结构和链式存储结构的实现,以便在实际问题中灵活应用。
·掌握栈的典型应用——中缀表达式转后缀表达式,并利用后缀表达式求值。
二. 实验内容(一)中缀表达式转后缀表达式的方法:1.遇到操作数:直接输出(添加到后缀表达式中)2.栈为空时,遇到运算符,直接入栈3.遇到左括号:将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈6.最终将栈中的元素依次出栈,输出。
(二)三. 实验分析程序源码(要求对每个函数及主要代码加上注释语句),源码出处。
//// main.c// 后缀表达式求值//// Created by 颜彦闻on 14/12/2.// Copyright (c) 2014年颜彦闻. All rights reserved.//#include <stdio.h>#include <stdlib.h>#define StackSize 100#define QueueSize 100typedef char DataType;typedef struct{char data[100];int front,rear;}SeqQueue; //定义队列类型void InitQueue(SeqQueue *Q) //初始化队列{Q->front=0;Q->rear=0;}int QueueEmpty(SeqQueue Q) //判空{return Q.rear==Q.front;}void EnQueue(SeqQueue *Q,DataType x) //元素入队列函数{if((Q->rear+1)%QueueSize==Q->front)printf("Queue overflow");else{Q->data[Q->rear]=x;Q->rear=(Q->rear+1)%QueueSize;}}DataType DeQueue(SeqQueue *Q){char x;if(QueueEmpty(*Q))return0;else{x=Q->data[Q->front];Q->front=(Q->front+1)%QueueSize;return x;}}//栈的相关操作typedef struct{DataType data[100];int top;}SeqStack;void InitStack(SeqStack *S) //栈的初始化{S->top=-1;}void Push(SeqStack *S,DataType x) //进栈函数{if(S->top==StackSize-1)printf("stack overflow");else{S->top=S->top+1;S->data[S->top]=x;}}DataType Pop(SeqStack *S) //退栈顶指针函数{if(S->top==-1){printf("stack underflow");return0;}elsereturn S->data[S->top--];}DataType GetTop(SeqStack S) //取栈顶元素{if(S.top==-1){printf("stack empty");return0;}elsereturn S.data[S.top];}int Priority(DataType op) //求运算符优先级函数{switch(op){case'(':case'#':return0;case'-':case'+':return1;case'*':case'/':return2;}return -1;}void CTPostExp(SeqQueue *Q){SeqStack S;char c,t;InitStack(& S);Push(&S,'#');do{c=getchar();switch(c){case' ':break;case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':EnQueue(Q ,c);break;case'(':Push(&S,c);break;case')':case'#':{do{t=Pop(&S);if(t!='('&&t!='#')EnQueue(Q ,t);}while(t!='('&&S.top!=-1);break;}case'+':case'-':case'*':case'/':while(Priority(c)<=Priority(GetTop(S))){t=Pop(&S);EnQueue(Q,t);}Push(&S,c);break;}}while(c!='#');}DataType CPostExp(SeqQueue Q){SeqStack S;char ch;int x,y;InitStack(&S);while(!QueueEmpty(Q)){ch=DeQueue(&Q);if(ch>='0'&&ch<='9')Push(&S,ch);else{y=Pop(&S)-'0';x=Pop(&S)-'0';switch(ch){case'+': Push(&S,(char)(x+y+'0'));break;case'-': Push(&S,(char)(x-y+'0'));break;case'*': Push(&S,(char)(x*y+'0'));break;case'/': Push(&S,(char)(x/y+'0'));break;}}}return GetTop(S);}int main(int argc, char *argv[]){SeqQueue Q;InitQueue(&Q);printf("输入表达式:\n");CTPostExp(&Q);printf("结果:%c\n",CPostExp(Q));printf("后缀表达式:");while(!QueueEmpty(Q))printf("%2c",DeQueue(&Q));printf("\n");system("PAUSE");return0;}四. 算法时间复杂度。
中缀表达式转后缀表达式的方法
中缀表达式转后缀表达式的方法中缀表达式是我们日常数学运算中最常用的表达方式,它是以操作符放在两个操作数之间的形式表示算式的。
例如,2+3就是一个中缀表达式。
但是在计算机程序中,中缀表达式存在着很多问题,我们需要把它转换成后缀表达式来方便计算机程序的处理。
本文将介绍中缀表达式转换成后缀表达式的方法。
一、什么是后缀表达式后缀表达式是一种更加容易计算机处理的表达方式,它就是把中缀表达式中的每个操作符放到操作数之后。
例如,2+3变成2 3+,3*4+5变成3 4*5+。
后缀表达式没有括号,更加简洁明了。
这种表达方式被广泛应用在计算器、编译器等领域。
二、为什么需要把中缀表达式转换成后缀表达式计算机程序在处理中缀表达式时,需要考虑优先级和括号等复杂的问题,因此非常费时间。
而把中缀表达式转换成后缀表达式之后,计算机程序就可以直接读取后缀表达式,不需要再考虑优先级和括号等问题,计算速度更快,程序也更加简单。
三、中缀表达式转后缀表达式的方法1.用栈实现中缀表达式转后缀表达式的方法中,最常用的就是用栈来实现。
具体步骤如下:(1)遍历中缀表达式中的每一个元素;(2)运用以下规则:a.如果该元素为数字,则直接加入到结果序列中;b.如果该元素为左括号,将其入栈;c.如果该元素为右括号,将栈中元素依次弹出,直到遇到左括号,将弹出的操作符依次加入到结果序列中;d.如果该元素为操作符,则将其与栈顶元素比较,如果其优先级大于等于栈顶操作符的优先级,则直接入栈,否则将栈顶操作符弹出加入到结果序列中,再将该操作符入栈;e.重复以上步骤,直到遍历完所有元素。
(3)最终将栈中剩余的操作符全部弹出,加入到结果序列中。
下面通过一个例子来演示以下使用栈实现中缀表达式转后缀表达式的过程:中缀表达式: A + B * C - D / E1.初始化栈S。
2.扫描中缀表达式从左到右,若读到的是操作数,则直接输出到后缀表达式中。
3.若遇到操作符,则判断当前操作符与栈顶操作符的优先级,若优先级低于等于栈顶操作符,则弹出栈顶操作符并输出到后缀表达式中,直到扫描到栈顶操作符优先级低于当前操作符或栈为空。
中缀表达式转后缀表达式并计算结果
中缀表达式转后缀表达式并计算结果⽬录1 栈的概念容器,先进后出规则;如图为表达式:a+(b*c) 逐个操作符、操作数⼊栈过程;出栈为该过程逆序2 何谓中缀表达式型如:a - b + c 的普通算术表达式,我们称之为中缀表达式。
3 后缀表达式(逆波兰)3.1 概念以及案例中缀表达式:a - b + c ,转化为后缀表达式:ab-c+;后缀表达式运算规则:1. 遇到操作数直接⼊栈,遇到操作符,从栈顶弹出两个操作数,并计算如下表达式结果压栈,直⾄最终弹出栈中最后⼀个数即停⽌算法,该记法的表达式称为后缀表达式后出栈操作数(两数中更靠近栈底者) (操作符[+_*/])先出栈操作数(栈顶)2. ab-c+计算过程如下图:3.2 求解⽅法⼊栈优先级{ [ ( > 乘= 除> 加= 减3.2.1 流程图弹出案例:扫描位优先级较⼩,扫描位为 " - "。
左括号虽然优先级⼤,但是左括号只在碰到,匹配的右括号时弹出3.2.2 推导相等优先级为何弹出栈顶只关注相同有优先级下是否弹出栈顶先加,后加减中缀表达式后缀表达式a +b +c abc++ 或 ab+c+a +b -c ab+c- 或 abc-+中缀表达式后缀表达式此例中,当需要判断操作符间优先级:栈顶为:+(加),栈外判断位:+ 或 - 。
此时若优先级相等,既可弹出栈顶操作符,也可不弹直接当前位压栈。
先减,后加减中缀表达式后缀表达式a -b +c ab-c+a -b -c ab-c-此例中,当需要判断操作符间优先级:栈顶为:-(减),栈外判断位:+ 或 - 。
此时若优先级相等,则只能弹出当前栈顶操作符。
先乘,后乘除中缀表达式后缀表达式a *b *c abc** 或 ab ca *b /c ab c/ 或 abc/此例中,当需要判断操作符间优先级:栈顶为:(乘),栈外判断位:或 / 。
此时若优先级相等,既可弹出栈顶操作符,也可不弹直接当前位压栈。
python数据结构之中缀表达式转后缀表达式(栈的应用)
python数据结构之中缀表达式转后缀表达式(栈的应⽤)1.设计的算法流程 ⾸先将⼀个中缀表达式从左到右的扫描,设计括号和操作符的优先级。
然后遍历切⽚后的中缀表达式。
遇到操作数就添加到后缀表达式的列表中去,遇到操作符就压⼊栈要求必须是操作符优先级⼤的在上⾯, 遇到左括号就标记,然后呢再就按照⽆括号的⽅法遍历,直到遇到右括号,然后再将操作符弹出直⾄左括号,然后再接着遍历,遍历到最后之后,将 栈⾥⾯的操作符弹出即可,完成中缀转后缀的操作。
具体实现如下from Stack import *def infixToPostfix(infixexpr):prec={}prec['*']=3prec['/']=3prec['+']=2prec['-']=2prec['(']=1opStack=Stack()postfixlist,tokenlist=[],[]for mark in range(len(infixexpr)):tokenlist.append(infixexpr[mark])print(tokenlist)for token in tokenlist:if token in'ABCDEFGHIJKLMNOPQRSTUVWXYZ'or token in'0123456789':postfixlist.append(token)elif token=='(':opStack.push(token)elif token==')':topToken=opStack.pop()while topToken!="(":postfixlist.append(topToken)topToken=opStack.pop()else:while (not opStack.isempity()) and (prec[opStack.get_stack()]>=prec[token]):postfixlist.append(opStack.pop())opStack.push(token)while not opStack.isempity():postfixlist.append(opStack.pop())return"".join(postfixlist)if__name__ == '__main__':n='A+B*C'print(infixToPostfix(n))这⾥将栈的get_stack⽅法修改了⼀下,变成拿到栈顶的数据。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
我们在数学中常见的计算式,例如2+(3*4)叫做中缀表达式。
表达式中涉及到了多个运算符,而运算符之间是有优先级的。
计算机在计算并且处理这种表达式时,需要将中缀表达式转换成后缀表达式,然后再进行计算。
中缀表达式转后缀表达式遵循以下原则:1.遇到操作数,直接输出;2.栈为空时,遇到运算符,入栈;3.遇到左括号,将其入栈;4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;5.遇到其他运算符'+''-''*''/'时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;6.最终将栈中的元素依次出栈,输出。
经过上面的步骤,得到的输出既是转换得到的后缀表达式。
举例:a+b*c+(d*e+f)*g ---------> abc*+de*f+g*+遇到a,直接输出:遇到+,此时栈为空,入栈:遇到b,直接输出:遇到*,优先级大于栈顶符号优先级,入栈:遇到c,输出:遇到+,目前站内的*与+优先级都大于或等于它,因此将栈内的*,+依次弹出并且输出,并且将遇到的这个+入栈:遇到(,将其入栈:遇到d,直接输出:遇到*,由于*的优先级高于处在栈中的(,因此*入栈:遇到e,直接输出:遇到+,栈顶的*优先级高于+,但是栈内的(低于+,将*出栈输出,+入栈:遇到f,直接输出:遇到),弹出栈顶元素并且输出,直到弹出(才结束,在这里也就是弹出+输出,弹出(不输出:遇到*,优先级高于栈顶+,将*入栈:遇到g,直接输出:此时已经没有新的字符了,依次出栈并输出操作直到栈为空:明白了这个过程,现在就需要用代码实现了。
对于各种运算符的优先级,可以使用整数来表示运算符的级别。
可以定义一个函数来返回各种符号的优先级数字:code.c/******************************************************************根据字符该字符是否在栈中,返回该字符的优先级。
*这里只处理+、-、*、/、(、)这些符号。
*需要注意的是:如果(在栈中,它的优先级是最低的,不在栈中则是最高的*@param c:需要判断的字符*@param flag:字符是否在栈中,0表示在栈中,1表示不在栈中*****************************************************************/int GetPrecedence(char c,int flag){if(c=='+' || c=='-'){return 1;}else if(c=='*' || c=='/'){return 2;}else if(c=='(' && flag==0){return 0;}else if(c=='(' && flag==1){return 3;}else{fprintf(stderr,"Input char is invalid!\n");return -1;}}/**************************************************************** *判断一个字符是不是运算符*如果是合法的运算符+、-、*、/、(、)则返回0,否则返回1****************************************************************/ int IsOperator(char c){if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'){return 0;}else{return 1;}}/**************************************************************** *完整的代码如下:****************************************************************/#include <stdio.h>#include <stdlib.h>#define ElementType chartypedef struct Node *PtrToNode;typedef PtrToNode Stack;typedef struct Node{ElementType Element;PtrToNode Next;};int IsEmpty(Stack S);Stack CreateStack();void DisposeStack(Stack S);void MakeEmpty(Stack S);void Push(ElementType X,Stack S); ElementType Top(Stack S);void Pop(Stack S);//判断栈是否为空int IsEmpty(Stack S){return S->Next == NULL;}//创建链栈Stack CreateStack(){Stack S = malloc(sizeof(struct Node));if(S == NULL){printf("No enough memory!");return NULL;}S->Next = NULL;MakeEmpty(S);return S;}//清空栈void MakeEmpty(Stack S){if(S == NULL){printf("Use CreateStack First!");}else{while(!IsEmpty(S)){Pop(S);}}}//进栈void Push(ElementType X,Stack S)PtrToNode Tmp;Tmp = malloc(sizeof(struct Node));if(Tmp != NULL){Tmp->Element = X;Tmp->Next = S->Next;S->Next = Tmp;}else{printf("Out of space!");}}//出栈void Pop(Stack S){if(IsEmpty(S)){printf("The Stack is Empty!");}else{PtrToNode Tmp = S->Next;S->Next = Tmp->Next;free(Tmp);}}//返回栈顶元素ElementType Top(Stack S){if(IsEmpty(S)){printf("The stack is empty!");return 0;}else{return S->Next->Element;}}/******************************************************************根据字符该字符是否在栈中,返回该字符的优先级。
*这里只处理+、-、*、/、(、)这些符号。
*需要注意的是:如果(在栈中,它的优先级是最低的,不在栈中则是最高的*@param c:需要判断的字符*@param flag:字符是否在栈中,0表示在栈中,1表示不在栈中*****************************************************************/ int GetPrecedence(char c,int flag){if(c=='+' || c=='-'){return 1;}else if(c=='*' || c=='/'){return 2;}else if(c=='(' && flag==0){return 0;}else if(c=='(' && flag==1){return 3;}else{fprintf(stderr,"Input char is invalid!\n");return -1;}}/**************************************************************** *判断一个字符是不是运算符*如果是合法的运算符+、-、*、/、(、)则返回0,否则返回1****************************************************************/ int IsOperator(char c){if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'){return 0;}else{return 1;}}char Output[50];//中缀表达式转成后缀表达式char* InfixToPostfix(char *ch,Stack S){int index=0;char c;while((c=*ch) != '\0'){//不是运算符,将该字符放进输出字符数组中。
if(IsOperator(c)==1){Output[index++] = c;ch++;}//是运算符else{//如果此时栈为空,运算符进栈if(IsEmpty(S)){Push(c,S);ch++;continue;}else{if(c==')'){while(!IsEmpty(S) && Top(S) != '('){Output[index++] = Top(S);Pop(S);}Pop(S);ch++;continue;}else{int outPrecedence = GetPrecedence(c,1);while(!IsEmpty(S) && GetPrecedence(Top(S),0) >= outPrecedence){Output[index++] = Top(S);Pop(S);}Push(c,S);ch++;continue;}}}}while(!IsEmpty(S)){Output[index++] = Top(S);Pop(S);}Output[index] = '\0';return Output;}int main(void){Stack S = CreateStack();char *charSequence = "1+2*3+(4*5+6)*7";char tmp;char *out = InfixToPostfix(charSequence,S);while((tmp=*out)!='\0'){printf("%c ",tmp);out++;}printf("\n");return 0;}。