C++栈实现将中缀表达式转换为后缀表达式
将中缀表达式转换成后缀表达式的三种方法

将中缀表达式转换成后缀表达式的三种方法中缀表达式是我们平常最常见的表达式形式,但在计算机的运算过程中,我们常常需要将中缀表达式转换成后缀表达式,因为后缀表达式具有易于计算的特点。
那么,接下来我们将介绍三种将中缀表达式转换成后缀表达式的方法。
一、栈的方法这种方法是最常见的一种方法,也是比较易理解的一种方法。
我们可以借助栈来完成中缀表达式转换成后缀表达式的过程。
具体的操作如下: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. 最终,输出的表达式即为转换后的后缀表达式。
三、判断法这种方法也是比较常见的一种方法。
算术表达式(中缀表达式)转换为后缀表达式

算术表达式(中缀表达式)转换为后缀表达式将后缀表达式exp转换为postexp的过程如下:while(从exp读取字符ch,ch!='\0'){ 若ch为数字,将后继的数字都⼀次存放到postexp中,并以字符'#'标志数值串的结束; 若ch为左括号“(”,将此括号进栈到运算符栈op中; 若ch为右括号“)”,将运算符栈op依次出栈,直到“(”,并将“(”也出栈; 若ch为运算符,优先级不⼤于运算符op的栈顶运算符(除栈顶运算符为“(”外)的优先级,则依次出栈并存⼊到postexp中,然后将ch 进栈}若中缀表达式exp扫描完毕,将运算符栈op中的所有运算符依次出栈并存放到postexp中,就得到了后缀表达式。
完整代码:#include <stdio.h>#define MAXSIZE 50typedef char elemType;//运算符栈typedef struct{elemType data[MAXSIZE];int top;}OP;OP op;//中缀表达式转为后缀表达式void trans(char exp[],char postexp[]){op.top=-1;int i=0,j=0;char ch=exp[i];while(ch!='\0'){switch(ch){case'(':{op.top++;op.data[op.top] = ch;break;}case')':{while(op.data[op.top]!='('){postexp[j++]=op.data[op.top--];}op.top--; //去除 '('break;}case'+':case'-':{while(op.top!=-1&&op.data[op.top]!='('){postexp[j++]=op.data[op.top--];}op.top++;op.data[op.top]=ch;break;}case'*':case'/':{while(op.top!=-1&&(op.data[op.top]=='*'||op.data[op.top]=='/')){postexp[j++]=op.data[op.top];op.top--;}op.top++;op.data[op.top]=ch;break;}case'':break;default :{while(ch>='0'&&ch<='9'){postexp[j++]=ch;i++;ch=exp[i];}i--; //不是数字退后⼀个,⽤switch来进⾏判断 postexp[j++]='#'; //在数字结束后添加'#'以便区分}}i++;ch=exp[i];}while(op.top!=-1){ //将运算符栈中postexp[j++]=op.data[op.top--];}postexp[j]='\0';}。
中缀表达式转后缀表达式

中缀表达式转后缀表达式逆波兰表达式先说⼀下中缀表达式,平时我们使⽤的运算表达式就是中缀表达式,例如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 }。
中缀转后缀数据结构

将中缀表达式转换为后缀表达式需要使用栈数据结构。
具体步骤如下: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 + 。
算术表达式的中缀式转后缀式c语言

算术表达式的中缀式转后缀式c语言算术表达式的中缀式转后缀式是计算机科学中的一个重要问题,它可以将人类可读的中缀表达式转换为计算机可处理的后缀表达式。
在C语言中,我们可以使用栈来实现中缀表达式转后缀表达式的算法。
首先,我们需要定义一个栈来存储操作符。
然后,我们从左到右扫描中缀表达式,如果遇到操作数,我们直接将其输出;如果遇到左括号,我们将其压入栈中;如果遇到操作符,我们需要判断其与栈顶操作符的优先级,如果栈顶操作符优先级高于或等于当前操作符,则将栈顶操作符弹出并输出,直到栈顶操作符优先级低于当前操作符或者栈为空,然后将当前操作符压入栈中;如果遇到右括号,则将栈中左括号上面的操作符依次弹出并输出,直到遇到左括号为止。
最后,如果表达式已经扫描完毕,我们将栈中所有操作符依次弹出并输出,直到栈为空。
下面是C语言实现中缀表达式转后缀表达式的代码:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_SIZE 100typedef struct {char data[MAX_SIZE];int top;} Stack;void init(Stack *s) {s->top = -1;}void push(Stack *s, char c) {if (s->top == MAX_SIZE - 1) { printf("Stack overflow\n"); exit(1);}s->data[++(s->top)] = c;}char pop(Stack *s) {if (s->top == -1) {printf("Stack underflow\n");exit(1);}return s->data[(s->top)--];}char peek(Stack *s) {if (s->top == -1) {printf("Stack underflow\n");exit(1);}return s->data[s->top];}int is_empty(Stack *s) {return s->top == -1;}int is_operator(char c) {return c == '+' || c == '-' || c == '*' || c == '/'; }int precedence(char c) {if (c == '+' || c == '-') {return 1;} else if (c == '*' || c == '/') {return 2;} else {return 0;}}void infix_to_postfix(char *infix, char *postfix) { Stack s;init(&s);int i, j;for (i = 0, j = 0; infix[i] != '\0'; i++) {if (infix[i] >= '0' && infix[i] <= '9') {postfix[j++] = infix[i];} else if (infix[i] == '(') {push(&s, infix[i]);} else if (infix[i] == ')') {while (!is_empty(&s) && peek(&s) != '(') { postfix[j++] = pop(&s);}if (!is_empty(&s) && peek(&s) == '(') {pop(&s);} else {printf("Invalid expression\n");exit(1);}} else if (is_operator(infix[i])) {while (!is_empty(&s) && precedence(peek(&s)) >= precedence(infix[i])) {postfix[j++] = pop(&s);}push(&s, infix[i]);} else {printf("Invalid character: %c\n", infix[i]);exit(1);}}while (!is_empty(&s)) {if (peek(&s) == '(') {printf("Invalid expression\n");exit(1);}postfix[j++] = pop(&s);}postfix[j] = '\0';}int main() {char infix[MAX_SIZE], postfix[MAX_SIZE];printf("Enter infix expression: ");scanf("%s", infix);infix_to_postfix(infix, postfix);printf("Postfix expression: %s\n", postfix);return 0;}```在这个代码中,我们使用了一个结构体来定义栈,其中包含一个字符数组和一个整数top表示栈顶的位置。
中缀表达式转后缀表达式 c++代码

中缀表达式转后缀表达式 c++代码中缀表达式转后缀表达式是一种常见运算表达式的转换方式,该转换方式可以使得运算表达式更加方便和高效。
在转换过程中,我们首先需要了解什么是中缀表达式,什么是后缀表达式以及它们之间的相互转换关系。
中缀表达式是指运算符放在两个运算对象的中间的表达式,例如:A + B * C,其中“+”是运算符,A、B和C是运算对象。
后缀表达式则是指运算符放在两个运算对象的后面的表达式,例如:A B C * +,其中“+”是运算符,A、B和C是运算对象。
中缀表达式和后缀表达式是等价的,它们可以相互转换而不改变表达式的含义。
在C++中,可以使用栈来实现中缀表达式转换为后缀表达式的操作。
具体实现方式如下:1. 遍历中缀表达式中的每个字符和运算符,依次进行如下操作:2. 如果遇到数字或者变量,直接输出到输出队列中。
3. 如果遇到运算符,则将其入栈。
4. 如果遇到“(”符号,则将其入栈。
5. 如果遇到“)”符号,则将栈中的运算符依次弹出并输出到输出队列中,直到遇到左括号为止。
6. 遍历完成后,如果栈中还有运算符,则将其依次弹出并输出到输出队列中。
7. 输出队列中的字符串即为后缀表达式。
下面是一个C++的实现代码示例:#include<iostream>#include<cstring>#include<stack>#include<queue>using namespace std;//将中缀表达式转换为后缀表达式string infixToPostfix(string infix_expression){stack<char> s;queue<char> q;string postfix_expression = "";int len = infix_expression.size();for(int i = 0;i < len;++i){if(infix_expression[i] == '+' || infix_expression[i] == '-' || infix_expression[i] == '*' || infix_expression[i] == '/'){//遇到操作符while(!s.empty() && s.top() != '('){if((infix_expression[i] == '*' || infix_expression[i] == '/') && (s.top() == '+' || s.top() == '-')){break;}q.push(s.top());s.pop();}s.push(infix_expression[i]);}else if(infix_expression[i] == '('){s.push(infix_expression[i]);}else if(infix_expression[i] == ')'){while(!s.empty() && s.top() != '('){q.push(s.top());s.pop();}s.pop();}else if((infix_expression[i] >= '0' && infix_expression[i] <= '9') || (infix_expression[i] >= 'a' && infix_expression[i] <= 'z')){ //遇到数字或变量q.push(infix_expression[i]);}}while(!s.empty()){q.push(s.top());s.pop();}while(!q.empty()){postfix_expression += q.front();q.pop();}return postfix_expression;}int main(){string infix_expression = "a+b*c-(d/e+f)*g";string postfix_expression = infixToPostfix(infix_expression);cout << postfix_expression << endl;return 0;}在代码实现中,我们用一个栈来保存运算符,用一个队列来保存输出的字符。
(完整版)数学表达式计算(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 栈。
C语言数据结构之栈:中缀表达式的计算

C语⾔数据结构之栈:中缀表达式的计算*注:本⼈技术不咋的,就是拿代码出来和⼤家看看,代码漏洞百出,完全没有优化,主要看⽓质,是吧学了数据结构——栈,当然少不了习题。
习题中最难的也是最有意思的就是这个中缀表达式的计算了(可以算+-*/和^,当然也可以带⼩括号)。
搞了很久很久啊,终于搞出来的。
简单说⼀下程序原理:因为中缀表达式基本没法算(就算可以也肯定会超时),所以得把中缀表达式转为后缀表达式。
程序分为两步第⼀步:将中缀表达式转为后缀表达式创建⼀个字符串,⽐如叫get,⽤于存储后缀表达式先是输⼊⼀个字符串,逐⼀读取单个字符,当是数字则直接存⼊get,如果是操作符则:创建栈,⽐如叫chaswhile循环当栈顶操作符优先级⼤于或等于当前操作符则弹出并把栈顶元素赋值给get 直到发现优先级⼩于当前操作符的栈顶的操作符,⼩于当前操作符的那个栈顶操作符不弹出然后将当前操作符压⼊栈内当当前操作符为'('则直接压⼊栈内当当前操作符为')'则while循环弹出栈顶操作符并赋值给get直到弹出的是'(' ( '('只弹出不赋值)注意,')'不压⼊栈中第⼆部:计算get创建int型数组栈,⽐如ints逐个读⼊get当读到数字压⼊ints当读到操作符则弹出两个ints的栈顶元素,并进⾏相应计算,将计算得到的值压⼊栈ints中最后读完get时,ints数组只剩下⼀个元素了,输出。
⾃个⼉写的稀巴烂源码(c):1 #include <stdio.h>2 #include <string.h>3 #include <math.h>45int ints[10000];6int intt;//ints的top7char chas[10000];8int chat;//chas的top9int i=0, ii=1;10char c;11char get[10000];//输⼊的中缀表达式12char get2[10000];//计算得出的后缀表达式1314void intpush(x)//整型栈压栈15 {16 intt++; ints[intt]=x;17 }18void chapush(x)//字符型栈压栈19 {20 chat++; chas[chat]=x;21 }22int intpop()//整型栈弹出23 {24 intt--; return ints[intt+1];25 }26char chapop()//字符型栈弹出27 {28 chat--; return chas[chat+1];29 }30void intadd(int x)//整型栈栈顶元素加⼊新的个位数字32 ints[intt]*=10; ints[intt]+=x;33 }3435int find()//get2加⼊操作符36 {37 c=chapop();38 get2[ii]='';39 get2[ii+1]=c;40 ii+=2;41if(chat==0) return0;42return1;43 }4445int main()46 {47 intt=0; chat=0;48 gets(get);49int lengets=strlen(get);50for(i=0;i<=lengets-1;i++)//逐个读取输⼊的中缀表达式51 {52if (isdigit(get[i]))//当get[i]为数字时53 {54 get2[ii]=get[i];55 ii++;56 }57else58 {59if(get[i]=='(')chapush('(');60if(get[i]=='^')chapush('^');61if(get[i]==')')62 {63 c=chapop();64while(c!='(')65 {66 get2[ii]='';67 get2[ii+1]=c;68 ii+=2;69 c=chapop();70 }71 }72if(get[i]=='+')73 {74while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^') 75 {76if(find()==0)break;77 }78 chapush('+');79 }80if(get[i]=='-')81 {82while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^') 83 {84if(find()==0)break;85 }86 chapush('-');87 }88if(get[i]=='*')89 {90while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')91 {92if(find()==0)break;93 }94 chapush('*');95 }96if(get[i]=='/')97 {98while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')99 {100if(find()==0)break;101 }102 chapush('/');103 }104 get2[ii]='';105 ii++;106 }107108 }109while(chat>0)//输出栈内剩余的操作符110 {111int c=chapop();112 get2[ii]='';113 get2[ii+1]=c;114 ii+=2;116 get2[ii]='@';//加⼊结束符117 i=1;118while(get2[i]!='@')//当看到结束符停⽌计算119 {120if(get2[i]=='+'||get2[i]=='-'||get2[i]=='*'||get2[i]=='/'||get2[i]=='^')121 {122int a=intpop();int b=intpop();int c;123if(get2[i]=='+') c=a+b;124if(get2[i]=='-') c=b-a;125if(get2[i]=='*') c=a*b;126if(get2[i]=='/') c=b/a;127if(get2[i]=='^') c=pow(b,a);128 intpush(c);129 }130else131 {132if(get2[i]!='')133 {134 intpush(get2[i]-48);135 ii=1;136while(get2[i+ii]!='')137 {138 intadd(get2[i+ii]-48);139 ii++;140 }141 i+=ii-1;142 }143 }144 i++;145 }146 printf("%d",ints[1]);147return0;148 }样例输⼊:1+(3+2)*(7^2+6*9)/(2)样例输出:258好了,就写到这了。
中缀表达式转后缀表达式最难例题

中缀表达式转后缀表达式最难例题以下是一个较复杂的中缀表达式转后缀表达式的示例:中缀表达式:(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",将其添加到后缀表达式中。
用堆栈实现四则运算c语言

用堆栈实现四则运算c语言堆栈是一种常见的数据结构,它符合先进后出的原则。
在四则运算中,我们可以借助堆栈这种数据结构实现运算,方便高效,不易出错。
堆栈的实现包括两个基本操作:Push(入栈)和Pop(出栈)。
我们可以以此设计四则运算。
首先,我们需要将输入的四则运算表达式转换成后缀表达式。
后缀表达式也叫逆波兰表达式,相对于中缀表达式而言,运算符在后面,操作数在前面,这样方便计算机进行读取和计算。
例如:中缀表达式:5+3*2后缀表达式:5 3 2 * +将中缀表达式转换成后缀表达式,我们需要用到堆栈。
具体的实现方法是,从左向右遍历表达式,如果是数字,则直接输出;如果是符号,则将其与堆栈顶的符号进行比较,如果优先级高就入栈,否则不断将符号出栈并输出,直到当前符号优先级大于堆栈顶符号优先级,最后将当前符号入栈。
例如:表达式:5+3*2堆栈操作:1.将5输出,堆栈为空2.遇到+号,入栈3.将3输出,堆栈顶为+号4.遇到*号,入栈5.将2输出,堆栈顶为*号6.输出*号,堆栈顶为+号7.输出+号,堆栈为空得到后缀表达式:5 3 2 * +有了后缀表达式,我们可以用堆栈进行计算。
具体方法是,从左向右遍历后缀表达式,如果是数字则入栈,如果是符号则将栈顶两个数字出栈并进行计算,将结果入栈,最终得到最终的计算结果。
例如:后缀表达式:5 3 2 * +堆栈操作:1.将5入栈2.将3入栈3.遇到*号,出栈3和2,进行计算得到6,将6入栈4.将栈顶元素5出栈5.遇到+号,出栈6和5,进行计算得到11,将11入栈得到计算结果:11通过堆栈实现四则运算,可以有效简化我们的计算流程,避免复杂的优先级判断和计算错误。
同时,堆栈为我们提供了一种更加高效的数据结构,不仅在四则运算中可以发挥作用,在其他应用中也很常见。
当然,在实际应用中,我们需要考虑到多种情况的处理,例如负数、小数、括号等,以及错误处理等细节问题,才能保证算法的正确性和可靠性。
中缀表达式转后缀表达式并计算结果(c语言版)

中缀表达式转后缀表达式中缀表达式转后缀表达式的规则。
1.遇到操作数:直接输入到后缀表达式栈2.遇到运算符,直接入操作符栈3.遇到左括号:直接将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈6.最终将操作符栈中的元素依次出栈,输出到后缀表达式栈。
以下是自己写的代码。
亲测没有问题。
(模拟一个计算器,可以带括号,中间可以空格,只支持整数输入,但是输出结果精确到小数后6位)#include "stdio.h"#define MAX_LEN 100typedef struct cal{unsigned char isOper;//是否是操作数1,操作符0.操作数double Num; //值。
或者是操作符的ASCII值}STRUCT_CAL;#define IS_NUM 0x00#define IS_OPER 0x01STRUCT_CAL stackCal[MAX_LEN];STRUCT_CAL stackCalBack[MAX_LEN];unsigned char topCal;char stackOper[MAX_LEN];unsigned char topOper;/****************************************************************** 堆栈初始化*****************************************************************/void stackInit(void){int i;for(i=0;i<MAX_LEN;i++){stackCal[i].isOper = 0;stackCal[i].Num = 0;stackOper[i] = 0;}topCal = topOper = 0;}/***************************************************************** * 返回堆栈的栈顶,返回后栈顶减一*****************************************************************/ STRUCT_CAL * stackCalPop(void){if(topCal == 0)return (STRUCT_CAL *)0;return stackCal+(--topCal);}/***************************************************************** * 计算表达式入栈*****************************************************************/void stackCalPush(double num, unsigned char isOper){if(topCal>=MAX_LEN)return;stackCal[topCal].Num = num;stackCal[topCal].isOper= isOper;topCal++;}/***************************************************************** * 操作符出栈*****************************************************************/char stackOperPop(void){if(topOper == 0)return 0;return stackOper[--topOper];}/****************************************************************** 操作符入栈*****************************************************************/void stackOperPush(char oper){if(topOper >=MAX_LEN)return;stackOper[topOper++] = oper;}/****************************************************************** 比较两个sour sour1 的优先级* 1 sour >= sour1 直接入操作符栈* 0 sour < sour1 直接入计算表达式栈*****************************************************************/ unsigned char comparPrior(char sour, char sour1){if(sour =='\0' ||sour1 == '\0') return 1;switch(sour){case '+':case '-':if(sour1 == '*' ||sour1 == '/'||sour1 == '+' ||sour1 == '-' ){return 0;}else{return 1;}break;case '*':case '/':if(sour1 == '*' ||sour1 == '/'||sour1 == '+' ||sour1 == '-'||sour1 == '('){return 1;}else{return 0;}break;default:return 1;break;}}/****************************************************************** 将输入的字符串转换为栈*****************************************************************/void StrToCal(char *pStr){int tmpNum = 0;char tmpOper;char islastNum = 0;//判断上一个字符是什么。
c语言基于二叉树的表达式求值算法

c语言基于二叉树的表达式求值算法C语言中,基于二叉树的表达式求值算法主要包括两部分:中缀表达式转换为后缀表达式和后缀表达式求值。
1.中缀表达式转换为后缀表达式中缀表达式是我们常见的数学表达方式,例如3 + 4 * 2 - 5。
为了方便计算机求值,我们需要将中缀表达式转换为后缀表达式,也叫做逆波兰表达式。
转换的过程使用栈数据结构来实现。
具体算法如下:1.定义一个栈和一个结果字符串,栈用于存储操作符,结果字符串用于保存后缀表达式。
2.从左到右遍历中缀表达式的每一个字符。
3.如果当前字符是数字,直接将其加入结果字符串。
4.如果当前字符是左括号"(",将其入栈。
5.如果当前字符是右括号")",则依次将栈顶的操作符弹出并加入结果字符串,直到遇到左括号为止,同时将左括号从栈中弹出。
6.如果当前字符是操作符,需要将栈中优先级比当前操作符高或者相等的操作符弹出并加入结果字符串,然后将当前操作符入栈。
7.遍历完所有字符后,将栈中剩余的操作符依次弹出并加入结果字符串。
8.最终结果字符串就是后缀表达式。
例如,对于中缀表达式3 + 4 * 2 - 5,转换为后缀表达式为3 4 2 * + 5 -2.后缀表达式求值后缀表达式求值算法使用栈数据结构来实现。
具体算法如下:1.定义一个栈,用于存储操作数。
2.从左到右遍历后缀表达式的每一个字符。
3.如果当前字符是数字,则将其转换为对应的整数并入栈。
4.如果当前字符是操作符,则从栈中弹出两个操作数,先弹出的作为右操作数,后弹出的作为左操作数,根据操作符进行运算,得到结果后入栈。
5.遍历完所有字符后,栈顶的数字即为最终的结果。
例如,对于后缀表达式3 4 2 * + 5 -,求值的过程如下:1.入栈3。
2.入栈4。
3.入栈2。
4.弹出2和4,计算4 * 2 = 8,将8入栈。
5.弹出8和3,计算3 + 8 = 11,将11入栈。
6.入栈5。
7.弹出5和11,计算11 - 5 = 6,得到最终结果。
中缀表达式转后缀表达式详解

中缀表达式转后缀表达式详解中缀表达式和后缀表达式是两种常见的数学表达式形式。
中缀表达式是我们通常使用的表达式形式,即运算符位于操作数的中间,例如:'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 * +'后缀表达式的计算可以通过遍历列表中的元素来完成。
C++中缀表达式计算

C++中缀表达式计算功能:输⼊⼀个中缀表达式的值(+ - * / ( ) )然后得出计算结果设计:1 第⼀步将中缀表达式转换为后缀表达式,每⼀个表达式都对应⼀个符号表达式数,中缀表达式是对数做中序遍历,⽽后缀表达式则是对次数做后缀遍历,学过数据结构的应该对此很熟悉了,借助堆栈可以轻松实现此点,在此我要说明的⼀点是,由于⼀个整数可能会占⼀个字符,⽐如“456”就占了3位,所以为了标识每个数在转换为后缀表达式后在每个数后⾯都加上了⼀个“#”,譬如“16 +28”转换后即为“16#28#+”2第⼆步相对来说就简单很多了,利⽤堆栈对后序表达式进⾏计算就可以了下⾯给出源码⾸先是头⽂件,⾥⾯是⾃⼰⽤链表实现的⼀个堆栈,很简单,在此不多做解释1 #ifndef STACK_H2#define STACK_H34 template<typename T>5class Stack;67 template<typename T>8class SNode9 {10 friend class Stack<T>;11private:12 T m_Data;13 SNode *m_pNext;14 };1516 template<typename T>17class Stack18 {19public:20 Stack();21 ~Stack();22public:23void Push(T data);24 T Pop();25bool IsEmpty();26 T GetTop();27private:28 SNode<T> *m_pTop;29 };3031 template<typename T>32 Stack<T>::Stack()33 {34 m_pTop=new SNode<T>;35 m_pTop->m_pNext=NULL;36 }3738 template<typename T>39void Stack<T>::Push(T data)40 {41 SNode<T> *pNode=new SNode<T>;42 m_pTop->m_Data=data;43 pNode->m_pNext=m_pTop;44 m_pTop=pNode;45 }4647 template<typename T>48 T Stack<T>::Pop()49 {50 SNode<T> *pNode=m_pTop->m_pNext;51if(pNode==NULL)52 {53 std::cout<<"Stack is empty"<<std::endl;54 exit(0);55 }56 m_pTop->m_pNext=pNode->m_pNext;57 T data=pNode->m_Data;58 delete pNode;59 pNode=NULL;60return data;61 }6263 template<typename T>64bool Stack<T>::IsEmpty()65 {66return m_pTop->m_pNext==NULL;67 }6869 template<typename T>70 T Stack<T>::GetTop()71 {72 SNode<T> *pNode=m_pTop->m_pNext;73return pNode->m_Data;74 }75 template<typename T>76 Stack<T>::~Stack()77 {78 SNode<T> *pNode=m_pTop->m_pNext,*pCur;79while(pNode!=NULL)80 {81 pCur=pNode;82 pNode=pNode->m_pNext;83 delete pCur;84 }85 }然后是两个函数,第⼀个函数将中序表达式换为后序表达式,第⼆个对后序表达式进⾏计算这是第⼀个函数此函数基于如下算法顺序的读⼊中序表达式,若遇到字符为操作数时则直接输出,并接着读下⼀字符,若单词为运算符时,取栈顶变量与当前变量的优先级做⽐较,若栈顶元素的优先级较⾼或相等,则栈顶元素退栈并输出到后序表达式中,接着新的栈顶变量与之⽐较。
【转】中缀表达式转换为后缀表达式

【转】中缀表达式转换为后缀表达式⼀、后缀表达式求值后缀表达式也叫逆波兰表达式,其求值过程可以⽤到栈来辅助存储。
假定待求值的后缀表达式为:6 5 2 3 + 8 * + 3 + *,则其求值过程如下:1)遍历表达式,遇到的数字⾸先放⼊栈中,此时栈如下所⽰:2)接着读到“+”,则弹出3和2,执⾏3+2,计算结果等于5,并将5压⼊到栈中。
3)读到8,将其直接放⼊栈中。
4)读到“*”,弹出8和5,执⾏8*5,并将结果40压⼊栈中。
⽽后过程类似,读到“+”,将40和5弹出,将40+5的结果45压⼊栈...以此类推。
最后求的值288。
⼆、中缀表达式转后缀表达式2.1)规则中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
转换过程需要⽤到栈,具体过程如下:1)如果遇到操作数,我们就直接将其输出。
2)如果遇到操作符,则我们将其放⼊到栈中,遇到左括号时我们也将其放⼊栈中。
3)如果遇到⼀个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为⽌。
注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为⽌。
弹出完这些元素后,才将遇到的操作符压⼊到栈中。
有⼀点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。
5)如果我们读到了输⼊的末尾,则将栈中所有元素依次弹出。
2.2)实例规则很多,还是⽤实例⽐较容易说清楚整个过程。
以上⾯的转换为例,输⼊为a + b * c + (d * e + f)*g,处理过程如下:1)⾸先读到a,直接输出。
2)读到“+”,将其放⼊到栈中。
3)读到b,直接输出。
此时栈和输出的情况如下:4)读到“*”,因为栈顶元素"+"优先级⽐" * " 低,所以将" * "直接压⼊栈中。
中缀表达式转化为后缀表达式算法

中缀表达式转化为后缀表达式算法首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入后缀表达式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。
可指定其他字符,不一定非#不可。
从中缀式的左端开始取字符,逐序进行如下步骤:(1)若取出的字符是数字,则分析出完整的运算数,该运算数直接送入S2栈(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否者,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,则将该运算符送入S1栈。
(3)若取出的字符是“(”,则直接送入S1栈栈顶。
(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。
完成以上步骤,S2栈便为后缀表达式输出结果。
不过S2应做一下逆序处理。
便可以按照后缀表达式的计算方法计算了!做法如下将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
后缀表达式的作用对于实现后缀表达式算法,难度并不大,但为什么要将看似简单的中缀表达式转换为复杂的后缀表达式?原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中缀表达式是非常复杂的结构。
相对的,后缀表达式在计算机看来却是比较简单易懂的结构。
C语言计算器实现(中缀表示法后缀表示法)

C语⾔计算器实现(中缀表⽰法后缀表⽰法)————————————————————————————————————————————实现原理:每个操作数都被依次压⼊栈中,当⼀个运算符到达时,从栈中弹出相应数⽬的操作数(对于⼆元运算符来说是两个操作数),把该运算符作⽤于弹出的操作数,并把运算结果再压⼊栈中- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -计算器(后缀表达式)相关知识:后缀表达式(逆波兰表⽰法):在逆波兰中,所有运算符都跟在操作数后⾯,如下:(1 - 2) *(4 + 5) 采⽤逆波兰表⽰法表⽰为:1 2 - 4 5 + *,不需要圆括号,只要知道每个运算符需要⼏个操作数就不会引起歧义实现功能:输⼊后缀表达式,以换⾏结束,计算四则运算结果。
对于 1 2 - 4 5 + * 来说,⾸先把1和2压⼊到栈中,再⽤两者之差-1取代它们;然后将4和5压⼊到栈中,再⽤两者之和9取代它们。
最后从栈中取出栈顶的-1和9,并把它们的积-9压⼊到栈顶。
到达输⼊⾏的末尾时,把栈顶的值弹出来并打印。
伪代码:while 读⼊值不为换⾏时if 是数字压⼊栈中else if 是运算符弹出两个运算数,计算并压栈else 输⼊错误并退出end if读⼊值弹出最终结果并打印实现代码:1/* 实现功能:输⼊后缀表达式,以换⾏结束,计算四则运算结果 */2/* 这种后缀表⽰法只需要⼀个栈就可以了,遇到符号则弹运算数,但是中缀就不⼀样 */3 #include <stdio.h>4 #include <stdlib.h>5#define OK 16#define ERROR 07#define OVERFLOW -28#define STACK_INIT_SIZE 1009#define STACKINCREAMENT 1010 typedef int Status;11 typedef char SElemType;12 typedef struct13 {14 SElemType *top;15 SElemType *base;16int stacksize;17 } SqStack;18 Status InitStack(SqStack *s)19 {20 s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));21if (!s->base) exit(OVERFLOW);22 s->top = s->base;23 s->stacksize = STACK_INIT_SIZE;24return OK;25 }26 Status Push(SqStack *s, SElemType e)27 {28if (s->top - s->base == s->stacksize)29 {30 s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType)); 31if (!s->base) exit(OVERFLOW);32 s->top = s->base + s->stacksize;33 s->stacksize += STACKINCREAMENT;34 }35 s->top++;36 *(s->top) = e;37return OK;38 }39 Status Pop(SqStack *s, SElemType *e)40 {41if (s->top == s->base) exit(OVERFLOW);42 *e = *(s->top);43 s->top--;44return OK;45 }46 Status Empty(SqStack s)47 {48if (s.top - s.base == 0)49return OK;50else51return ERROR;52 }53int main()54 {55 SqStack OPND; //OPTR是运算符 OPND是运算数56char c, num1, num2;57 InitStack(&OPND);58while((c = getchar()) != '\n')59 {60switch(c)61 {62case'0':63case'1':64case'2':65case'3':66case'4':67case'5':68case'6':69case'7':70case'8':71case'9':72 Push(&OPND, c - '0');73break;74case'+':75 Pop(&OPND, &num2);76 Pop(&OPND, &num1);77 Push(&OPND, num1 + num2);78break;79case'-':80 Pop(&OPND, &num2);81 Pop(&OPND, &num1);82 Push(&OPND, num1 - num2);83break;84case'*':85 Pop(&OPND, &num2);86 Pop(&OPND, &num1);87 Push(&OPND, num1 * num2);88break;89case'/':90 Pop(&OPND, &num2);91 Pop(&OPND, &num1);92 Push(&OPND, num1 / num2);93break;94default:95break;96 }97 }98while(!Empty(OPND))99 {100 Pop(&OPND, &c);101 printf("%d ", c);102 }103return OK;104 }- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -计算器(中缀表⽰法)运算符优先级:+-*/()# +>><<<>>->><<<>>*>>>><>>/>>>><>>(<<<<<=0)>>>>0>>#<<<<<0=执⾏过程:在计算 #4+3*(5-10)/5# 时栈中的执⾏过程如下步骤输⼊字符执⾏操作OPTR OPND 1#Push(#)#24Push(4)#43+'#'<'+',Push(+)# +443Push(3)# + 4 35*'+'<'*',Push(*)# + * 4 36('*'<'(',Push(()# + * ( 4 375Push(5)# + * ( 4 3 58-'('<'-',Push(-)# + * ( - 4 3 5910Push(10)# + * ( - 4 3 5 1010)'-'>')',计算并压⼊结果# + * ( 4 3 -511'('=')',脱括号# + * 4 3 -5 12/'*'>'/'计算并压⼊结果# + 4 -1513'+'<'/',Push(/)# + / 4 -15145Push(5)# + / 4 -15 5 15#'/'>'#',计算并压⼊结果# + 4 -316'+'>'#',计算并压⼊结果#117'#'='#',脱括号1伪代码:初始化运算符栈;压⼊#;初始化运算数栈;获取输⼊;while 获取输⼊不为#或栈顶不为#if 输⼊的是数字压⼊运算数栈获取输⼊if 新输⼊的也是数字⼗位数百位数运算end ifelseswitch 运算符栈顶与当前输⼊优先级⽐较压⼊运算符栈获得输⼊弹出运算符栈顶(或#获得输⼊弹出运算符栈顶弹出两个运算数计算并将结果压⼊运算数栈//此时不获取新输⼊,该循环输⼊的运算符作为c重新进⼊循环end ifend while输出运算数栈中剩的运算数实现代码:1/* 只能运算-128~127之间的结果 */2 #include <stdio.h>3 #include <stdlib.h>4 #include <math.h>5#define OK 16#define ERROR 07#define SPILL -2 //math.h中已有OVERFLOW,则改⽤SPILL8#define STACK_INIT_SIZE 1009#define STACKINCREAMENT 1010 typedef char SElemType;11 typedef int Status;12 typedef struct13 {14 SElemType *top;15 SElemType *base;16int stacksize;17 } SqStack;18 Status InitStack(SqStack *s)19 {20 s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));21if (!s->base)22 exit(SPILL);23 s->top = s->base;24 s->stacksize = STACK_INIT_SIZE;25return OK;26 }27 Status EmptyStack(SqStack s)28 {29if (s.top - s.base == 0)30return OK;31else32return ERROR;33 }34 Status Push(SqStack *s, SElemType e)35 {36if (s->top - s->base == s->stacksize)37 {38 s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType)); 39if (!s->base)40 exit(SPILL);41 s->top = s->base + s->stacksize;42 s->stacksize += STACKINCREAMENT;43 }44 s->top ++;45 *(s->top) = e;46return OK;47 }48 Status Pop(SqStack *s, SElemType *e)49 {50if (s->top == s->base)51 exit(SPILL);52 *e = *(s->top);53 s->top--;54return OK;55 }56 SElemType GetTop(SqStack s)57 {58return *(s.top);59// *e = *(s.top);60// return OK;61 }62/* 判断如果是数字则返回OK,运算符返回ERROR,⾮法输⼊则退出 */63 Status InputJudge(SElemType c)64 {65switch(c)66 {67case'0':68case'1':69case'2':70case'3':71case'4':72case'5':73case'6':74case'7':75case'8':76case'9':77return OK;78break;79case'+':80case'-':81case'*':82case'/':83case'(':84case')':85case'#':86return ERROR;87break;88default:89 exit(SPILL);90break;91 }92 }93/* 当前输⼊的运算符和前⼀个运算符⽐较优先级 */94 SElemType PriorityJudge(SElemType optr1, SElemType optr2)95 {96int i, j;97char priorityTable[7][7] =98 {99 {'>', '>', '<', '<', '<', '>', '>'},100 {'>', '>', '<', '<', '<', '>', '>'},101 {'>', '>', '>', '>', '<', '>', '>'},102 {'>', '>', '>', '>', '<', '>', '>'},103 {'<', '<', '<', '<', '<', '=', '0'},104 {'>', '>', '>', '>', '0', '>', '>'},105 {'<', '<', '<', '<', '<', '0', '='}106 };107switch(optr1)108 {109case'+':110 i = 0;111break;112case'-':113 i = 1;114break;115case'*':116 i = 2;117break;118case'/':119 i = 3;120break;121case'(':122 i = 4;123break;124case')':125 i = 5;126break;127case'#':128 i = 6;129break;130 }131switch(optr2)132 {133case'+':134 j = 0;135break;136case'-':137 j = 1;138break;139case'*':140 j = 2;141break;142case'/':143 j = 3;144break;145case'(':146 j = 4;147break;148case')':149 j = 5;150break;151case'#':152 j = 6;153break;154 }155return priorityTable[i][j];156 }157/* 四则运算 */158 SElemType Calc(SElemType optr, SElemType num1, SElemType num2)159 {160switch(optr)161 {162case'+':163return (num1 + num2);164break;165case'-':166return (num1 - num2);167break;168case'*':169return (num1 * num2);170break;171case'/':172return (num1 / num2);173break;174 }175 }176int main()177 {178char c, optr, num1, num2, temp;179 SqStack OPND, OPTR;180 InitStack(&OPTR);181 Push(&OPTR, '#');182 InitStack(&OPND);183 c = getchar();184while(c != '#' || GetTop(OPTR) != '#')185// while(!EmptyStack(OPTR))186//严蔚敏⽼师书上的算法是判断输⼊⾮#或栈顶⾮#时循环,个⼈认为判断运算符栈不为空也可以,当初始化时压⼊的#闭合,结束运算187 {188if (InputJudge(c))189 {190 Push(&OPND, c - '0');191 c = getchar();192/* 当连续输⼊数字时,计算⼗位数和百位数 */193while(InputJudge(c))194 {195int i = 1;196 Pop(&OPND, &temp);197 Push(&OPND, temp * pow(10, i) + (c - '0'));198 i++;199 c = getchar();200 }201 }202else203switch(PriorityJudge(GetTop(OPTR), c))204 {205case'<':206 Push(&OPTR, c);207 c = getchar();208break;209case'=':210 Pop(&OPTR, &c);211 c = getchar();212break;213case'>':214 Pop(&OPTR, &optr);215 Pop(&OPND, &num2);216 Pop(&OPND, &num1);217 Push(&OPND, Calc(optr, num1, num2)); 218break;219 }220 }221while(!EmptyStack(OPND))222 {223 Pop(&OPND, &c);224 printf("%d\n", c);225 }226return OK;227 }。
c++ 中缀转后缀表达式

c++ 中缀转后缀表达式摘要:一、前缀表达式与后缀表达式的概念1.前缀表达式2.后缀表达式二、C++中缀转后缀的算法实现1.输入表达式2.初始化栈3.遍历表达式a.遇到操作数,压入栈b.遇到运算符,弹出栈顶运算符c.判断栈顶运算符与当前运算符的优先级d.将当前运算符压入栈e.继续遍历三、C++中缀转后缀的代码实现1.函数声明与定义2.输入表达式3.初始化栈4.遍历表达式a.遇到操作数,压入栈b.遇到运算符,弹出栈顶运算符c.判断栈顶运算符与当前运算符的优先级d.将当前运算符压入栈e.继续遍历5.返回结果正文:在C++中,中缀表达式是一种非常常见的表达式形式,但是有时我们需要将其转换为后缀表达式来进行一些特定的操作。
例如,计算表达式的值、实现四则运算的计算器等。
那么如何将一个中缀表达式转换为后缀表达式呢?下面我们将详细介绍C++中缀转后缀的算法实现与代码实现。
首先,我们需要了解前缀表达式与后缀表达式的概念。
前缀表达式是一种仅包含操作数和运算符的表达式,如“3+5*2”。
而后缀表达式是一种仅包含操作数和运算符优先级信息的表达式,如“35*2+”。
通过对比这两种表达式,我们可以发现后缀表达式能够清晰地表示运算符的优先级,为后续计算表达式的值提供了便利。
接下来,我们将介绍C++中缀转后缀的算法实现。
首先,我们需要输入一个中缀表达式,然后初始化一个栈来存储运算符及其优先级。
接着,我们遍历输入的中缀表达式,遇到操作数时将其压入栈,遇到运算符时弹出栈顶运算符并判断其与当前运算符的优先级。
如果当前运算符的优先级小于等于栈顶运算符的优先级,则将当前运算符压入栈,否则将栈顶运算符弹出并将其压入栈。
最后,当遍历完整个表达式后,栈中剩下的运算符就是后缀表达式。
最后,我们将介绍C++中缀转后缀的代码实现。
首先,我们需要声明一个函数,接收一个字符串参数表示中缀表达式。
然后,我们通过循环输入表达式中的字符,根据字符类型进行相应的处理。
用栈实现中缀表达式转后缀表达式并构建计算机求值

#include <string>#include <stack>#include <iostream>#include <sstream>#include <iomanip>using namespace std;class calculator{public:calculator() {}calculator(string expression) {getexpression(expression);}//获得算术表达式void getexpression(string expression) {e = expression;}~calculator() {}//返回中缀表达式string ShowMiddleExpression() {return e;}//计算函数, 输入为两个数和一个操作符, 返回值为计算结果(字符串形式) string calculate(string num2, string num1, string op) {double n2, n1;string result;stringstream x;x << num2;x >> n2;x.clear();x << num1;x >> n1;x.clear();if (op == "+")x << (n2 + n1);if (op == "-")x << (n2 - n1);if (op == "*")x << (n2 * n1);if (op == "/")x << (n2 / n1);x >> result;x.clear();return result;}//判别符号的优先级int Priority(char a) {if (a == '(')return 0;else if (a == '+' || a == '-')return 1;else if (a == '*' || a == '/')return 2;return 0;}//用于去除输入中多余的空格输入为要除去空格的算术表达式返回去掉空格的算术表达式string RidSpace(string origin) {string transfer;for (int i = 0; i < origin.length(); i++) {if (origin[i] != ' ')transfer += origin[i];}return transfer;}//中缀表达式转后缀表达式, 因为要兼容多位数, 括号, 负数和小数等功能,//由于多位数在转为后缀表达式时会分不清, 故在每个数和运算符后面加上一个空格作为区别//expression为输出的后缀表达式string MidToLast(string str) {str = RidSpace(str);string expression = "";string number = "";char x;stack<char> op;for (int i = 0; i < str.length(); ) {//第一位做特殊处理判断是否为负号if (i == 0 && str[i] == '-') {number = "-";i++;}x = str[i];//录入数字if ((x >= '0' && x <= '9') || number == "-" || x == '.') {while ((str[i] >= '0' && str[i] <= '9') || str[i] == '.') {number += str[i];i++;}expression += number;//加空格以区别expression += " ";number = "";continue;} else {//判断是括号还是运算符if (x == '(') {op.push(x);//判断是否为负号if (str[i+1] == '-') {number = "-";i++;}} else {//遇到右括号直接弹出运算符栈里的运算符到表达式中运算符后加空格以区别if (x == ')') {while (op.top() != '(') {expression += op.top();expression += " ";op.pop();}//弹出右括号op.pop();} else {//弹出栈中优先级较高的运算符运算符后加空格以区别while (!op.empty() && (Priority(op.top()) >= Priority(x))) {expression += op.top();expression += " ";op.pop();}//判断是否为负号if (str[i+1] == '-') {number = "-";i++;}//将运算符压入栈op.push(x);}}}i++;}while (!op.empty()) {expression += op.top();expression += " ";op.pop();}return expression;}//获得后缀表达式string GetLastExpression() {return MidToLast(RidSpace(e));}string exe() {//获取后缀表达式string le = GetLastExpression();string tem = "";stack<string> num;for (int i = 0; i < le.length(); ) {while (le[i] != ' ') {tem += le[i];i++;}//若为数字, 压栈if (tem.length() > 1 || (tem.length() == 1 && tem[0] >= '0' && tem[0] <= '9')) { num.push(tem);} else {//若为运算符, 执行运算后压栈//处理如-()的情况if (num.empty()) {tem = "-";i++;continue;}string tem1 = num.top();num.pop();if (!num.empty()) {string tem2 = num.top();num.pop();num.push(calculate(tem2, tem1, tem));} else {tem1 = "-" + tem1;num.push(tem1);}}i++;tem = "";}return num.top();}private:string e;};。
c++ 中缀转后缀表达式

c++ 中缀转后缀表达式摘要:1.C++中缀转后缀表达式的概念2.中缀转后缀的转换方法3.转换过程中的数据结构和算法4.实际应用案例和注意事项正文:C++中缀转后缀表达式在C++编程语言中,表达式是程序设计中常见的概念。
表达式分为中缀表达式和后缀表达式两种形式。
中缀表达式是运算符写在运算对象的中间,而后缀表达式则是运算对象写在运算符的后面。
为了方便编程和计算,有时候需要将中缀表达式转换为后缀表达式。
下面我们来探讨一下C++中缀转后缀表达式的相关知识。
一、C++中缀转后缀表达式的概念中缀转后缀表达式是指将一个中缀表达式转换为一个后缀表达式的过程。
例如,给定中缀表达式"a + b * c",转换后的后缀表达式为"ab + c *"。
在后缀表达式中,运算符位于运算对象的后面,这样可以方便计算。
二、中缀转后缀的转换方法中缀转后缀的转换方法有多种,其中一种比较常见的方法是采用栈来实现。
具体步骤如下:1.初始化一个空栈。
2.从中缀表达式的左端开始,依次将每个运算对象和运算符入栈。
3.当遇到运算对象时,将其入栈;当遇到运算符时,进行以下操作:a.弹出栈顶的两个运算对象,记为a 和b。
b.将弹出的运算对象a 和当前运算符进行运算,得到一个新的运算对象。
c.将新运算对象入栈。
4.当栈为空时,转换完成。
此时栈中的元素就是后缀表达式的运算对象序列。
三、转换过程中的数据结构和算法在转换过程中,需要使用栈这种数据结构来存储运算对象。
栈是一种遵循后进先出(LIFO)原则的数据结构,可以用来存储序列中的运算对象。
算法方面,主要是通过栈的入栈和出栈操作来实现中缀表达式到后缀表达式的转换。
在遇到运算对象时,将其入栈;在遇到运算符时,弹出栈顶的两个运算对象进行运算,并将新的运算对象入栈。
这样,当栈为空时,就完成了中缀转后缀的转换。
四、实际应用案例和注意事项中缀转后缀表达式在实际编程中有很多应用,例如表达式求值、中缀表达式遍历等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5 将中缀表达式转换为后缀表达式
【问题描述】表达式转换。
输入的中缀表达式为字符串,转换得到的后缀表达式存入字符数组中并输出。
例如:a*(x+y)/(b-x) 转换后得:a x y + * b x - /
【数据结构】
●定义一个暂时存放运算符的转换工作栈opst。
●中缀表达式字符串char *infix;
●后缀表达式字符串char *postfix;
【算法提示】转换规则:把运算符移到它的两个操作数后面,删除掉所有的括号。
从头到尾扫描中缀表达式,对不同类型的字符按不同情况处理:
●数字或小数点,直接写入字符串postfix,并在每个数值后面写入一个空格;
●左括号,进栈,直到遇见相配的右括号,才出栈;
●右括号,表明已扫描过括号内的中缀表达式,把从栈顶直到对应左括号之间的运算
符依次退栈,并把结果推入栈内;
●对于运算符,分两种情况处理:
◆该运算符的优先级大于栈顶符号的优先级,则入栈;
◆若该运算符的优先级小于栈顶优先级,则先弹出栈顶运算符、写入postfix串;继续将该
运算符与栈顶运算符比较,直到能把它推入栈内为止(即优先级大于栈顶运算符)。
说明:自行设计运算符优先级的表示。
【主要代码】
#include <assert.h>
#include <iostream.h>
//#include <stdlib.h>
const int stackIncreament=20;
class SeqStack
{
private:
char *elements;
int top;
int maxSize;
void overflowProcess();
public:
SeqStack(int sz=50);
~SeqStack()
{ delete []elements; }
void Push(const char &x);
bool Pop(char &x);
bool getTop(char &x);
int isdigit(char ch);
int isp(char ch1);
int icp(char ch2);
bool IsEmpty() const
{ return (top == -1)? true:false; }
bool IsFull() const
{ return (top == maxSize-1)? true:false; }
int getSize() const { return top+1; }
void MakeEmpty() { top= -1; }
};
SeqStack::SeqStack(int sz)
{ top = -1; maxSize = sz; elements = new char[maxSize];
assert(elements!=NULL);
}
void SeqStack::overflowProcess()
{ char*newArray=new char[maxSize+stackIncreament];
/* if (newArray==NULL)
{
cerr<<"存储分配失败!"<<endl;
exit(1);
}*/
for (int i = 0; i <= top; i++) newArray[i] = elements[i];
maxSize= maxSize+stackIncreament;
delete []elements; elements = newArray; }
void SeqStack::Push(const char &x)
{
if (IsFull()==true) overflowProcess();
elements[++top]=x;
}
bool SeqStack::Pop(char &x)
{ if (IsEmpty() == true) return false;
x = elements[top--]; return true;
}
bool SeqStack::getTop(char &x)
{ if (IsEmpty()==true) return false;
x=elements[top]; return true;
}
int SeqStack::isdigit(char ch)
{ if(ch>='0'&&ch<='9'||ch=='.'||ch>='a'&&ch<='z'||ch>='A'&&ch<='Z') return 1; e lse return 0;
}
int SeqStack::isp(char ch1)
{ int val; switch(ch1)
{ case '#': val=0; break;
case '(': val=1; break;
case '*': case '/': case '%': val=5; break;
case '+': case '-': val=3; break;
case ')': val=6; break;
}
return val;
}
int SeqStack::icp(char ch2)
{ int val; switch(ch2)
{ case '#': val=0; break;
case '(': val=6; break;
case '*': case '/': case '%': val=4; break;
case '+': case '-': val=2; break;
case ')': val=1; break;
} return val;
}
class Show:public SeqStack
{ public:
Show(int sz):opst(sz){} void Clear(); void Postfix();void Input();void Output(); private:
SeqStack opst; char *infix; char *postfix;
};
void Show::Clear()
{ opst.MakeEmpty();
}
void Show::Input()
{ infix=new char[20];cout<<"请输入中缀表达式:"<<endl; cin>>infix;
}
void Show::Postfix()
{ postfix=new char[20];cout<<"输出的后缀表达式为:"<<endl;
SeqStack opst;char ch='#',ch1,op;opst.Push(ch);
int i=0; ch=infix[i];while(opst.IsEmpty()==false&&ch!='#')
if(opst.isdigit(ch)==1)
{ cout<<ch; i++;ch=infix[i];
}else { cout<<" ";opst.getTop(ch1);
if(opst.isp(ch1)<opst.icp(ch))
{opst.Push(ch); i++;ch=infix[i];
}
else
if(opst.isp(ch1)>opst.icp(ch))
{opst.Pop(op); if(op!='#') cout<<op;
}
else{opst.Pop(op); i++; c h=infix[i]; }
} cout<<endl;
}
void main()
{ Show Sh(100); Sh.Input(); Sh.Postfix();}
【实验过程】
【实验体会】一直都不理解为什么要加语句“if (newArray==NULL) {cerr<<"存储分配失败!"<<endl; exit(1); }*/”觉得此举可有可无,到现在为止去掉了此举后的程序照样运行。
但是“存在的即是合理的”,此类句子肯定有他的意义,只是我还没发现出来。
中追转换成后缀对我们理解栈的意义,及栈的重要操作有很大的帮助,虽然模拟的是计算机处理算式的过程,我们此类计算的用处也不多,但是有助于我们理解栈先今后出的特性。
这个题目算好还没要求按照后缀表达式计算,如果用后缀表达式计算,那就是一个相反的过程,肯定也极其繁琐。