将中缀表达式转换为后缀表达式_C 程序[1]
将中缀表达式转换成后缀表达式的三种方法
将中缀表达式转换成后缀表达式的三种方法中缀表达式是我们平常最常见的表达式形式,但在计算机的运算过程中,我们常常需要将中缀表达式转换成后缀表达式,因为后缀表达式具有易于计算的特点。
那么,接下来我们将介绍三种将中缀表达式转换成后缀表达式的方法。
一、栈的方法这种方法是最常见的一种方法,也是比较易理解的一种方法。
我们可以借助栈来完成中缀表达式转换成后缀表达式的过程。
具体的操作如下: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+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 }。
中缀表达式转换为后缀表达式C语言程序
#ifndef STACK_H#define STACK_H#include<stdio.h>#include<stdlib.h>typedef struct astack *Stack;typedef struct astack{int top;int maxtop;char* data;}Astack;Stack NewEmpty(int size){Stack S=(Stack)malloc(sizeof(Astack));S->maxtop=size;S->top=-1;S->data=(char*)malloc(size*sizeof(char)); return S;}int StackEmpty(Stack S){return S->top<0;}int StackFull(Stack S){return S->top==S->maxtop;}int Peek(Stack S){return S->data[S->top];}void Push(char x,Stack S){if(StackFull(S)){printf("Stack is full!\n");exit(1);}elseS->data[++S->top]=x;int Pop(Stack S){if(StackEmpty(S)){printf("Stack is empty!\n");exit(1);}elsereturn S->data[S->top--];}Stack NewStack(int size){Stack S=NewEmpty(size);int i,x,num;printf("Please enter the number of data:\n"); scanf("%d",&num);for(i=0;i<num;i++){printf("Please enter the %d date:\n",i+1); scanf("%c",&x);Push(x,S);}return S;}void ShowStack(Stack S){int i;for(i=0;i<=S->top;i++){printf(" %c",S->data[i]);}printf("\n");}#endif#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include"1.h"#define MAX 30int Precedence(char ch){if(ch=='+'||ch=='-')return 2; else if(ch=='*'||ch=='/')return 3; else if(ch=='('||ch==')')return 4; else if(ch=='@')return 1;else return 0;}void Change(char *s1,char *s2) {Stack S=NewEmpty(MAX); int i=0,j=0,one=0;char ch=s1[i];Push('@',S);while(ch!='@'){if(ch==' ')ch=s1[++i];else if(isalnum(ch)!=0){if(one==1){s2[j++]=' ';}s2[j++]=ch;ch=s1[++i];one=0;}else if(ch=='('){Push(ch,S);ch=s1[++i];one=1;}else if(ch==')'){while(Peek(S)!='(')s2[j++]=Pop(S);Pop(S);ch=s1[++i];one=1;}else if(ch=='+'||ch=='-'||ch=='*'||ch=='/'){while(Peek(S)!='('&&Precedence(Peek(S))>=Precedence(ch)) {s2[j++]=Pop(S);one=1;}Push(ch,S);ch=s1[++i];one=1;}}while(StackEmpty(S)!=1){s2[j++]=Pop(S);one=1;}s2[j]='\0';}int main(){char s1[MAX],s2[MAX];printf("Enter the equation:\n");gets(s1);Change(s1,s2);printf("%s\n",s2);return 0;}。
中缀表达式转后缀表达式 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;}在代码实现中,我们用一个栈来保存运算符,用一个队列来保存输出的字符。
算法笔记--中缀表达式转后缀表达式后缀表达式计算
算法笔记--中缀表达式转后缀表达式后缀表达式计算中缀表达式转后缀表达式规则中缀表达式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. 读到" + ",因为栈顶元素" * "的优先级⽐它⾼,所以弹出" * "并输出,同理,栈中下⼀个元素" + "优先级与读到的操作符" + "⼀样,所以也要弹出并输出。
然后再将读到的" + "压⼊栈中。
c++ 中缀转后缀表达式
c++中缀转后缀表达式
在计算机科学中,中缀表达式和后缀表达式是两种不同的数学表达式表示方法。
中缀表达式是我们在日常生活中所使用的表达式形式,例如"2+3"。
而后缀表达式,也称为逆波兰表示法,是一种更简洁的表达式形式,例如"23+"。
下面是一个详细的步骤,说明如何将中缀表达式转换为后缀表达式:
1.创建一个空的后缀表达式列表:这个列表将用于存储转换后的后缀表达式。
2.创建一个符号栈:这个栈用于临时存储中缀表达式中的操作数和操作符。
3.遍历中缀表达式的每个字符:
如果字符是一个操作数(数字),则直接将其添加到后缀表达式列表中。
如果字符是一个操作符(如+、-、、/),则检查栈顶的两个元素。
如果栈顶的两个元素是操作数,则将操作符压入栈中。
否则,从栈中弹出操作符,并将其与栈顶的操作数结合,形成新的后缀表达式,添加到后缀表达式列表中。
然后将当前的操作数压入栈中。
4.处理中缀表达式的最后一个字符:此时,如果栈中仍有操作符,则将其与栈顶的操作数结合,形成新的后缀表达式,添加到后缀表达式列表中。
5.清空符号栈中剩余的元素:此时,栈中可能还有未使用的操作数。
将这些操作数依次添加到后缀表达式列表中。
6.返回后缀表达式列表:此时,后缀表达式列表就是转换后的后缀表达式。
这个算法的时间复杂度是O(n),其中n是中缀表达式的长度。
这是因为我们需要遍历每个字符一次,并且栈操作的时间复杂度是线性的。
空间复杂度也是O(n),因为我们需要使用一个大小与输入长度相同的栈。
中缀表达式转后缀表达式 c++代码
中缀表达式转后缀表达式 c++代码中缀表达式是人类表达算术运算的一种方式,但是对于计算机来说却不那么方便,因为计算机更容易处理后缀表达式。
因此,我们需要找到一种转换方法,将中缀表达式转换为后缀表达式。
本文将介绍一种使用栈来实现中缀表达式转后缀表达式的方法,并提供相关的C++代码参考。
1. 什么是中缀表达式中缀表达式是一种常用的算术表达式表示法,它使用操作符在两个操作数中间,例如:2 + 3(a + b) * c(a > b) && (c < d)这种表示方法是人类思考数学问题时使用的方式,但是对于计算机来说,它不是最方便的表示方法,因为需要考虑运算符优先级和结合性等问题。
2. 什么是后缀表达式后缀表达式也被称为逆波兰表达式,它使用操作符在两个操作数之后,例如:2 3 +a b + c *a b > c d < &&后缀表达式消除了括号和运算符优先级等问题,因此非常适合计算机使用。
3. 中缀表达式转换为后缀表达式的过程中缀表达式转后缀表达式的过程可以使用栈来实现。
具体步骤如下:1) 创建一个空栈,并将后缀表达式的结果存储在一个空字符串中。
2) 从左向右遍历中缀表达式,每次遇到一个运算符或操作数时执行以下操作:- 如果是操作数,将其添加到结果字符串中。
- 如果是左括号,将其压入栈中。
- 如果是右括号,则弹出栈中的元素,直到遇到左括号。
每个弹出的元素都添加到结果字符串中,但不包括左括号。
- 如果是运算符,则比较其与栈顶元素的优先级。
如果栈顶元素的优先级大于或等于当前运算符的优先级,则弹出栈顶元素并添加到结果字符串中。
重复此步骤直到栈为空或栈顶元素的优先级小于当前运算符的优先级。
然后将当前运算符压入栈中。
3) 如果所有输入都已处理,则弹出栈中所有元素并将其添加到结果字符串中,直到栈为空。
4. 栈的实现在使用栈来实现中缀表达式转换为后缀表达式时,我们需要实现以下三个基本操作:- push: 在栈顶添加一个元素。
中缀表达式转后缀表达式详解
中缀表达式转后缀表达式详解中缀表达式和后缀表达式是两种常见的数学表达式形式。
中缀表达式是我们通常使用的表达式形式,即运算符位于操作数的中间,例如:'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 * +'后缀表达式的计算可以通过遍历列表中的元素来完成。
中缀表达式转换成后缀表达式
实验三中缀表达式转换成后缀表达式,然后按后缀表达式计算实验一、实验目的:对所学数据结构知识进行温习,比如栈和队列的顺序存储结构和链式结构、大体操作进行温习;将一个中缀表达式转换成后缀表达式,然后按后缀表达式计算进行分析与设计,上机调试,最终达到应用的目。
二、实验要求:要求对中缀表达式转换成后缀表达式,然后按后缀表达式计算作设计性实验,并上机运行,撰写实验报告。
三、实验内容:将一个中缀表达式转换成后缀表达式,然后按后缀表达式计算,例如: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)实验改良,若是本实验能在改良为,当输入为字符时自动提示为此字符赋值,那么此程序也将能计算出带有字符的的表达式的结果,同时本实验也能够通过其它算法实现。
练手系列(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 }。
c语言中缀表达式转后缀表达式
c语言中缀表达式转后缀表达式如何将中缀表达式转换为后缀表达式。
一、前言在计算机科学中,表达式是一个常见且重要的概念。
表达式由运算符和运算数组成,用于执行各种计算任务。
在计算机程序设计中,我们经常需要对表达式进行解析和计算。
中缀表达式是我们最熟悉的表达式形式,其中运算符位于操作数之间。
例如,表达式2 + 3是一个中缀表达式。
然而,在计算机内部,中缀表达式并不是最方便的形式来进行计算。
因此,我们通常将中缀表达式转换为后缀表达式。
后缀表达式又称为逆波兰表达式,其中运算符位于操作数之后。
例如,上述的中缀表达式2 + 3在后缀表达式中表示为2 3 +。
本文将逐步介绍如何将中缀表达式转换为后缀表达式,并提供相应的C语言代码示例。
二、栈在开始之前,我们需要了解一个基本的概念:栈。
栈是一种具有特定特征的数据结构。
根据"先进后出"的原则,栈可以用来存储和检索数据。
栈有两个基本操作:入栈(push)和出栈(pop)。
当我们将元素放入栈中时,称为入栈操作。
出栈操作是将栈中最近添加的元素移除。
栈在中缀转后缀算法中起到了关键的作用。
我们将使用一个运算符栈来存储操作符,并使用一个输出队列来存储转换后的后缀表达式。
三、中缀转后缀算法概述中缀转后缀算法可以简要概括为以下几个步骤:1. 创建一个空的运算符栈和一个空的输出队列。
2. 从左到右扫描中缀表达式。
3. 如果遇到操作数,将其添加到输出队列中。
4. 如果遇到左括号,将其入栈。
5. 如果遇到右括号,则将栈中的运算符弹出并添加到输出队列中,直到遇到左括号为止。
然后,将左括号从栈中弹出,但不添加到输出队列中。
6. 如果遇到运算符,比较其与栈顶运算符的优先级:如果栈顶运算符优先级较高或相等,则将栈顶运算符弹出并添加到输出队列中。
重复此步骤,直到栈顶运算符的优先级低于当前运算符或栈为空。
然后,将当前运算符入栈。
7. 如果扫描完成,将栈中的所有运算符弹出并添加到输出队列中。
中缀转后缀表达式并求值C 程序
S.MaxSize=20;
S.stack=new ElemType[S.MaxSize];
if(!S.stack){
cerr<<"动态存储分配失败!"<<endl;
exit(1);
}
S.top=-1;
}
void Push(Stack& S, ElemType item) //元素item进栈,即插入到栈顶
{
if(str[i]==' ')
{i++; continue;}
switch(str[i])
{
case '+':
int m,n;
m=Pop(S);n=Pop(S);
x=m+n; //cout<<m<<" "<<n<<" "<<x<<endl;
i++; break;
case '-':
x=Pop(S);
ch=s1[++i];
}
else {
if((ch<'0'||ch>'9') && ch!='.') {
cout<<"中缀表达式表示错误!"<<endl;
exit(1);
}
while((ch>='0' && ch<='9') || ch=='.') {
s2[j++]=ch;
中缀表达式转后缀表达式并计算结果C语言版
{
int i = 0;
int tmpTop;
double num1,num2;
for(i = 0;i<topCal;i++)
{
stackCalBack[i] = stackCal[i];
}
i = 0;
tmpTop = topCal;
topCal = 0;
return stackCal+(--topCal);
}
/*****************************************************************
*计算表达式入栈
*****************************************************************/
break;
case ')':
while((tmpOper = stackOperPop()) != '(')
{
stackCalPush(tmpOper, IS_OPER);
}
pStr++;
islastNum = 0;
break;
case '0':case '1':case '2':case '3':case '4':
*操作符出栈
*****************************************************************/
char stackOperPop(void)
{
if(topOper == 0)return 0;
将中缀表达式转换为后缀表达式C程序
5 将中缀表达式转换为后缀表达式【问题描述】表达式转换。
输入的中缀表达式为字符串,转换得到的后缀表达式存入字符数组中并输出。
例如:a*(x+y)/(b-x) 转换后得:a x y + * b x - /【数据结构】●定义一个暂时存放运算符的转换工作栈opst。
●中缀表达式字符串char *infix;●后缀表达式字符串char *postfix;【算法提示】转换规则:把运算符移到它的两个操作数后面,删除掉所有的括号。
从头到尾扫描中缀表达式,对不同类型的字符按不同情况处理:●数字或小数点,直接写入字符串postfix,并在每个数值后面写入一个空格;●左括号,进栈,直到遇见相配的右括号,才出栈;●右括号,表明已扫描过括号内的中缀表达式,把从栈顶直到对应左括号之间的运算符依次退栈,并把结果推入栈内;●对于运算符,分两种情况处理:◆该运算符的优先级大于栈顶符号的优先级,则入栈;◆若该运算符的优先级小于栈顶优先级,则先弹出栈顶运算符、写入postfix串;继续将该运算符与栈顶运算符比较,直到能把它推入栈内为止(即优先级大于栈顶运算符)。
说明:自行设计运算符优先级的表示。
【主要代码】#include<iostream.h>#include<assert.h>#include<math.h>#include<string.h>const int stackIncreament=0;class opst{public:opst(int sz=50){maxSize=sz;top=-1;elements=new char[maxSize];assert(elements!=NULL);}~opst(){delete[]elements;}bool IsEmpty(){return (top==-1)?true:false;} bool IsFull(){return(top==maxSize-1)?true:false;}void Push( char &x);bool Pop(char &x);bool getTop(char &x);int getSize()const{return top+1;}void MakeEmpty(){top=-1;}void input();void Convert();friend ostream& operator<<(ostream &os,opst &s);private:char *elements;int top;int maxSize;void overflowProcess();};void opst::overflowProcess()//溢出处理{char *newArray=newchar[maxSize+stackIncreament];for(int i=0;i<=top;i++)newArray[i]=elements[i];maxSize=maxSize+stackIncreament; delete [] elements;elements=newArray;}void opst::Push(char &x){if(IsFull()==true) overflowProcess(); elements[++top]=x;}bool opst::Pop( char &x){if(IsEmpty()==true) return false;x=elements[top--];return true;}bool opst::getTop(char &x){if(IsEmpty()==true)return false;x=elements[top];return true;}ostream& operator<<(ostream &os,opst &s) {os<<"top=="<<s.top<<endl;for(int i=0;i<=s.top;i++)os<<s.elements[i];return os;}void opst::input(){char ch[20];cout<<"请输入中缀表达式(括号不能省略):"<<endl;cin.getline(ch,20);int i=0;while(ch[i]!='\0'){this->Push(ch[i]);i++;}ch[i]='#';}bool isdigit(char &x){if((x>='a'&&x<='z')||(x>='A'&&x<='Z')||(x>=' 0'&&x<='9'))return true;else return false;}int isp(char &x)//设置栈内优先级{switch(x){case '#':{return 0;break;}case '(':{return 1;break;}case '*':case '/':case '%':{return 5;break;}case '+':case '-':{return 3;break;}case ')':{return 6;break;}}}int icp(char &x)//设置栈外优先级{switch(x){case '#':{return 0;break;}case '(':{return 6;break;}case '*':case '/':case '%':{return 4;break;}case '+':case '-':{return 2;break;}case ')':{return 1;break;}}}void opst::Convert(){opst s;int i=0;char ch='#',ch1,op;s.Push(ch);this->Push(ch);elements[i];while(this->IsEmpty()==false&&elements[i]! ='#'){if(isdigit(elements[i])){cout<<elements[i];i++;}else{s.getTop(ch1);if(isp(ch1)<icp(elements[i])){s.Push(elements[i]);i++;}else if(isp(ch1)>icp(elements[i])){s.Pop(op);cout<<op;}else{s.Pop(op);if(op=='(') i++;}}}}void main(){opst a;a.input();cout<<"后缀表达式为:"<<endl;a.Convert();cout<<endl;}【实验过程】请输入中缀表达式(括号不能省略):(a+((b-c)/d))后缀表达式为:abc-d/+【实验体会】怎么样设置栈内外的优先级是解决这个程序的关键,我是用了开关语句来实现的。
C语言实现中缀表达式转换为后缀表达式
C语⾔实现中缀表达式转换为后缀表达式本⽂实例为⼤家分享了C语⾔实现中缀表达式转后缀表达式的具体代码,供⼤家参考,具体内容如下中缀表达式转换为后缀表达式(思路)1.创建栈2.从左向右顺序获取中缀表达式a.数字直接输出b.运算符情况⼀:遇到左括号直接⼊栈,遇到右括号将栈中左括号之后⼊栈的运算符全部弹栈输出,同时左括号出栈但是不输出。
情况⼆:遇到乘号和除号直接⼊栈,直到遇到优先级⽐它更低的运算符,依次弹栈。
情况三:遇到加号和减号,如果此时栈空,则直接⼊栈,否则,将栈中优先级⾼的运算符依次弹栈(注意:加号和减号属于同⼀个优先级,所以也依次弹栈)直到栈空或则遇到左括号为⽌,停⽌弹栈。
(因为左括号要匹配右括号时才弹出)。
情况四:获取完后,将栈中剩余的运算符号依次弹栈输出例:⽐如将:2*(9+6/3-5)+4转化为后缀表达式 2 9 6 3 / +5 - * 4 +转换算法代码如下:/*中缀转后缀函数*/void Change(SqStack *S,Elemtype str[]){int i=0;Elemtype e;InitStack(S);while(str[i]!='\0'){while(isdigit(str[i])){/*过滤数字字符,直接输出,直到下⼀位不是数字字符打印空格跳出循环 */printf("%c",str[i++]);if(!isdigit(str[i])){printf(" ");}}/*加减运算符优先级最低,如果栈顶元素为空则直接⼊栈,否则将栈中存储的运算符全部弹栈,如果遇到左括号则停⽌,将弹出的左括号从新压栈,因为左括号要和⼜括号匹配时弹出,这个后⾯单独讨论。
弹出后将优先级低的运算符压⼊栈中*/ if(str[i]=='+'||str[i]=='-'){if(!StackLength(S)){PushStack(S,str[i]);}else{do{PopStack(S,&e);if(e=='('){PushStack(S,e);}else{printf("%c ",e);}}while( StackLength(S) && e != '(' );PushStack(S,str[i]);}}/*当遇到右括号是,把括号⾥剩余的运算符弹出,直到匹配到左括号为⽌左括号只弹出不打印(右括号也不压栈)*/else if(str[i]==')'){PopStack(S,&e);while(e!='('){printf("%c ",e);PopStack(S,&e);}}/*乘、除、左括号都是优先级⾼的,直接压栈*/else if(str[i]=='*'||str[i]=='/'||str[i]=='('){PushStack(S,str[i]);}else if(str[i]=='\0'){break;}else{printf("\n输⼊格式错误!\n");return ;}i++;}/*最后把栈中剩余的运算符依次弹栈打印*/while(StackLength(S)){PopStack(S,&e);printf("%c ",e);}}完整代码如下:#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<assert.h>#define INITSIZE 20#define INCREMENT 10#define MAXBUFFER 20#define LEN sizeof(Elemtype)/*栈的动态分配存储结构*/typedef char Elemtype;typedef struct{Elemtype *base;Elemtype *top;int StackSize;}SqStack;/*初始化栈*/void InitStack(SqStack *S){S->base=(Elemtype*)malloc(LEN*INITSIZE);assert(S->base !=NULL);S->top=S->base;S->StackSize=INITSIZE;}/*压栈操作*/void PushStack(SqStack *S,Elemtype c){if(S->top - S->base >= S->StackSize){S->base=(Elemtype*)realloc(S->base,LEN*(S->StackSize+INCREMENT));assert(S->base !=NULL);S->top =S->base+S->StackSize;S->StackSize+=INCREMENT;}*S->top++ = c;}/*求栈长*/int StackLength(SqStack *S){return (S->top - S->base);}/*弹栈操作*/int PopStack(SqStack *S,Elemtype *c){if(!StackLength(S)){return 0;}*c=*--S->top;return 1;}/*中缀转后缀函数*/void Change(SqStack *S,Elemtype str[]){int i=0;Elemtype e;InitStack(S);while(str[i]!='\0'){while(isdigit(str[i])){/*过滤数字字符,直接输出,直到下⼀位不是数字字符打印空格跳出循环 */printf("%c",str[i++]);if(!isdigit(str[i])){printf(" ");}}/*加减运算符优先级最低,如果栈顶元素为空则直接⼊栈,否则将栈中存储的运算符全部弹栈,如果遇到左括号则停⽌,将弹出的左括号从新压栈,因为左括号要和⼜括号匹配时弹出,这个后⾯单独讨论。
中缀表达式转后缀表达式(代码实现)及前缀表达式思路补充
中缀表达式转后缀表达式(代码实现)及前缀表达式思路补充 后缀表达式适合计算机式的计算,因此在开发中,我们需要将中缀表达式转为后缀表达式。
三种表达式 这⾥再次区分⼀下前缀表达式、中缀表达式、后缀表达式(以(3+4)*5-6为例) 中缀表达式就是我们正常遇见的(3+4)*5-6这样的式⼦ 前缀表达式⼜称为波兰式,其运算符是在数之前 中缀表达式转前缀表达式思路:从右⾄左扫描表达式,遇到数字时,将数字压⼊堆栈,遇到运算符时,弹出栈顶的两个数,⽤运算符对它们做相应的计算(栈顶元素 top 次顶元素),并将结果⼊栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果 例如:- * + 3 4 5 61. 从右⾄左扫描,将6、5、4、3压⼊堆栈2. 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做⽐较),计算出3+4的值,得7,再将7⼊栈3. 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35⼊栈4. 最后是-运算符,计算出35-6的值,即29,由此得出最终结果中缀表达式转后缀表达式具体步骤 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中剩余的运算符依次弹出并压⼊s2 8)依次弹出s2中的元素并输出,结果的逆序为中缀表达式对应的后缀表达式举例说明 将中缀表达式"1+((2+3)*4)-5"转换为后缀表达式为:"1 2 3 + 4 * + 5 -"过程如下:举例代码package com.atxihua;import java.util.ArrayList;import java.util.List;import java.util.Stack;public class PolandNotation1 {public static void main(String[] args) {//完成将⼀个中缀表达式转成后缀表达式的功能//1+((2+3)*4)-5转成1 2 3 + 4 * + 5 -//因为直接对str进⾏操作,不⽅便,因此,先将1+((2+3)*4)-5存⼊对应的list//即1+((2+3)*4)-5=》ArrayList[1,+,(,(,2,+,3,),*,4),-,5]//将得到的中缀表达式对应的List=》后缀表达式对应的List//即ArrayList[1,+,(,(,2,+,3,),*,4),-,5]=>ArrayList[1,2,3,+,4,*,+,5,-]String expression="1+((2+3)*4)-5";List<String> infixExpreesionList=toInfixExpreesionList(expression);System.out.println("中缀表达式="+infixExpreesionList);//ArrayList[1,+,(,(,2,+,3,),*,4),-,5] List<String> suffixExpreesionList=parseSuffixExpreesionList(infixExpreesionList);System.out.println("后缀表达式="+suffixExpreesionList);//ArrayList[1,2,3,+,4,*,+,5,-]System.out.println("结果为:"+calculate(suffixExpreesionList));}//将中缀表达式转成对应的listprivate static List<String> toInfixExpreesionList(String s) {//定义⼀个List,存放中缀表达式对应的内容List<String> ls=new ArrayList<String>();int i=0;//⽤于遍历中缀表达式字符串String str;//⽤于拼接多位数char c;//每遍历到⼀个字符,就放到cdo{//如果c是⼀个⾮数字,我们需要加⼊到lsif((c=s.charAt(i))<48||(c=s.charAt(i))>57){ls.add(""+c);i++;}else {//如果是⼀个数,需要考虑多位数str="";//先将str设置为0[48]-9[57]while (i<s.length()&&(c=s.charAt(i))>=48&&(c=s.charAt(i))<=57){str+=c;//拼接i++;}ls.add(str);}}while (i<s.length());return ls;}//将得到的中缀表达式对应的List=>后缀表达式private static List<String> parseSuffixExpreesionList(List<String> ls) {//定义两个栈Stack<String> s1=new Stack<String>();//符号栈//说明:s2这个栈,在整个转换过程中,没有pop操作,⽽且后⾯需要逆序输出,就不使⽤栈,直接使⽤list存储//Stack<String> s2=new Stack<String>();//数栈List<String> s2=new ArrayList<String>();//存储中间结果的list//遍历lsfor(String item:ls){//如果是⼀个数,加⼊s2if(item.matches("\\d+")){s2.add(item);}else if(item.equals("(")){s1.push(item);}else if(item.equals(")")){//如果是右括号")",则依次弹出s1栈顶的运算符,并压⼊s2,直到遇到左括号为⽌,此时,将这⼀对括号丢弃while (!s1.peek().equals("(")){s2.add(s1.pop());}s1.pop();//将 ( 弹出s1栈,消除⼩括号}else {//当item的优先级⼩于等于s1栈顶运算符,将s1栈顶运算符弹出并加⼊到s2,直到遇到左括号为⽌,此时将这⼀对括号丢弃 //我们缺少⼀个⽐较优先级⾼低的⽅法while (s1.size()!=0&& Operation.getValue(s1.peek())>=Operation.getValue(item)){s2.add(s1.pop());}//还需要将item压⼊栈s1.push(item);}}//将s1中剩余的运算符依次弹出并加⼊s2while (s1.size()!=0){s2.add(s1.pop());}return s2;//}private static int calculate(List<String> ls) {//创建⼀个栈Stack<String> stack = new Stack<String>();//遍历lsfor(String item:ls){//使⽤正则表达式来取数if(item.matches("\\d+")){//匹配多为数//⼊栈stack.push(item);}else {//pop出两个数并运算,再⼊栈int num2=Integer.parseInt(stack.pop());int num1=Integer.parseInt(stack.pop());int res=0;if(item.equals("+")){res=num1+num2;}else if(item.equals("-")){//注意num2⽐num1先出栈,所以是num1-num2res=num1-num2;}else if(item.equals("/")){res=num1/num2;}else if(item.equals("*")){res= num1*num2;}else {throw new RuntimeException("运算符有误");}//把res⼊栈stack.push(""+res);}}//最后留在stack中的数据即运算结果return Integer.parseInt(stack.pop());}}//编写⼀个类Operation可以返回⼀个运算符,对应的优先级class Operation{private static int Add=1;private static int SUB=1;private static int MUL=2;private static int DIV=2;//写⼀个⽅法,返回对应的优先级数字public static int getValue(String operation){int result=0;if(operation.equals("+")){result=Add;}else if(operation.equals("-")){result=SUB;}else if(operation.equals("*")){result=MUL;}else if(operation.equals("/")){result=DIV;}else {System.out.println("不存在该运算符");}return result;}}运⾏结果因为我们在写代码时,遇到左括号时,压⼊栈中,在遇到右括号时在处理,因此,计算机将左括号当作运算符处理,在处理逻辑中只对加减乘除进⾏了处理,相信这点很容易理解,就不再处理了。
C#中缀表达式转换为后缀表达式算法及后缀表达式计算算法的实现
/*名称:中缀表达式转换为后缀表达式算法及后缀表达式计算算法的实现内容:1、掌握栈的存储结构的C语言描述2、掌握中缀表达式转换为后缀表达式的算法实现3、掌握后缀表达式计算算法的实现要求:程序功能包括:主程序;表达式的输入、转换;后缀表达式的输出、计算和数据的输出。
名称二叉树的建立与遍历及二叉树中序线索化及线索化遍历的实现内容掌握二叉树的建立与遍历的算法实现掌握二叉树中序线索化及线索化遍历的算法实现要求程序功能包括:主程序;二叉树的建立、二叉树的遍历(前序、中序、后序)、二叉树中序线索化、线索化遍历和输出等实验报告:程序流程图;上机通过的程序(清单);总结二叉树遍历的特点*//*函数:1、线索二叉树(左孩子、右孩子、左线索标志、右线索标志、双亲、数据域)2、建立二叉树3、前、中、后序扫描二叉树4、中序线索化二叉树5、中序遍历线索二叉树6、线索二叉树查找7、线索二叉树插入功能:1、二叉树的输入实现(输入根、左、右的顺序,当左或右为空时输入0,以‘#’结束输入)(输入优化)2、前、中、后序扫描二叉树输出扫描结果3、二叉树中序线索化4、二叉树线索化遍历/*#include <stdio.h>#include <stdlib.h>#include <conio.h>#define maxsize 100typedef char datatype;typedef struct node{int ltag,rtag;datatype data;struct node *lchild,*rchild;//*parent;} bitree;bitree *root;bitree *pre;bitree *Q[maxsize];bitree *creatree(){char ch;int front,rear;//队头、队尾指针bitree *root,*s;root=NULL;//置空二叉树front=1;rear=0;//置空队列printf("\t\t>>>请输入二叉树(无孩子输入'@'并以'#'结束):\n\t\t");ch=getchar();//输入第一个字符while(ch!='#')//不是结束符时重复做{s=NULL;if(ch!='@')//@表示虚结点,不是虚结点时建立新结点{s=(bitree *)malloc(sizeof(bitree));s->data=ch;s->lchild=NULL;s->rchild=NULL;s->ltag=0;s->rtag=0;}rear++;Q[rear]=s;//将虚结点指针NULL或新结点地址入队if(rear==1) root=s;//输入的第一个结点为根结点else{if(s && Q[front])//孩子和双亲结点均不是虚结点if(rear%2==0) Q[front]->lchild=s;//rear为偶数,新结点为左孩子else //rear为奇数Q[front]->rchild=s;//新结点是右孩子if(rear%2==1) front++;//结点*Q[front]的两个孩子已经处理完毕,出队列}ch=getchar();//输入下一个字符}return root;//返回根指针}//关于建立新树:输入处理(关于完全二叉树)//中序遍历void inorder(bitree *t){if(t)//二叉树非空{inorder(t->lchild);//中序遍历t的左子树printf("%c ",t->data);//访问结点tinorder(t->rchild);//中序遍历t的右子树}}//前序遍历void preorder(bitree *t){if(t)//二叉树非空{printf("%c ",t->data);//访问结点tpreorder(t->lchild);//中序遍历t的左子树preorder(t->rchild);//中序遍历t的右子树}}//后序遍历void postorder(bitree *t){if(t)//二叉树非空{postorder(t->lchild);//中序遍历t的左子树postorder(t->rchild);//中序遍历t的右子树printf("%c ",t->data);//访问结点t}}void inthread(bitree *p)//将二叉树p中序线索化,线索标志初值为0 {if(p!=NULL){inthread(p->lchild);//左子树线索化if(p->lchild==NULL) p->ltag=1;//建立左线索标志if(p->rchild==NULL) p->rtag=1;//建立右线索标志if(pre!=NULL){if(pre->rtag==1)//p无右子树pre->rchild=p;//右线索p->rchild为pif(pre->ltag==1)//p无左子树pre->lchild=pre;//左线索p->lchild为pre}pre=p;inthread(p->rchild);//右子树线索化}}//在中序线索树中找结点*p的中序后继bitree *inordernext(bitree *p){bitree *q;if(p->rtag==1)//p右子树为空return (p->rchild);//p->rchild是右线索,指向p的后继else //p的右子树非空{q=p->rchild;//从p的右孩子开始查找while(q->ltag==0)//当q不是左下结点时,继续查找q=q->lchild;return(q);}}//遍历中序线索二叉树pvoid travereinthread(bitree *p){if(p!=NULL)//非空树{while(p->ltag==0)//找中序序列的开始结点p=p->lchild;do{printf("%c ",p->data);//访问结点pp=inordernext(p);//找p的中序后继结点}while(p!=NULL);}}void main(){bitree *p;int a=0;printf("\t\t**********************************************\n");printf("\t\t ************二叉树************\n");printf("\t\t**********************************************\n\n");p=creatree();//创建二叉树printf("\n");printf("\t\t二叉树的前序遍历结果为:\n");//前序遍历printf("\t\t"); preorder(p); printf("\n");printf("\t\t二叉树的中序遍历结果为:\n");//中序遍历printf("\t\t"); inorder(p); printf("\n");printf("\t\t二叉树的后序遍历结果为:\n");//后序遍历printf("\t\t"); postorder(p); printf("\n");inthread(p);//中序线索化printf("\t\t二叉树的中序线索化遍历结果为:\n");//后序遍历printf("\t\t");travereinthread(p);//中序线索话遍历printf("\t\t");getch();}*//*//在结点p、p的右子树之间插入新结点qinsertright(bithptr *p,bithptr *q){bithptr *s;s=inordernext(p);//查找p的原中序后继结点q->ltag=1;//建立q的左线索标志q->lchild=p;//q的中序前趋为pq->rtag=p->rtag;q->rchild=p->rchild;//q的右子树或右线索等于原p的右子树或右线索p-ratag=0;p->rchild=q;//新结点q作为p的右孩子if((s!=NULL)&&(s->ltag==1))s->lchild=q;//结点s的左链是线索,s的前趋是p}*//*#include <stdio.h>#include <stdlib.h>#include <conio.h>#include <math.h>typedef struct node//定义栈结构体类型{bool n;//标志操作数和操作符char operate;//操作符float num; //操作数struct node *next;} stack;struct changenum//临时变量{bool w;float num;char op;stack *q;} ;stack *InitStack()//初始化堆栈{stack *S;S = (stack *)malloc(sizeof(stack));S->n=0;S->num=0;S->operate=0;S->next=NULL;return S;}stack *push(stack *top,bool n,float num,char operate)//进栈函数{stack *p;p=(stack *)malloc(sizeof(stack));//生成新节点if(n==0)//进栈的为浮点数{p->n=0;p->operate=NULL;p->num=num;}if(n==1)//进栈的为操作符{p->n=1;p->operate=operate;p->num=NULL;}p->next=top;top=p;return p;}changenum *pop(stack *top)//退栈函数{stack *p;changenum *sp;sp=(changenum *)malloc(sizeof(changenum));if(top->next==NULL) {printf("underflow!\n");return NULL;}//栈下溢else//退栈操作{p=top;top=top->next;sp->q=top;sp->num=p->num;sp->op=p->operate;sp->w=0;return sp;}}//*******************************************//****************栈定义及操作***************//后缀表达式的存储//*******************************************typedef struct node2{bool n;//标志操作数和操作符float num;//操作数char operate;//操作符struct node2 *front,*rear,*next;//队头队尾指针} squeue; //定义队列类型squeue *q;squeue *InitQueue()//初始化队列{squeue *Q;Q = (squeue *)malloc(sizeof (squeue));Q->n=0;Q->front=Q;Q->num=12345;Q->operate=0;Q->front->next=NULL;Q->rear =Q;return Q;}void enqueue(squeue *q,bool n,float number,char op)//入队操作{if(op==')') ;else{q->rear->next=(squeue *)malloc(sizeof(squeue));q->rear=q->rear->next;if(n==0){q->rear->n=0;q->rear->operate=NULL;q->rear->num=number;}if(n==1){q->rear->n=1;q->rear->operate=op;q->rear->num=NULL;}q->rear->next=NULL;}}changenum *dequeue(squeue *q)//出队操作{squeue *s;changenum *sp;sp=(changenum *)malloc(sizeof(changenum));if(q->front->next==NULL) {sp->num=q->num;sp->w=q->n;} else{s=q->front->next;q->front->next=s->next;sp->w=s->n;sp->num=s->num;sp->op=s->operate;}return sp;}//*******************************************//****************队定义及操作***************//实现表达式的临时存储//*******************************************int priority(char ch)//操作符及操作数优先级判断{switch(ch){case'+': case'-': return 2;case'*': case'/':return 3;case'(': case'#': return 1;case')': return 4;case ' ':return 10;case'.': case'0': case'1': case'2':case'3': case'4': case'5': case'6':case'7': case'8': case'9': return 0;default:printf("ERROR!"); return 5;}}changenum *getlist(char ch)//将字符数组转为float类型变量{changenum *sp;sp=(changenum *)malloc(sizeof(changenum));if(priority(ch)==0){sp->w=0;int p=1;float sum=0,point=0;char a[40];int m=0;int n=1;for(int i=0;i<=39;i++)a[i]=0;while(ch!='.'&&priority(ch)==0){a[m]=ch; sum=sum*10+(a[m]-'0'); m++;//整数部分ch=getchar();}if(ch=='.'){ch=getchar();while(priority(ch)==0)//小数部分处理{a[m+n]=ch; point=point*10+(a[m+n]-'0');p=p*10; n++;ch=getchar();}}sum=sum+point/p;//转为浮点数sp->num=sum;sp->op=ch;return sp;}else{sp->w=1;sp->num=100;sp->op=100;return sp;}}float change()//输入中缀表达式并转换为后缀表达式、输出后缀表达式并计算结果{stack *formula1;squeue *formula2,*formula4;stack *formula3;char a,ch;bool i; changenum *mark,*sign;formula2=InitQueue();formula4=InitQueue();formula1=InitStack();formula3=InitStack();formula3=push(formula3,1,0,'#');formula1=push(formula1,1,0,'#');printf("请输入表达式以#结束:\n");ch=getchar();do{mark=getlist(ch);i=mark->w;if(i==0){enqueue(formula2,0,mark->num,0);enqueue(formula4,0,mark->num,0);ch=mark->op;free(mark);/ /将操作数入队}else{switch(ch)//操作符处理{case '(' : formula1=push(formula1,1,0,ch); break; //将做括号压入栈Scase ')' :if(formula1->operate=='#') {printf("括号不匹配!!!\n");return 1;}else{do{sign=pop(formula1);formula1=sign->q;a=sign->op;if(a=='(') break;else if(priority(a)==4) ;else{enqueue(formula2,1,0,a);enqueue(formula4,1,0,a);}}while(a!='#');if(a=='#') {printf("括号不匹配!!!\n");return 1;}}case '+' :case '-' :case '*' :case '/' :while (formula1->operate!='#' && formula1->operate!='(' && priority(formula1->operate)>=priority(ch)){sign=pop(formula1);formula1=sign->q;enqueue(formula2,1,0,sign->op);enqueue(formula4,1,0, sign->op);}formula1=push(formula1,1,0,ch);break;case '#' : break;default: printf("ERROR!!!\n");return 1;}ch=getchar();}}while(ch!='#');//表达式扫描结束条件//表达式扫描结束后若栈中还有元素则依次弹出输入的后缀表达式中while (formula1->operate!='#'){sign=pop(formula1);formula1=sign->q;if(sign->op=='(') {printf("括号不匹配!!!\n");return 1;}else {enqueue(formula2,1,0,sign->op);enqueue(formula4,1,0,sign->op);}}printf("后缀表达式为:\n");do//后缀表达式的输出{mark=dequeue(formula2);if(mark->num==12345) break;if(mark->w==0){printf("%.3f",mark->num);free(mark);}else{printf("%c",mark->op);free(mark);}}while(1);printf("\n");/////////////////////////////////////////////////////////后缀表达式的计算////////////////////////////////////////////////////////float x,y;mark=dequeue(formula4);while (mark->num!=12345)//若队不为空{if (mark->w==0){formula3=push(formula3,0,mark->num,0);free(mark);}else{sign=pop(formula3);y =sign->num; formula3=sign->q;free(sign);//两次取操作数并交换次序sign=pop(formula3);x =sign->num; formula3=sign->q;free(sign);switch (mark->op)//计算周缀表达式的值{case '+' : formula3=push(formula3,0, x + y,0);break;case '-' : formula3=push(formula3,0, x - y,0);break;case '*' : formula3=push(formula3,0, x * y,0);break;case '/' : formula3=push(formula3,0, x / y,0);break;default:printf("ERROR!!!\n");return 0;}}mark = dequeue(formula4);//出队操作}printf("表达式的计算结果为:%.3f\n",pop(formula3)->num);return 0;}void main(){float sum;bool a;sum=change();//计算并转换后缀表达式getch();}*/。
c语言表达式求值中缀表达式转后缀表达式求值
c语⾔表达式求值中缀表达式转后缀表达式求值中转后具体转换⽅式:1.从左到右遍历需要计算的字符串2.若是运算数,直接压⼊后缀表达式栈3.若是左括号,直接压⼊运算符栈,(括号是最⾼优先级,⽆需⽐较)(⼊栈后优先级降到最低,确保其他符号正常⼊栈)4.若是右括号,(意味着括号已结束)不断弹出运算符栈顶运算符并输出到后缀表达式栈直到遇到左括号(弹出但不输出)5.运算符,将该运算符与运算符栈顶运算符进⾏⽐较,如果优先级⾼于栈顶运算符则压⼊运算符栈(该部分运算还不能进⾏),如果优先级低于等于栈顶运算符则将栈顶运算符弹出到后缀表达式栈然后⽐较新的栈顶运算符.(低于弹出意味着前⾯部分可以运算,先输出到后缀表达式栈⼀定是⾼优先级运算符,等于弹出是因为同等优先级,从左到右运算)直到优先级⼤于栈顶运算符或者栈空,再将该运算符⼊运算符栈6.如果字符串处理完毕,则按顺序从运算符栈弹出所有运算符到后缀表达式栈使⽤后缀表达式计算的⽅法:1、按顺序取后缀表达式的每个值2、若是数字则⼊栈3、若是操作符则从栈取出两个数字进⾏运算运算之后再将结果⼊栈4、循环上述过程知道后缀表达式结束栈顶元素(栈中只有⼀个元素)即为结果1 #include <windows.h>2 #include <stdio.h>3 #include <string.h>4 #include <malloc.h>5#define NUM 06#define OPERATION 17 typedef struct {//栈中的结点8int val;9int type;10 } Node;11 typedef struct {//栈12const char* name;//栈名13 Node* sta;//结点14int size;//最多存储多少个元素15int cnt;//当前存储了多少个元素16 } MyStack;17void trace(MyStack* s)//栈的遍历18 {19int i;20 printf("%s栈中的元素为:", s->name);21for (i = 0; i < s->cnt; i++) {22if (s->sta[i].type == NUM) {//若是数字23 printf("%d ", s->sta[i].val);24 }25else {//若是字符26 printf("%c ", (char)s->sta[i].val);27 }28 }29 printf("\n");30 }31void sFree(MyStack* s)//释放栈32 {33if (s->sta != NULL) {34 free(s->sta);35 s->sta = NULL;36 }37return;38 }39int sInit(MyStack* s, const char* name, int size)//初始化栈40 {41 s->name = name;42 s->size = size;43 s->sta = (Node*)calloc(s->size, sizeof(Node));//calloc申请后其中存的都是044if (s->sta == NULL) {45return -1;//分配失败46 }47 s->cnt = 0;//当前栈中元素有0个48return0;//分配成功49 }50void sPush(MyStack* s, Node item)//⼊栈⼀个元素51 {52if (s->cnt == s->size) {53 printf("栈空间不⾜\n");54return;55 }56 s->sta[s->cnt] = item;57 s->cnt++;58return;59 }60bool sIsEmpty(MyStack* s)//判断栈是否为空61 {62return s->cnt == 0;63 }64void sPop(MyStack* s, Node* item)//删除栈顶元素并返回值到item65 {66if (sIsEmpty(s)) {67return;68 }69 *item = s->sta[s->cnt - 1];70 s->cnt--;71return;72 }73void sTop(MyStack* s, Node* item)//获得栈顶元素到item 不删除栈顶袁术74 {75if (sIsEmpty(s)) {76return;77 }78 *item = s->sta[s->cnt - 1];79return;80 }81bool myIsNum(char ch)//判断是否是数字82 {83return ch >= '0' && ch <= '9';84 }85bool myIsOper(char ch)//判断是否是运算符86 {87return ch == '+' || ch == '-' || ch == '*' || ch == '/'||ch=='('||ch==')';88 }89//处理数值90void procNum(MyStack* postfix_expression, char* s, int len, int* pi)91 {92int i = *pi;//令i等于当前在处理的元素的坐标93int num=0;//当前数字的值具体是多少94 Node item_num;95while (myIsNum(s[i]))96 {97 num = num * 10 + s[i]-'0';98 i++;99 }100//新建结点101 item_num.type = NUM;102 item_num.val = num;103//数字直接⼊后缀表达式的栈104 sPush(postfix_expression, item_num);105 *pi = i-1;//改变calculate_postfix_expression 中i的值106return;107 }108//处理运算符109void procOper(MyStack* postfix_expression, MyStack* s_oper, char* s, int len, int* pi) 110 {111int i = *pi;112 Node item;113 Node top_item;114 Node pop_item;115if (s[i] == '(')//如果是( 直接存⼊运算符栈116 {117 item.type = OPERATION;118 item.val = s[i];119 sPush(s_oper, item);120 }121else if (s[i] == ')')//若是) 则弹出到(为⽌122 {123int flag = 0;//是否找到了 (124while (!sIsEmpty(s_oper)) {125 sPop(s_oper, &pop_item);126if (pop_item.val == '(') {//若找到了左括号退出127 flag = 1;128break;129 }130 sPush(postfix_expression, pop_item);//若未找到左括号则⼀直从运算符栈中pop131 }132if (!flag)133 {134 printf("括号不匹配!");135 exit(0);136 }137 }138//如果是乘除139else if (s[i] == '*' || s[i] == '/')140 {141 item.type = OPERATION;142 item.val = s[i];143while (!sIsEmpty(s_oper)) {144 sTop(s_oper, &top_item);145//如果当前运算符栈的栈顶是+ - (146//则* /级别较⾼则跳出循环147if (top_item.val == '+' || top_item.val == '-' || top_item.val == '(') {148break;149 }150//若当前运算符栈顶不是+ - ( 则是* /151//则需先把* / pop完152 sPop(s_oper, &pop_item);153 sPush(postfix_expression, pop_item);154 }155//才能将当* /⼊栈156 sPush(s_oper, item);157 }158//如果是 + -159else if (s[i] == '+' || s[i] == '-')160 {161 item.type = OPERATION;162 item.val = s[i];163while (!sIsEmpty(s_oper)) {164 sTop(s_oper, &top_item);165//如果当前运算符栈的栈顶是 (166//则当前运算符级别较⾼则跳出循环167if (top_item.val == '(') {168break;169 }170//若当前运算符栈顶不是 ( 则是+ - * /171//则需先把+ - * /pop完172 sPop(s_oper, &pop_item);173 sPush(postfix_expression, pop_item);174 }175//才能将当+ - ⼊栈176 sPush(s_oper, item);177 }178else179 {180 printf("输⼊了⾮空格⾮数字⾮运算符的元素 %c\n", s[i]);181 exit(0);182 }183return;184 }185//计算后缀表达式存储在s_trans中186void calculate_postfix_expression(MyStack* postfix_expression, MyStack* s_oper, char* s, int len) 187 {188int i;189int ret;190int num;191 Node item;192for (i = 0; i < len; i++) {193if (s[i] == '') {//当前输⼊为空格时跳过194continue;195 }196if (myIsNum(s[i])) {//当前是数字时197 procNum(postfix_expression, s, len, &i);198continue;199 }200if (myIsOper(s[i])) {//当前是运算符时进⼊运算的处理程序201 procOper(postfix_expression, s_oper, s, len, &i);202continue;203 }204 printf("输⼊了⾮空格⾮数字⾮运算符的元素 %c\n", s[i]);205 exit(0);206 }207//若运算栈不为空依次pop出运算栈中的元素再push到后缀表达式栈208while (!sIsEmpty(s_oper)) {209 sPop(s_oper, &item);210 sPush(postfix_expression, item);211 }212return;213 }214int cal(MyStack* postfix_expression, MyStack* s_num)//进⾏计算215 {216int i;217 Node n1, n2;218 Node item;219//顺序取出栈中的每个元素220for (i = 0; i < postfix_expression->cnt; i++) {221//item为后缀表达式中顺序取的第i个元素222 item = postfix_expression->sta[i];223//若⼀直是数字则⼀直放进数字栈224if (item.type == NUM) {225 sPush(s_num, item);226continue;//开始下⼀次循环227 }228//执⾏到这⾥证明不是数字是运算符了229 sPop(s_num, &n2);//从栈中拿出两个元素到n2 n1中230 sPop(s_num, &n1);231if (item.val == '+') {232 n1.val += n2.val;233 }234else if (item.val == '-') {235 n1.val -= n2.val;236 }237else if (item.val == '*') {238 n1.val *= n2.val;239 }240else {241 n1.val /= n2.val;242 }243 sPush(s_num, n1);//再将此次运算结果⼊数字栈244 }245return s_num->sta[0].val;//最后数字栈中的第⼀个元素就是计算结果246 }247int calculate(char* s) {//进⾏计算248int ret;249int len;250if (s == NULL||(len=strlen(s))==0) {251return0;252 }253 MyStack s_num;//数字栈254 MyStack s_oper;//运算符栈255 MyStack postfix_expression;//后缀表达式栈256if (sInit(&s_num, "数字", len)==-1||257 sInit(&s_oper, "运算符", len)==-1||258 sInit(&postfix_expression, "后缀表达式", len)==-1259 ) //若初始化三个栈失败的话则释放内存 return 0260 {261 sFree(&s_num);262 sFree(&postfix_expression);263 sFree(&s_oper);264return0;265 }266//计算后缀表达式267 calculate_postfix_expression(&postfix_expression, &s_oper, s, len); 268//显⽰后缀表达式269 trace(&postfix_expression);270//使⽤后缀表达是进⾏计算271 ret = cal(&postfix_expression, &s_num);272//释放栈的空间273 sFree(&postfix_expression);274 sFree(&s_oper);275 sFree(&s_num);276//返回结果277return ret;278 }279int main()280 {281char str[10000];282 scanf("%[^\n]", str);//可以输⼊空格回车停⽌输⼊283 printf("计算结果为%d\n", calculate(str));284 }285//例⼦ (((50+20)+(2*3))/14)。
将中缀表达式转换为后缀表达式并计算
将中缀表达式转换为后缀表达式并计算(总13页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--《数据结构》实验报告◎实验题目:使用键盘输入表达式,计算表达式的值并输出;将表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。
◎实验目的:使用栈的操作编写关于数据结构的程序。
◎实验内容:写出程序并上机调试、通过。
一、需求分析1、演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“请输入表达式”时输入中缀表达式。
然后计算机终端输出转换后的后缀表达式及计算后的结果。
2、程序执行的命令包括:(1)构造链栈;(2)输入数据;(3)判断输入的表达式是否为非法表达式;(4)将中缀表达式转换为后缀表达式;(5)计算表达式的值;(6)输出。
(7)结束4、本程序能将中缀表达式转换为后缀表达式,并且能计算表达式的值。
5、输入及输出示例:例1:请输入表达式6+3*(6+5)后缀表达式:6 3 6 5 + * +计算结果为:39Press any key to continue例2:请输入表达式6-3*(7+1ERROR:表达式错误Press any key to continue二概要设计1.基本操作(1)、struct node操作结果:创建结构体(2)、int Searchexpression(char string1[])初始条件:表达式string1已经存在。
操作结果:判断表达式是否非法(3)、struct node *Initialization()操作结果:创建栈链。
(4)、struct node *assort(struct node *s)初始条件:string1、string2已存在。
操作结果:将中缀表达式转换为后缀表达式并存在string2中。
(5)、struct node *calcolate(struct node *s)操作结果:求出表达式的值2、模块调用图三详细设计1、每个模块:(1) 定义结构体struct node{char data;int num;struct node *next;};(2) 判断表达式是否非法int Searchexpression(char string1[]){int i1,b1,b2;int m;m=strlen(string1);if(string1[0]<'0'||string1[0]>'9'){printf("ERROR:表达式缺操作数!\n");return(WRONG);}for(i1=0;i1<=m;i1++){if(string1[i1]=='(')b1++;elseif(string1[i1]==')')b2++;}if(b1!=b2){printf("ERROR:缺少括号\n");return(WRONG);}for(i1=0;i1<m;i1++)if('0'<=string1[i1]&&string1[i1]<='9'&&'0'<=string1[i1+1]&&stri ng1[i1+1]<='9'){ printf("ERROR:表达式缺操作符!\n");return(WRONG);}for(i1=0;i1<=m;i1++)if(string1[i1]=='+'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||string1[i1+1]=='*'||string1[i1+1]=='/')){ printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='-'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||string1[i1+1]=='*'||string1[i1+1]=='/')){ printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='*'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||string1[i1+1]=='*'||string1[i1+1]=='/')){printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='/'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||string1[i1+1]=='*'||string1[i1+1]=='/')){printf("ERROR:表达式缺操作数!\n");return(WRONG);}return(RIGHT);}(3)、将中缀表达式转换为后缀表达式struct node *assort(struct node *s)//输入字符串{struct node *p,*top;int i;top=s;int m;char a;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++; //比其高,现将栈顶运算符出栈,再进栈。
c 实现中缀表达式转后缀表达式比计算值
c 实现中缀表达式转后缀表达式比计算值C语言是一种广泛应用的编程语言,它具有高效、可移植、灵活等特点,在计算机科学领域有着广泛的应用。
中缀表达式是我们常见的数学表达方式,而将中缀表达式转换为后缀表达式是一项常见的任务。
本文将介绍如何使用C语言实现中缀表达式转后缀表达式,并计算其值。
我们需要了解中缀表达式和后缀表达式的概念。
中缀表达式是我们常见的数学表达方式,其中操作符位于操作数之间,如"3 + 4"。
而后缀表达式(也称为逆波兰表达式)是一种更加简洁的数学表达方式,其中操作符位于操作数之后,如"3 4 +"。
后缀表达式的计算更加简单直观,因此在计算机中更为常见。
接下来,我们需要实现一个函数来将中缀表达式转换为后缀表达式。
我们可以使用栈这一数据结构来辅助实现。
具体的步骤如下:1. 创建一个栈,用于存储操作符。
2. 遍历中缀表达式的每个字符。
3. 如果当前字符是操作数,直接输出。
4. 如果当前字符是操作符,并且栈为空,将操作符入栈。
5. 如果当前字符是操作符,并且栈不为空,比较当前操作符与栈顶操作符的优先级。
- 如果当前操作符的优先级大于栈顶操作符的优先级,将当前操作符入栈。
- 如果当前操作符的优先级小于等于栈顶操作符的优先级,将栈顶操作符出栈并输出,直到栈为空或者栈顶操作符的优先级小于当前操作符。
- 将当前操作符入栈。
6. 如果当前字符是左括号"(",将其入栈。
7. 如果当前字符是右括号")",将栈顶操作符出栈并输出,直到栈顶操作符为左括号"("。
8. 遍历结束后,将栈中剩余的操作符依次出栈并输出。
通过上述步骤,我们可以将中缀表达式转换为后缀表达式。
接下来,我们需要计算后缀表达式的值。
为了计算后缀表达式的值,我们可以使用另一个栈来辅助实现。
具体的步骤如下:1. 创建一个栈,用于存储操作数。
2. 遍历后缀表达式的每个字符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
For personal use only in study and research; not for c o m m e r c i a l u s e
5将中缀表达式转换为后缀表达式
【问题描述】表达式转换。
输入的中缀表达式为字符串,转换得到的后缀表达式存入字符数组中并输出。
例如:a*(x+y)/(b-x) 转换后得:a x y + * b x - /
【数据结构】
●定义一个暂时存放运算符的转换工作栈opst。
●中缀表达式字符串char *infix;
●后缀表达式字符串char *postfix;
【算法提示】转换规则:把运算符移到它的两个操作数后面,删除掉所有的括号。
从头到尾扫描中缀表达式,对不同类型的字符按不同情况处理:
●数字或小数点,直接写入字符串postfix,并在每个数值后面写入一个空格;
●左括号,进栈,直到遇见相配的右括号,才出栈;
●右括号,表明已扫描过括号内的中缀表达式,把从栈顶直到对应左括号之间的运算
符依次退栈,并把结果推入栈内;
●对于运算符,分两种情况处理:
◆该运算符的优先级大于栈顶符号的优先级,则入栈;
◆若该运算符的优先级小于栈顶优先级,则先弹出栈顶运算符、写入postfix串;继续将该
运算符与栈顶运算符比较,直到能把它推入栈内为止(即优先级大于栈顶运算符)。
说明:自行设计运算符优先级的表示。
【主要代码】
#include<iostream.h>
#include<assert.h>
#include<math.h>
#include<string.h>
const int stackIncreament=0; class opst
{
public:
opst(int sz=50)
{
maxSize=sz;
top=-1;
elements=new char[maxSize]; assert(elements!=NULL);
}
~opst(){delete[]elements;}
bool IsEmpty(){return (top==-1)?true:false;} bool IsFull(){return
(top==maxSize-1)?true:false;}
void Push( char &x);
bool Pop(char &x);
bool getTop(char &x);
int getSize()const{return top+1;}
void MakeEmpty(){top=-1;}
void input();
void Convert();
friend ostream& operator<<(ostream
&os,opst &s);
private:
char *elements;
int top;
int maxSize;
void overflowProcess();
};
void opst::overflowProcess()//溢出处理{
char *newArray=new
char[maxSize+stackIncreament];
for(int i=0;i<=top;i++)
newArray[i]=elements[i];
maxSize=maxSize+stackIncreament; delete [] elements;
elements=newArray;
}
void opst::Push(char &x)
{
if(IsFull()==true) overflowProcess(); elements[++top]=x;
}
bool opst::Pop( char &x)
{
if(IsEmpty()==true) return false;
x=elements[top--];
return true;
}
bool opst::getTop(char &x)
{
if(IsEmpty()==true)return false;
x=elements[top];
return true;
}
ostream& operator<<(ostream &os,opst &s) {
os<<"top=="<<s.top<<endl;
for(int i=0;i<=s.top;i++)
os<<s.elements[i];
return os;
}
void opst::input()
{
char ch[20];
cout<<"请输入中缀表达式(括号不能省略):"<<endl;
cin.getline(ch,20);
int i=0;
while(ch[i]!='\0')
{this->Push(ch[i]);i++;}
ch[i]='#';
}
bool isdigit(char &x)
{
if((x>='a'&&x<='z')||(x>='A'&&x<='Z')||(x>=' 0'&&x<='9'))
return true;
else return false;
}
int isp(char &x)//设置栈内优先级
{
switch(x)
{
case '#':
{return 0;break;}
case '(':
{return 1;break;}
case '*':
case '/':
case '%':
{return 5;break;}
case '+':
case '-':
{return 3;break;}
case ')':
{return 6;break;}
}
}
int icp(char &x)//设置栈外优先级
{
switch(x)
{
case '#':
{return 0;break;}
case '(':
{return 6;break;}
case '*':
case '/':
case '%':
{return 4;break;}
case '+':
case '-':
{return 2;break;}
case ')':
{return 1;break;}
}
}
void opst::Convert()
{
opst s;
int i=0;
char ch='#',ch1,op;
s.Push(ch);
this->Push(ch);
elements[i];
while(this->IsEmpty()==false&&elements[i]! ='#')
{
if(isdigit(elements[i]))
{
cout<<elements[i];
i++;
}
else
{
s.getTop(ch1);
if(isp(ch1)<icp(elements[i]))
{s.Push(elements[i]);i++;}
else if(isp(ch1)>icp(elements[i]))
{s.Pop(op);cout<<op;}
else
{
s.Pop(op);
if(op=='(') i++;
}
}
}
}
void main()
{
opst a;
a.input();
cout<<"后缀表达式为:"<<endl;
a.Convert();
cout<<endl;
}
【实验过程】
请输入中缀表达式(括号不能省略):
(a+((b-c)/d))
后缀表达式为:
abc-d/+
【实验体会】
怎么样设置栈内外的优先级是解决这个程序的关键,我是用了开关语句来实现的。
具体的转换算法,书上有。
仿照书上的实现,编写了Convert()函数。
这个程序编写起来比较顺利,编写过程中没有遇到什么非常大的问题。
最值得注意的是栈内优先级和栈外优先级的函数,我并没有在类内定义,我是在类外定义的。
所以调用的时候并不用某个对象来调用,而是直接在调用。
这就要注意成员函数和常规函数的区别。