数据结构算法:中缀表达式转化为后缀表达式
中缀转后缀表达式算法

中缀转后缀表达式算法
中缀表达式转后缀表达式(也称为逆波兰表达式)是一种将中缀表达式转换为后缀表达式的算法。
它的基本思想是将中缀表达式转换为一个后缀表达式,其中操作符位于操作数之后,而不是操作数之前。
中缀表达式转后缀表达式的算法步骤如下:
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.如果扫描字符是"+"或者"-",则⼀直出栈⾄栈顶元素为"+"或者"-"或者"("。
数据结构之中缀表达式转后缀表达式

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 + (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. 读到" + ",因为栈顶元素" * "的优先级⽐它⾼,所以弹出" * "并输出,同理,栈中下⼀个元素" + "优先级与读到的操作符" + "⼀样,所以也要弹出并输出。
然后再将读到的" + "压⼊栈中。
中缀表达式转换为后缀表达式

中缀表达式转换为后缀表达式中缀表达式转换成后缀表达式 1、概述 可以看到,后缀表达式适合计算式进⾏运算,但是⼈却不太容易写出来,尤其是表达式很长得情况下,因此在开发中,需要将中缀表达式转成后缀表达式。
2、具体步骤1.初始化两个栈:运算符栈s1和储存中间结果的栈s2;2.从左⾄右扫描中缀表达式;3.遇到操作数时,将其压s2;4.遇到运算符时,⽐较其与s1栈顶运算符的优先级: (1)如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符⼊栈; (2)否则,若优先级⽐栈顶运算符的⾼,也将运算符压⼊s1; (3)否则,将s1栈顶的运算符弹出并压⼊到s2中,再次转到(4.1)与s1中新的栈顶运算符相⽐较;5.遇到括号时: (1)如果是左括号"(",则直接压⼊s1 (2)如果是右括号")",则依次弹出s1栈顶的运算符,并压⼊s2,直到遇到左括号为⽌,此时将这⼀对括号丢弃6.重复步骤2⾄5,直到表达式的最右边7.将s1中剩余的运算符依次弹出并压⼊s28.依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式 3、案例 将中缀表达式 "1+((2+3)*4)-5" 转换为后缀表达式的过程如下: 结果为:"1 2 3 + 4 * 5 - " 4、思路分析⽰意图 5、代码实现1import java.util.ArrayList;2import java.util.List;3import java.util.Stack;45/**6 * 把中缀表达式转成后缀表达式7 *8*/9public class ToSuffixExpression {1011public static void main(String[] args) {12// 完成⼀个中缀表达式转成后缀表达式13// 说明14// 1. 1+((2+3)*4)-5 => 转成 123 + 4 * + 5-15// 2. 因为对 str进⾏操作不⽅便,先将中缀表达式存⼊ list16// 3.将得到的中缀表达式对应的 list转成 =>后缀表达式对应的list17// 即[1,+,(,(,2,+,3,),*,4,),-,5] => [1,2,3,+,4,*,+,5,-]1819 String expression = "1+((2+3)*4)-5";20 List<String> list = toInfixExpressionList(expression);21 System.out.println("中缀表达式对应的list="+list);22 List<String> list2 = parseSuffixExpressionList(list);23 System.out.println("后缀表达式对应的list="+list2);24 }2526//⽅法:将得到的中缀表达式对应的 list转成 =>后缀表达式对应的list27public static List<String> parseSuffixExpressionList(List<String> ls) {28//定义两个栈29 Stack<String> s1 = new Stack<String>(); // 符号栈3031//说明:因为 s2这个栈,在整个转换过程中,没有pop操作,后⾯还需要逆序输出 32//所以,把 s2 这个栈换成 List<String> 即可33//Stack<String> s2 = new Stack<String>(); // 存储中间结果的栈34 List<String> s2 = new ArrayList<String>(); //存储中间结果的list3536//遍历 ls37for(String item : ls) {38//如果是⼀个栈,就加⼊到s239if(item.matches("\\d+")) {40 s2.add(item);41 } else if (item.equals("(")) {42 s1.push(item);43 } else if (item.equals(")")) {44// 如果是右括号,则依次弹出s1栈顶的运算符,并压⼊ s2,知道遇到左括号为⽌,此时将这⼀对括号丢弃4546while(!s1.peek().equals("(")) {47 s2.add(s1.pop());48 }49 s1.pop(); // 将左括号弹出,消除⼩括号50 } else {51// 当 item 的优先级⼩于或等于栈顶运算符,将s1栈顶的运算符弹出并压⼊s2中,再次转到4.1与s1中新的栈顶运算符相⽐较 52//问题:缺少⽐较优先级⾼低的⽅法53while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)) {54 s2.add(s1.pop());55 }56//还需要将 item 压⼊栈中57 s1.push(item);58 }59 }6061//将s1中剩余的运算符依次弹出加⼊s262while(s1.size()!=0) {63 s2.add(s1.pop());64 }6566return s2; //因为存放到list中,因此,按顺序输出就是对应的后缀表达式对应的 list67 }686970// ⽅法:将中缀表达式转成对应的 list71public static List<String> toInfixExpressionList(String s) {72// 定义⼀个 list,存放中缀表达式对应的内容73 List<String> ls = new ArrayList<String>();74int i = 0; // 指针,⽤于遍历中缀表达式字符串75 String str; // 做对多位数的拼接⼯作76char c; // 每遍历到⼀个字符,就放⼊到 c7778do {79// 如果c是⼀个⾮数字,就需要加⼊到 ls80if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {81 ls.add("" + c);82 i++; // i后移83 } else { // 如果是数字,考虑多位数问题84 str = ""; // 将 str置空85while (i < s.length() && (c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57) {86 str += c; // 拼接87 i++;88 }89 ls.add(str);90 }9192 } while (i < s.length());93return ls; // 返回94 }95 }9697/**98 * 可以返回⼀个运算符的对应的优先级99 *100*/101public class Operation {102private static int ADD = 1;103private static int SUB = 1;104private static int MUL = 2;105private static int DIV = 2;106107// 写⼀个⽅法,返回对应的优先级数字108public static int getValue(String operation) { 109int result = 0;110switch(operation) {111case "+":112 result = ADD;113break;114case "-":115 result = SUB;116break;117case "*":118 result = MUL;119break;120case "/":121 result = DIV;122break;123default:124 System.out.println("不存在该运算符"); 125break;126 }127return result;128 }129 }。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
题目:中缀表达式转化为后缀表达式算法及其后缀表达式计算算法的实现。
内容:掌握栈的存储结构的C语言描述。
掌握中缀表达式和后缀表达式的存储结构。
掌握后缀表达式算法的实现。
calcolate():依次扫描string2中的字符,遇到数字则将其转化为整型数据存入栈中,遇运算符则将栈中栈顶的两个元素取出参与运算,并将计算结果放入栈中,如此直到运算符全部用完,最后一次运算结果即为后缀表达式的计算结果。
程序代码:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#define MAX 60
#define DEMAX 15
#define NULL 0
char string1[MAX];
char string2[MAX];
int j=0;
struct node
{
char data;
int num;
struct node *next;
};
struct node *Initialization()//初始化栈链,链栈不带头结点
{
struct node *top;
top=(struct node *)malloc(sizeof(struct node));
top->data='@';
top->num=0;
top->next=NULL;
return top;
}
struct node *assort(struct node *s)//输入字符串
{
struct node *p,*top;
int i;
top=s;
int m;
char a;
gets(string1);
m=strlen(string1);
for(i=0;i<=m;i++)
{
a=string1[i];
if('0'<=string1[i]&&string1[i]<='9')
{
string2[j]=string1[i];j++;
}
else
{
switch(a)
{
case '(':{
p=(struct node *)malloc(sizeof(struct node));
p->data=a;p->next=top;
top=p;
break;
}
case '*':
case '/':
string2[j]=' ';j++;
if((top->data=='*')||(top->data=='/'))
{
string2[j]=top->data;j++; //比其高,现将栈顶运算符出栈,再进栈。
top->data=a;
break;
}
else
{
p=(struct node *)malloc(sizeof(struct node));//否,直接进栈
p->data=a;p->next=top;
top=p;
break;
}
case '+':
case '-':{
string2[j]=' ';j++;
if(top->data=='+'||top->data=='-'||top->data=='*'||top->data=='/')
{
string2[j]=top->data;j++;;
top->data=a;
break;
}
else
{
p=(struct node *)malloc(sizeof(struct node));
p->data=a;p->next=top;
top=p;
break;
}
}
case ')':{
string2[j]=' ';j++;
if(top->data=='@'){printf("input error");break;}
while(top->data!='(')
{
string2[j]=top->data;j++;
p=top;
top=top->next;
free(p);
}
p=top;top=top->next;free(p);
break;
}
}
}
}
while(top->data!='@')
{
string2[j]=top->data;j++;
p=top;
top=top->next;
free(p);
}
string2[j]='#';
printf("转化后的后缀表达式为:%s\n",string2);
return top;
}
struct node *calcolate(struct node *s)
{
struct node *top,*p;
char *q;
int x,y,a;
int i,n;
top=s;//指向栈顶的指针
for(i=0;i<=j;i++)//遍历字符串string2
{
if(string2[i]>='0'&&string2[i]<='9')
{
q=&string2[i];
a=atoi(q);
for(n=i;string2[n]>='0'&&string2[n]<='9';n++){}
p=(struct node *)malloc(sizeof(struct node ));
p->num=a;p->next=top;top=p;
i=n-1;
}
else
if(string2[i]=='#') //遇#号结束标志,输出栈中的最后计算结果printf("计算结果为:%d\n",top->num);
else
{
if(string2[i]==' '){}
else
{
y=top->num;p=top;top=top->next;free(p);
x=top->num;p=top;top=top->next;free(p);
switch(string2[i])
{case '+':{a=x+y;
p=(struct node *)malloc(sizeof(struct node));
p->num=a;p->next=top;top=p;
break;}
case '-':{a=x-y;
p=(struct node *)malloc(sizeof(struct node ));
p->num=a;p->next=top;top=p;
break;}
case '*':{a=x*y;
p=(struct node *)malloc(sizeof(struct node ));
p->num=a;p->next=top;top=p;
break;}
case '/':{a=(float)x/y;
p=(struct node *)malloc(sizeof(struct node ));
p->num=a;p->next=top;top=p;
break;}
}
}
}
}
return 0;
}
main()
{
struct node *top,*head;
int m;
top=Initialization();//建立一个链栈,并返回栈顶指针
printf("请输入表达式:");
head=assort(top);//中缀转化为后缀表达式
calcolate(head);//后缀表达式的计算
}
运行结果:。