数据结构算法:中缀表达式转化为后缀表达式
中缀转后缀表达式算法
中缀转后缀表达式算法
中缀表达式转后缀表达式(也称为逆波兰表达式)是一种将中缀表达式转换为后缀表达式的算法。
它的基本思想是将中缀表达式转换为一个后缀表达式,其中操作符位于操作数之后,而不是操作数之前。
中缀表达式转后缀表达式的算法步骤如下:
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 }。
中缀表达式转后缀表达式详解
中缀表达式转后缀表达式详解中缀表达式和后缀表达式是两种常见的数学表达式形式。
中缀表达式是我们通常使用的表达式形式,即运算符位于操作数的中间,例如:'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=='^')//如果是幂运算符就直接压栈
中缀表达式转换成后缀表达式
实验三中缀表达式转换成后缀表达式,然后按后缀表达式计算实验一、实验目的:对所学数据结构知识进行温习,比如栈和队列的顺序存储结构和链式结构、大体操作进行温习;将一个中缀表达式转换成后缀表达式,然后按后缀表达式计算进行分析与设计,上机调试,最终达到应用的目。
二、实验要求:要求对中缀表达式转换成后缀表达式,然后按后缀表达式计算作设计性实验,并上机运行,撰写实验报告。
三、实验内容:将一个中缀表达式转换成后缀表达式,然后按后缀表达式计算,例如:5+(4+2)/2-3*2。
四、实验环境:Windows XP + VC++6.0开发环境。
五、上机调试代码:# include<stdio.h># include<stdlib.h>typedef char typedata1;typedef int typedata2;typedef struct charnode{typedata1 data;struct charnode *next;}charstack;typedef struct intnode{typedata2 data;struct intnode *next;}intstack;char s[100];charstack *creat(){ charstack *head;head=(charstack *)malloc(sizeof(charstack));head->data='#';head->next=0;return head;}intstack *intcreat(){ intstack *head;head=(intstack *)malloc(sizeof(intstack));head->data=0;head->next=0;return head;}charstack *push(charstack *top,char x){charstack *p;p=(charstack *)malloc(sizeof(charstack));p->data=x;p->next=top;top=p;return top;}intstack *intpush(intstack *top,int x){intstack *p;p=(intstack *)malloc(sizeof(intstack));p->data=x;p->next=top;top=p;return top;}typedata1 top(charstack *top){return top->data;}typedata2 inttop(intstack *top){return top->data;}char compare(char x1,char x2){char m;int m1,m2;if(x1=='+'||x1=='-') m1=0;else if(x1=='*'||x1=='/') m1=1;else if(x1=='(') m1=2;if(x2=='+'||x2=='-') m2=0;else if(x2=='*'||x2=='/') m2=1;else if(x2=='(') m2=2;if(m1>m2) m='>';else if(m1<m2) m='<';else m='=';return m;}charstack *popl(charstack *top){ charstack *p;if(top==0)printf("下溢!");else{p=top;top=top->next;free(p);return top;}}intstack *intpopl(intstack *top){ intstack *p;if(top==0)printf("下溢!");else{p=top;top=top->next;free(p);return top;}}void display(char m[],int n){int i;for(i=0;i<=n;i++)printf("%c",m[i]);}int change(char a[],int n){int i;int j=0;char x1,x2,bj;charstack *q;q=creat();for(i=0;i<n;i++){if(a[i]<='9'&&a[i]>='0'){s[j]=a[i];j=j+1;if(a[i+1]>'9'||a[i+1]<'0'){s[j]=' ';j=j+1;}}else{x1=a[i];x2=top(q);if(x2=='#')q=push(q,x1);else{if(x1==')'){while(top(q)!='('){s[j]=top(q);j=j+1;q=popl(q);}q=popl(q);}else{bijiao:bj=compare(x1,x2);switch(bj){case '>':q=push(q,x1);break;case '<':if(x2!='('){s[j]=top(q);j=j+1;q=popl(q);x2=top(q);if(x2!='#') goto bijiao; else q=push(q,x1);break;}else q=push(q,x1);break;case '=':s[j]=top(q);j=j+1;q=popl(q);q=push(q,x1);break;}}}}}while(top(q)!='#'){s[j]=top(q);j=j+1;q=popl(q);}return j;}int calculator(char s[],int n){int i,x1,x2,x;intstack *q;q=intcreat();for(i=0;i<=n;i++){if(s[i]==' ') i=i+1;if(s[i]<='9'&&s[i]>='0'){x1=(int)s[i]-48; while(s[i+1]<='9'&&s[i+1]>='0'){x1=10*x1+(int)s[i+1]-48;i=i+1;}q=intpush(q,x1); }else if(s[i]=='+'){ x2=inttop(q);q=intpopl(q);x1=inttop(q);q=intpopl(q);q=intpush(q,x1+x2); }else if(s[i]=='-'){ x2=inttop(q);q=intpopl(q);x1=inttop(q);q=intpopl(q);q=intpush(q,x1-x2); }else if(s[i]=='*'){ x2=inttop(q);q=intpopl(q);x1=inttop(q);q=intpopl(q);q=intpush(q,x1*x2); }else if(s[i]=='/'){ x2=inttop(q);q=intpopl(q);x1=inttop(q);q=intpopl(q);q=intpush(q,x1/x2);}}x=inttop(q);return x;}void main(){int i,k;char f[100];printf("请输入中缀表达式(输入#终止):\n");for(i=0;i<100;i++){scanf("%c",&f[i]);if(f[i]=='#')break;}printf("\n后缀表达式为:");k=change(f,i);display(s,k);printf("\n\n计算结果为:%d\n\n",calculator(s,k)); }六、实验结果分析:1)实验运行结果及测试截图如下:2)本实验对字符也一样能得出后缀表达式,可是没有赋具体值,故不能算结果,同时呢也会弹出运用程序错误提示,测试截图如下:3)实验改良,若是本实验能在改良为,当输入为字符时自动提示为此字符赋值,那么此程序也将能计算出带有字符的的表达式的结果,同时本实验也能够通过其它算法实现。
【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 }。
数据结构与算法——中缀表达式
数据结构算法:中缀表达式转化为后缀表达式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; }}。
数据结构中缀式中缀表达式改后缀表达式并求值
《数据结构》课程设计报告课程设计题目:中缀表达式改后缀表达式并求值一. 实验目的·掌握栈的特征及基本操作,如入栈、出栈等,栈的顺序存储结构和链式存储结构的实现,以便在实际问题中灵活应用。
·掌握栈的典型应用——中缀表达式转后缀表达式,并利用后缀表达式求值。
二. 实验内容(一)中缀表达式转后缀表达式的方法: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;}四. 算法时间复杂度。
中缀表达式转化成后缀表达式的计算
目录一、设计思想 (01)二、算法流程图 (02)三、源代码 (03)四、运行结果 (16)五、遇到的问题及解决 (17)六、心得体会 (18)一、设计思想第一种算法先把算术表达式转化成后缀表达式,在对后缀表达式进行计算。
首先建立一个符号栈,用于存放字符和字符的优先级别;然后在建立一个数栈,用于辅助后缀表达式的计算;最后在定义一个字符串数组,用于存放后缀表达式。
建立一个计算的函数,该函数用于两个数的计算,在调用这个函数的时候,传入三个参数,两个浮点型参数和一个字符型参数,根据不同的符号进行不同的计算。
定义一个判断优先级别的函数,用于判断两个操作符的优先级别,在根据优先级的不同决定不同的操作。
后缀表达式的取得,对算术表达式字符串进行挨个的扫描,如果是数字或者是小数点,则将数字或者小数点存放到字符数组中,每取完一个数字,则在后面用“|”隔开,如果是操作符,则和栈中得操作符进行比较,若扫描到的符号优先级比栈里的符号优先级低,则栈中元素出栈并存放到字符数组中。
每出一个字符到字符数组中就在后面加“|”分隔。
继续检查栈顶比较优先级,直到栈中元素优先级比扫描到的符号优先级低或者符号栈为空,则将此操作符入栈。
若是“(”则无条件入字符栈,若是“)”则从字符栈中出字符直到遇到“(”为止。
当字符数组扫描到最后的时候,计算并没有结束。
然后得进行字符栈的判断,看是否已经为空栈,若不是空栈,则出栈字符,将字符存放到数组中。
最后字符串数组中存放的就是后缀表达式。
得到后缀表达式后,要用数栈进行后缀表达式的计算,后缀表达式的计算中,对新的数组进行从道到尾的扫描,如果遇到数字,以“|”为标记取出完整的操作数,用辅助数组存放,然后转化成浮点数存放到数栈中,遇到“|”则直接将数组下标往后走。
遇到字符,则从数栈取出两个数进行计算,将计算的结果从新存放到数栈中,循环直到接到结束。
最后存放在数栈中的数就是计算的结果。
最后在主函数中调用此函数,进行结果的输出。
中缀表达式转后缀表达式的方法
中缀表达式转后缀表达式的方法中缀表达式是我们日常数学运算中最常用的表达方式,它是以操作符放在两个操作数之间的形式表示算式的。
例如,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/此例中,当需要判断操作符间优先级:栈顶为:(乘),栈外判断位:或 / 。
此时若优先级相等,既可弹出栈顶操作符,也可不弹直接当前位压栈。
中缀转后缀表达式
中缀转后缀表达式中缀表达式是我们平时最常见的表达式形式,例如:1 + 2 * 3。
但是在计算机中,我们更常使用后缀表达式来进行计算。
因此,将中缀表达式转换为后缀表达式是非常重要的。
一、中缀表达式中缀表达式是指运算符位于两个操作数之间的表达式。
例如:1 + 2 * 3。
在中缀表达式中,运算符的优先级是由括号来确定的。
括号内的表达式优先计算,同级别的运算符按照从左到右的顺序计算。
二、后缀表达式后缀表达式是指运算符位于两个操作数之后的表达式。
例如:1 2 3 * +。
在后缀表达式中,运算符的优先级是由运算符本身来确定的。
同级别的运算符按照从左到右的顺序计算。
三、中缀转后缀中缀表达式转换为后缀表达式的过程可以使用栈来实现。
具体步骤如下:1. 初始化两个栈:运算符栈和结果栈。
2. 从左到右扫描中缀表达式。
3. 如果遇到操作数,直接将其压入结果栈。
4. 如果遇到运算符,比较其与运算符栈栈顶的优先级。
5. 如果运算符栈为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈。
6. 否则,若优先级比栈顶运算符的优先级高或相等,也将运算符压入运算符栈。
7. 否则,将运算符栈顶的运算符弹出并压入结果栈中,再次转到步骤4与新的栈顶运算符比较。
8. 如果遇到括号,如果是左括号“(”,则直接压入运算符栈;如果是右括号“)”,则依次弹出运算符栈顶的运算符,并压入结果栈中,直到遇到左括号为止,此时将这一对括号丢弃。
9. 重复步骤2至8,直到表达式的最右边。
10. 将运算符栈中剩余的运算符依次弹出并压入结果栈中。
11. 最后将结果栈中的元素依次弹出,即可得到后缀表达式。
四、总结中缀表达式转换为后缀表达式是一个非常重要的算法,它可以使我们更方便地进行计算。
在实际应用中,我们可以使用栈来实现这个算法。
通过这个算法的学习,我们可以更深入地理解计算机中的表达式计算过程。
中缀表达式转后缀表达式
中缀表达式转后缀表达式 先看⼏个中缀表达式和它们对应的后缀表达式的例⼦ 可以看到操作数a, b, c 在中缀表达式中的顺序和在后缀表达式中的顺序是⼀致的,但操作符的顺序可能不⼀致,因为在中缀表达式中操作符有优先级,括号也能改变运算的优先级,这些都要在后缀表达式中体现出来,后缀表达式中没有括号。
那怎么转化呢? 1,创建⼀个变量,初始化为空的字符串,来表⽰要完成的后缀表达式,创建⼀个字符栈,⽤来存储操作符 2,从左向右依次扫描中缀表达式, 遇到操作数,直接加到后缀表达式的后⾯,因为,在中缀表达式和后缀表达式中,操作数的顺序是⼀样的, 遇到操作符,要先存起来,存到栈中,因为操作符有优先级,它要和后⾯的操作符⽐较优先级,然后才能决定把它放到什么哪个位置。
如果栈为空,直接把操作符放⼊栈中 如果栈不为空,⽐较优先级。
如果遇到的操作符⽐栈顶中的操作符优先级⾼,把遇到的操作符放⼊栈中。
如果遇到的操作符和栈顶操作符的优先级相等,这要考虑操作符的结合性,它是从左到右结合,还是从右到左结合。
从左到右接合,就是操作数属于它前⾯的操作符⽽不是它后⾯操作符。
+, - , * , / 就是从左向右结合,⽐如a-b+c中的b 是-的操作数,⽽不是+的操作数,整个表达式,也是从左向右计算的。
从右向左结合,操作数属于它前⾯的操作符⽽不是它后⾯操作符,⽐如阶乘。
a ^ b ^ c, b是第⼆个^的操作数,⽽不是第⼀个^的操作数,整个表达式也是从右向左计算,a ^ (b ^ c)。
如果从左向右接合,那就弹栈,把操作符放到后缀表达式中,如果从右向左结合,则把遇到的操作符放⼊栈中(和优先级⾼的情况⼀致) 如果遇到的操作符⽐栈顶中的操作符优先级低,那就弹栈,把操作符放到后缀表达式中 遇到(,放到字符栈,因为要等到)才能知道怎么操作。
遇到),依次从字栈中弹栈,放到后缀表达式中,直到遇到(, 遇到(, 要把它弹栈,然后舍弃掉。
3,循环完毕,如果字符栈中还有操作符,依次弹栈放到后缀表达式中,最终栈为空,得到完整的后缀表达式。
- 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);//后缀表达式的计算
}
运行结果:。