编译原理 中缀表达式转换成后缀表达式,并按后缀表达式计算
编译原理——前缀后缀表达式

top--;
}
i--; //7)假如输入还未完毕,跳转到步骤2。
}
while(top!=0) //8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
{
output[j++]=stack[top];
top--;
}
}
int main()
{ char input[50],output[50]="";
6假如是开括号栈中运算符逐个出栈并输出直到遇到闭括号
输入一个中缀表达式转换为后缀和前缀,并求值C程序
待修改……
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define max 100
char ex[max]; /*存储后缀表达式*/
{
if(op=='+'||op=='-'||op=='*'||op=='/')
return true;
else
return false;
}
void convert(char *s,char *output) //将一个中缀串转换为后缀串,
{ int j=0;
strcpy(output,""); //输出串
while(stack[top]=='*'||stack[top]=='/')
{
ex[t]=stack[top];top--;t++;
}
中缀转后缀表达式计算报告

目录一、设计思想 (01)二、算法流程图 (02)三、源代码 (04)四、运行结果 (14)五、遇到的问题及解决 (16)六、心得体会 (16)一、设计思想(1)中缀表达式转后缀表达式并计算创建一个数组存储输入的计算表达式。
另创建一个数组储存将要生成的后缀表达式。
创建一个栈储存操作符。
对已存储的表达式数组扫描。
判断当前节点,如果是操作数或’.’,直接加入后缀表达式中,如果是操作符,则比较前一个操作符与当前操作符的优先级。
如果前一个操作符的优先级较高,则将前一个操作符加入后缀表达式中,否则将操作符压入操作符栈。
如果遇到左括号’(’,直接入栈;如果遇到右括号’)’,则在操作符栈中反向搜索,直到遇到匹配的左括号为止,将中间的操作符依次加到后缀表达式中。
当执行完以上操作,发现栈中仍有剩余操作符,则将操作符依次加到后缀表达式中。
此时中缀表达式已经转换成了后缀表达式。
对后缀表达式进行计算。
如果后缀表达式为大于0小于9的字符,则将它转换成浮点型数据并存入数栈中。
如果遇到操作符,则从数栈中提取两个数,进行相应的运算。
依次进行下去,当没有运算符是,运算结束得到最后的结果。
(2)直接表达式求值创建一个数组存储输入的计算表达式。
创建两个栈,一个字符型的栈,一个双精度型的栈。
分别用来存储字符和数。
对已存储的表达式数组扫描。
判断当前节点,如果是操作数和’.’,将字符型的操作数转换为浮点型的数后存入操作数栈。
如果是操作符则判断操作符的优先级。
如果字符栈中已存储符号的优先级小于要存入的字符的优先级,则直接让字符入操作符栈。
如果字符栈中已存储符号的优先级大于或等于要存入的字符的优先级,则取出操作符栈中的一个字符和操作数栈中的两个数进行计算,然后将结果存入操作数栈中,同上进行下去,直到字符栈中已存储符号的优先级小于要存入的字符的优先级时,将操作符存入操作符栈中。
当遇到左括号’(’,将左括号直接存入操作符栈中。
当遇到右括号’)’,则在操作符栈中反向搜索,并且每搜到一个字符就在操作数栈中取两个数进行相应的计算。
中缀转后缀并输出运算步骤

中缀转后缀并输出运算步骤从中缀表达式转换为后缀表达式的过程中,需要遵循一定的规则和算法。
下面将具体介绍中缀转后缀的步骤及其运算过程。
一、引言中缀表达式是我们日常生活中最常见的表达式形式,例如:2 + 3 * 4。
但是,对于计算机来说,中缀表达式并不方便进行计算,因此需要将其转换为后缀表达式。
后缀表达式也被称为逆波兰表达式,它的计算规则更加简单明了。
二、中缀转后缀的规则和算法1. 创建一个空的栈,用于存储运算符。
2. 从左到右遍历中缀表达式的每个元素。
3. 如果当前元素是操作数,则直接输出到后缀表达式。
4. 如果当前元素是左括号"(",则将其压入栈中。
5. 如果当前元素是右括号")",则将栈中的运算符依次弹出并输出到后缀表达式,直到遇到左括号为止。
注意:左括号不输出。
6. 如果当前元素是运算符,则判断栈顶运算符的优先级:- 若栈为空,则直接将当前运算符压入栈中。
- 若栈不为空,且当前运算符的优先级小于等于栈顶运算符的优先级,则将栈顶运算符弹出并输出到后缀表达式,直到栈为空或者栈顶运算符的优先级小于当前运算符。
- 将当前运算符压入栈中。
7. 遍历完中缀表达式后,如果栈中还有运算符,则依次弹出并输出到后缀表达式。
三、运算过程示例考虑中缀表达式:"2 + 3 * 4 - (5 + 6) / 7"1. 创建空栈和空后缀表达式。
2. 从左到右遍历中缀表达式的每个元素:- 遇到"2",为操作数,直接输出到后缀表达式。
- 遇到"+",为运算符,将其压入栈中。
- 遇到"3",为操作数,直接输出到后缀表达式。
- 遇到"*",为运算符,将其压入栈中。
- 遇到"4",为操作数,直接输出到后缀表达式。
- 遇到"-",为运算符,栈顶为"*",优先级高于"-",因此将"*"弹出并输出到后缀表达式,然后将"-"压入栈中。
算法笔记--中缀表达式转后缀表达式后缀表达式计算

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

else if(c=='(')
_push(&front,c);
else if(c==')')
{
data=_pop(&front);
}
while(data=_pop(&front))
{
postfix[k++]=(char)data;
}
postfix[k]='\0';
// printf("语法解析成功!\n");
return 1;
{
//如果操作符是*(乘法)
case '+':
return add(info,stack);break;
case '-':
return sub(info,stack);break;
for(i=0,k=0;i<len;++i)
{
c=input[i];
if(c>='a' &&c<='z' || c>='A' && c<='Z')
postfix[k++]=c;
else if(c>='0' && c<='9')
_push(&front,c);
}
else if(data=='+' || data=='-')
{
_push(&front,data);
中缀表达式转后缀表达式并求值C++数据结构链栈应用

#define SIZE 40
#include <string.h>
#include <iostream.h>
#include <stdlib.h>
#define MaxSize 32
{
*S.top++=e;
//cout<<e<<"已经被放入整数栈中"<<endl;
}
void Push(node& S,char e) //将运算符放入栈中
{
*S.top++=e;
//cout<<e<<"已经被放入字符栈中"<<endl;
};
struct list //整数栈
{
float *base;
float *top;
int size;
};
node m;list n; //定义两个对象
void Push2(list& S,float e) //将整数放入栈中的算法
{
int data;
struct LNode *next;
}Snode,*LinkStack;
void DestroyLinStack(LinkStack &S)
{//销毁链栈S。
LinkStack temp=S,p;
后缀表达式转换和计算

后缀表达式转换和计算将一个表达式转换成后缀表达式,并利用后缀表达式进行计算时,需要使用两个栈。
将一个中缀表达式转换成后缀表达式,需要用运算符栈进行;利用后缀表达式进行计算,则需要一个操作数栈。
转换时,首先定义各个运算符的优先级,才能根据规则实现转换。
具体程序如下:#include <malloc.h>#include <stdio.h>#include <ctype.h>#include <string.h>#define maxsize 100typedef struct sqstack{ /*运算符栈*/char stack[maxsize];int top;}sqstack;typedef struct sqstack2{ /*操作数栈*/int stack[maxsize];int top;}sqstack2;void Convert(char *exp,char *result);char op[6]={'+','-','*','/','(','#'}; /*运算符字符*/int pre[6]={1,1,2,2,0,-1}; /*运算符优先级*/void Initstack(sqstack *s){ /*运算符栈初始化*/s->top=0;}void Push(sqstack *s,char x){ /*运算符栈入栈*/if (s->top==maxsize-1) printf("Overflow1\n");else{s->stack[s->top]=x;s->top++;}}void Pop(sqstack *s,char *x){ /*运算符栈出栈*/if (s->top==0) printf("underflow1\n");else{s->top--;*x=s->stack[s->top];}}char Gettop(sqstack s){ /*运算符栈取栈顶元素*/ if (s.top==0){printf("underflow3\n");return 0;}else return s.stack[s.top-1];}void Initstack2(sqstack2 *s){ /*操作数栈初始化*/ s->top=0;}void Push2(sqstack2 *s,int x){ /*操作数栈入栈*/ if (s->top==maxsize-1) printf("Overflow2\n");else{s->stack[s->top]=x;s->top++;}}void Pop2(sqstack2 *s,int *x){ /*操作数栈出栈*/ if (s->top==0) printf("underflow2\n");else{s->top--;*x=s->stack[s->top];}}char f(char c){ /*定位运算符在对应数组的下标*/ switch (c) {case '+': return 0;case '-': return 1;case '*': return 2;case '/': return 3;case '(': return 4;case ')': return 5;default: return 6;}}int precede(char c1,char c2){ /*计算运算符优先级的大小*/int i1=f(c1);int i2=f(c2); /*找到字符在f数组中的位置,以方便确定其优先等级*/return pre[i1]-pre[i2];}int Operate(int a,char theta,int b){ /*对制定的操作数进行theta运算*/int sum;switch (theta) {case '+': sum=a+b; break;case '-': sum=a-b; break;case '*': sum=a*b; break;case '/': sum=a/b;}return sum;}void Convert(char *exp,char *result){ /*将中缀表达式串转换成后缀表达式串,用空格间隔各项*/sqstack OPTR;char c,x;int i=0;Initstack(&OPTR);Push(&OPTR,'#');while(*exp!='\0'){c=*exp++;if(isdigit(c)) { /*若为操作数,直接送后缀表达式*/while(isdigit(c)) {result[i++]=c;c=*exp++;}result[i++]=' ';exp--;continue;}if(c==')'){ /*若为')',出栈直至'('*/Pop(&OPTR,&x);while(x!='('){result[i++]=x;result[i++]=' ';Pop(&OPTR,&x);}continue;}if(c=='#'){ /*若为'#',出栈直至'#'*/Pop(&OPTR,&x);while(x!='#'){result[i++]=x;result[i++]=' ';Pop(&OPTR,&x);}break; /*表达式串处理结束*/}if(c=='(') { /*若为'(',直接入栈*/Push(&OPTR,c);continue;}else{ /*否则为运算符,与栈顶运算符比较*/if(precede(c,Gettop(OPTR))>0) Push(&OPTR,c); /*若优先级大于栈顶运算符,直接入栈*/else{ /*否则,优先级小于等于栈顶运算符*/Pop(&OPTR,&x); /*栈顶运算符出栈*/result[i++]=x;result[i++]=' ';while(precede(c,Gettop(OPTR))<=0){Pop(&OPTR,&x); /*栈顶运算符出栈*/result[i++]=x;result[i++]=' ';}Push(&OPTR,c);}continue;}}result[i++]='\0';}int Evalution(char *npl){sqstack2 OPND;int a,b,sum,result;char c;Initstack2(&OPND);while(*npl){c=*npl++;if(isdigit(c)){sum=0;while (isdigit(c)) {sum=sum*10+(c-'0');c=*npl++;}Push2(&OPND,sum);/*把数字串转化成十进制数字再压栈*/}else{Pop2(&OPND,&b);Pop2(&OPND,&a);Push2(&OPND,Operate(a,c,b));npl++;}}Pop2(&OPND,&result);return result;}int main(){char result[80],exp[80];printf("输入你的算术表达式,参与运算的都是正整数,不需输入等号,以#结束输入:\n");gets(exp); /*输入中缀表达式串*/Convert(exp,result); /*转换成后缀表达式串*/puts(result); /*输出后缀表达式串*/printf("The result is %d",Evalution(result)); /*利用后缀表达式计算并输出结果*/return 0;}。
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)。
c 实现中缀表达式转后缀表达式比计算值

c 实现中缀表达式转后缀表达式比计算值C语言是一种广泛应用的编程语言,它具有高效、可移植、灵活等特点,在计算机科学领域有着广泛的应用。
中缀表达式是我们常见的数学表达方式,而将中缀表达式转换为后缀表达式是一项常见的任务。
本文将介绍如何使用C语言实现中缀表达式转后缀表达式,并计算其值。
我们需要了解中缀表达式和后缀表达式的概念。
中缀表达式是我们常见的数学表达方式,其中操作符位于操作数之间,如"3 + 4"。
而后缀表达式(也称为逆波兰表达式)是一种更加简洁的数学表达方式,其中操作符位于操作数之后,如"3 4 +"。
后缀表达式的计算更加简单直观,因此在计算机中更为常见。
接下来,我们需要实现一个函数来将中缀表达式转换为后缀表达式。
我们可以使用栈这一数据结构来辅助实现。
具体的步骤如下:1. 创建一个栈,用于存储操作符。
2. 遍历中缀表达式的每个字符。
3. 如果当前字符是操作数,直接输出。
4. 如果当前字符是操作符,并且栈为空,将操作符入栈。
5. 如果当前字符是操作符,并且栈不为空,比较当前操作符与栈顶操作符的优先级。
- 如果当前操作符的优先级大于栈顶操作符的优先级,将当前操作符入栈。
- 如果当前操作符的优先级小于等于栈顶操作符的优先级,将栈顶操作符出栈并输出,直到栈为空或者栈顶操作符的优先级小于当前操作符。
- 将当前操作符入栈。
6. 如果当前字符是左括号"(",将其入栈。
7. 如果当前字符是右括号")",将栈顶操作符出栈并输出,直到栈顶操作符为左括号"("。
8. 遍历结束后,将栈中剩余的操作符依次出栈并输出。
通过上述步骤,我们可以将中缀表达式转换为后缀表达式。
接下来,我们需要计算后缀表达式的值。
为了计算后缀表达式的值,我们可以使用另一个栈来辅助实现。
具体的步骤如下:1. 创建一个栈,用于存储操作数。
2. 遍历后缀表达式的每个字符。
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();}*/。
数据结构中缀式中缀表达式改后缀表达式并求值

《数据结构》课程设计报告课程设计题目:中缀表达式改后缀表达式并求值一. 实验目的·掌握栈的特征及基本操作,如入栈、出栈等,栈的顺序存储结构和链式存储结构的实现,以便在实际问题中灵活应用。
·掌握栈的典型应用——中缀表达式转后缀表达式,并利用后缀表达式求值。
二. 实验内容(一)中缀表达式转后缀表达式的方法: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;}四. 算法时间复杂度。
中缀表达式转后缀表达式并计算结果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;
中缀表达式转化为后缀表达式算法

中缀表达式转化为后缀表达式算法首先需要分配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)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
后缀表达式的作用对于实现后缀表达式算法,难度并不大,但为什么要将看似简单的中缀表达式转换为复杂的后缀表达式?原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中缀表达式是非常复杂的结构。
相对的,后缀表达式在计算机看来却是比较简单易懂的结构。
中缀表达式转化成后缀表达式的计算

目录一、设计思想 (01)二、算法流程图 (02)三、源代码 (03)四、运行结果 (16)五、遇到的问题及解决 (17)六、心得体会 (18)一、设计思想第一种算法先把算术表达式转化成后缀表达式,在对后缀表达式进行计算。
首先建立一个符号栈,用于存放字符和字符的优先级别;然后在建立一个数栈,用于辅助后缀表达式的计算;最后在定义一个字符串数组,用于存放后缀表达式。
建立一个计算的函数,该函数用于两个数的计算,在调用这个函数的时候,传入三个参数,两个浮点型参数和一个字符型参数,根据不同的符号进行不同的计算。
定义一个判断优先级别的函数,用于判断两个操作符的优先级别,在根据优先级的不同决定不同的操作。
后缀表达式的取得,对算术表达式字符串进行挨个的扫描,如果是数字或者是小数点,则将数字或者小数点存放到字符数组中,每取完一个数字,则在后面用“|”隔开,如果是操作符,则和栈中得操作符进行比较,若扫描到的符号优先级比栈里的符号优先级低,则栈中元素出栈并存放到字符数组中。
每出一个字符到字符数组中就在后面加“|”分隔。
继续检查栈顶比较优先级,直到栈中元素优先级比扫描到的符号优先级低或者符号栈为空,则将此操作符入栈。
若是“(”则无条件入字符栈,若是“)”则从字符栈中出字符直到遇到“(”为止。
当字符数组扫描到最后的时候,计算并没有结束。
然后得进行字符栈的判断,看是否已经为空栈,若不是空栈,则出栈字符,将字符存放到数组中。
最后字符串数组中存放的就是后缀表达式。
得到后缀表达式后,要用数栈进行后缀表达式的计算,后缀表达式的计算中,对新的数组进行从道到尾的扫描,如果遇到数字,以“|”为标记取出完整的操作数,用辅助数组存放,然后转化成浮点数存放到数栈中,遇到“|”则直接将数组下标往后走。
遇到字符,则从数栈取出两个数进行计算,将计算的结果从新存放到数栈中,循环直到接到结束。
最后存放在数栈中的数就是计算的结果。
最后在主函数中调用此函数,进行结果的输出。
编译原理 中缀表达式转换成后缀表达式,并按后缀表达式计算

实验三中缀表达式转换成后缀表达式,并按后缀表达式计算[实验目的]对中缀表达式转换成后缀表达式,然后按后缀表达式计算进行分析与设计,并上机运行。
使学生能通该实验理解对一个简单表达式的编译实现过程。
[实验要求]要求对中缀表达式转换成后缀表达式,然后按后缀表达式计算作设计性实验,并上机运行,写出实验报告。
[实验时数]2学时。
[实验内容]中缀表达式转换成后缀表达式,然后按后缀表达式计算,例如:A*(B+C)/D-E*(F+G)。
[实验环境]硬件坏境:实验室209、一人一台机子。
软件坏境:Windows XP、Visual studio 6.0[算法描述及实验步骤]根据本实验内容的要求,实验要实现的是一个中缀表达式转换成后缀表达式并输出。
通过设计一个算法来实现以上实验。
[调试过程]运行Visual studio 6.0。
打开事先编写的程序:中缀到后缀.cpp。
在Visual studio 6.0环境下进编译、调试、运行。
多次重复无错误后,输出结果。
[实验结果][实验总结][附录]#include<stack>#include<iostream>using namespace std;bool prior(char op1,char op2) {bool ret=false;switch (op1){case'+':case'-':switch(op2){case'+':case'-':case'*':case'/':ret= false;break;case'#':case'(':ret = true;break;}break;case'*':case'/':switch(op2){case'#':case'+':case'-':case'(':ret= true;break;case'*':case'/':ret= false;break;}break;}return ret;}int main(int argc, char* argv[]){char s[]="A*(B+C)/D-E*(F+G)";int k;for(k=0;k<17;k++){cout<<s[k];}cout<<endl;stack<char> operS;//操¨´作Á¡Â符¤?栈?int i=0;operS.push('#');while(s[i]!='\0'){if(s[i]==' '){i++;continue;}if(s[i]>='A' && s[i]<'Z' ) //是º?字Á?母?{cout<<s[i];}else//不?是º?字Á?母?{switch(s[i]){case'+':case'-':case'*':case'/':if(prior(s[i],operS.top()))//比À¨¨栈?顶£¤优®?先¨¨级?高?,直¡À接¨®进?栈?{operS.push(s[i]);}else if(operS.top()!='(') //比À¨¨栈?顶£¤优®?先¨¨级?低̨ª,ê?先¨¨出?栈?,s[i]进?栈?{cout<<operS.top();operS.pop();operS.push(s[i]);}break;case'(': //直¡À接¨®进?栈?operS.push(s[i]);break;case')': //匹£¤配?栈?内¨²的Ì?'(',都?出?栈?,ê?并¡é删¦?除y'(' while(operS.top()!='('){cout<<operS.top();operS.pop();}operS.pop();break;case'#':break;}}i++;}while(!operS.empty()){cout<<operS.top();operS.pop();}cout<<endl;int a;cin >> a;return 0;}[教师评语]。
将中缀表达式转换为后缀表达式并计算

《数据结构》实验报告◎实验题目:使用键盘输入表达式,计算表达式的值并输出;将表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。
◎实验目的:使用栈的操作编写关于数据结构的程序。
◎实验内容:写出程序并上机调试、通过。
一、需求分析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]&&str ing1[i1+1]<='9'){ printf("ERROR:表达式缺操作符!\n");return(WRONG);}for(i1=0;i1<=m;i1++)if(string1[i1]=='+'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||stri ng1[i1+1]=='*'||string1[i1+1]=='/')){ printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='-'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||strin g1[i1+1]=='*'||string1[i1+1]=='/')){ printf("ERROR:表达式缺操作数!\n");return(WRONG);}elseif(string1[i1]=='*'&&(string1[i1+1]=='+'||string1[i1+1]=='-'||strin g1[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++; //比其高,现将栈顶运算符出栈,再进栈。
编译原理中缀式转换为后缀式,词法分析,语法分析,中间代码

#include<math.h> #include<stdlib.h>#include<fstream>#include<iostream>#include<stdio.h>#include<malloc.h>#include<string.h>#define MAX 60#define DEMAX 15#define NULL 0char string1[MAX];char string2[MAX];int j=0;using namespace std;#define MAX 100char inputstream[50];//存储输入句子int temp1=0;//数组下标int right1;//判断输出信息int m2=0,sum2=0;//sum用于计算运算符的个数//m用于标记输入表达式中字符的个数char JG='A';char str[MAX];//用于存输入表达式int tokene=0;//左括号的标志char prog1[80],token1[8],ch1;int syn1,p1,m1,n1,sum1;char *rwtab1[6]={"begin","if","then","while","do","end"}; int r1 ;char prog[80]; //存放所有输入字符char token[8]; //存放词组char ch; //单个字符int syn,p,m,n,i;//syn:种别编码double sum;int count;int isSignal; //是否带正负号(0不带,1负号,2正号)int isError;int isDecimal; //是否是小数double decimal;//小数int isExp;//是否是指数int index;//指数幂int isNegative; //是否带负号double temp;int temp2;int repeat; //是否连续出现+,-int nextq;int kk; //临时变量的标号int ntc,nfc,nnc,nnb,nna;char *rwtab[9]={"main","int","float","double","char","if","else","do","while"}; struct{char result[10]; //字符串(字符数组)char arg1[10];char opera[10];char arg2[10];}fourCom[20]; //结构体数组cifafenxi();yufafenxi();zhongjiandaima();scaner1();void e();void e1();void t();void t1();void f();void lrparser();void staBlock(int *nChain); //语句块void staString(int *nChain); //语句串void sta(int *nChain); //语句void fuzhi(); //赋值语句void tiaojian(int *nChain); //条件语句void xunhuan(); //循环语句char* E(); //Expresiion表达式char* T(); //Term项char* F(); //Factor因子char *newTemp(); //自动生成临时变量void backpatch(int p,int t); //回填int merge(int p1,int p2); //合并p1和p2void emit(char *res,char *num1,char *op,char *num2); //生成四元式void scanner(); //扫描void lrparser(){int nChain;nfc=ntc=1;nextq=1;if(syn==1) //main {scanner();if(syn==26) //({scanner();if(syn==27) //){scanner();staBlock(&nChain);}elseprintf("缺少右括号\n");}else }else printf("缺少左括号\n");printf("缺少main\n");}//<语句块> ::= '{'<语句串>'}'void staBlock(int *nChain) //语句块{if(syn==28) //{{scanner();staString(nChain);//backpatch(*nChain,nextq);if(syn==29) //}scanner();//读下一个elseprintf("缺少}号\n");}elseprintf("缺少{号\n");}//<语句串>::=<语句>{;<语句>};void staString(int *nChain) //语句串{sta(nChain);backpatch(*nChain,nextq);while(syn==31) //;{scanner();sta(nChain);}//backpatch(*nChain,nextq-1);}void sta(int *nChain) //语句{if(syn==10){fuzhi();//*nChain=0;}else if(syn==6) //if {tiaojian(nChain);}else if(syn==8) //doxunhuan();}//<条件语句>->if(<条件>)<语句块>void tiaojian(int *nChain){char res[10],num1[10],num2[10],op[10];int nChainTemp;//<条件>-><表达式><关系运算符><表达式> if(syn==6) //if {scanner();//strcpy(num1,E());if(syn==26) //({}scanner();strcpy(num1,E());if((syn<=37)&&(syn>=32)){switch(syn){case 32: strcpy(op,">");break;case 33:strcpy(op,">=");break;case 34:strcpy(op,"<");break;case 35:strcpy(op,"<=");break;case 36:strcpy(op,"==");break;case 37:strcpy(op,"!=");break;default:printf("error");}}scanner();strcpy(num2,E());strcat(num1,op);strcat(num1,num2);//nfc=nextq+1;ntc=nextq; //记住if语句位置emit("0","if",num1,"goto");nfc=nextq; //if中表达式为假emit("0","","","goto");//第一个0已回填backpatch(ntc,nextq); //ntc链接的所有四元式都回填nextq }}if(syn==27)//)scanner();staBlock(&nChainTemp); //语句块*nChain=merge(nChainTemp,nfc);//<循环语句>::=do <语句块>while <条件>void xunhuan(){char res[10],num1[10],num2[10],op[10];int nChainTemp;if(syn==8) //do {nnc=nextq; //记住if语句位置,emit之后nextq就变了//emit("0","if",num1,"goto");scanner();staBlock(&nChainTemp); //语句块if(syn==9) //while {scanner();if(syn==26) //({scanner();strcpy(num1,E());if((syn<=37)&&(syn>=32)){switch(syn){case 32:strcpy(op,">");break;case 33:strcpy(op,">=");break;case 34:strcpy(op,"<");break;case 35:strcpy(op,"<=");break;case 36:strcpy(op,"==");break;case 37:strcpy(op,"!=");break;default:printf("error");}}scanner();strcpy(num2,E());strcat(num1,op);strcat(num1,num2);nnb=nextq;emit("0","if",num1,"goto");backpatch(nnb,nnc);nna=nextq;emit("0","","","goto");backpatch(nna,nextq);}if(syn==27)//)scanner();}}}void fuzhi() //赋值语句只有1个操作数{char res[10],num[10]; //num操作数if(syn==10) //字符串{strcpy(res,token); //结果scanner();if(syn==21) //={scanner();}}strcpy(num,E());emit(res,num,"=","");}else {}printf("缺少=号\n");char* E() //Expression表达式{char *res,*num1,*op,*num2; res=(char *)malloc(10);num1=(char *)malloc(10);op=(char *)malloc(10);num2=(char *)malloc(10);strcpy(num1,T());while((syn==22)||(syn==23)) //+ -{if(syn==22) //+strcpy(op,"+");elsestrcpy(op,"-");scanner();strcpy(num2,T());strcpy(res,newTemp());emit(res,num1,op,num2);strcpy(num1,res);}return num1;}char* T() //Term项{char *res,*num1,*op,*num2;res=(char *)malloc(10);num1=(char *)malloc(10);op=(char *)malloc(10);num2=(char *)malloc(10);strcpy(num1,F());while((syn==24)||(syn==25)) //* /{if(syn==24)}strcpy(op,"*");elsestrcpy(op,"/");scanner();strcpy(num2,F());strcpy(res,newTemp());emit(res,num1,op,num2);strcpy(num1,res);}return num1;char* F() //Factor因子{char *res;res=(char *)malloc(10);if(syn==10) //字符串{strcpy(res,token);scanner();}else if(syn==20) //二进制数{itoa((int)sum,res,10); //整数转换为字符串scanner();}else if(syn==26) //({scanner();res=E();if(syn==27) //){scanner();}else isError=1;}elseisError=1;return res;}char *newTemp(){char *p;}char varTemp[10];p=(char *)malloc(10);kk++;itoa(kk,varTemp,10);strcpy(p+1,varTemp);p[0]='T';return p;//将p所链接的每个四元式的第四个分量都回填tvoid backpatch(int p,int t){int w,circle=p;while(circle) //circle不为0的时候{w=atoi(fourCom[circle].result); //四元式circle第四分量内容//strcpy(fourCom[circle].result,t); //把t填进四元式circle的第四分量sprintf(fourCom[circle].result,"%d",t);circle=w; //w记录的是链条上下一个四元式,移动!}return;}int merge(int p1,int p2) //合并p1和p2{char circle,nResult;if(p2==0)nResult=p1;else {nResult=circle=p2;while(atoi(fourCom[circle].result)) //四元式第四个分量不为0{circle=atoi(fourCom[circle].result);//strcpy(fourCom[circle].result,p1);sprintf(fourCom[circle].result,"%s",p1);}//目的是用p1的值覆盖0}return nResult; //p2是头,p1覆盖0,接在p2后边}void emit(char *res,char *num1,char *op,char *num2){strcpy(fourCom[nextq].result,res);strcpy(fourCom[nextq].arg1,num1);strcpy(fourCom[nextq].opera,op);strcpy(fourCom[nextq].arg2,num2);nextq++;}void scanner(){sum=0;decimal=0;m=0;for(n=0;n<8;n++)token[n]=NULL;ch=prog[p++]; //从prog中读出一个字符到ch中while(ch==' '||ch=='\n')//跳过空字符(无效输入)if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))) //ch是字母字符{while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9'))){token[m++]=ch; //ch=>tokench=prog[p++]; //读下一个字符}token[m++]='\0';p--; //回退一格syn=10; //标识符//如果是"begin","if","then","while","do","end"标识符中的一个for(n=0;n<9;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0')&&(ch<='9')){IsNum:if(isSignal==1){//token[m++]='-';}while((ch>='0')&&(ch<='9')){sum=sum*10+ch-'0'; //ch中数字本身是当做字符存放的ch=prog[p++];}if(ch=='.'){isDecimal=1;ch=prog[p++];count=0; //之前忘了清零,123.123+123.123#两个浮点数就无法识别while((ch>='0')&&(ch<='9')){//pow(x,y)计算x的y次幂temp=(ch-'0')*pow(0.1,++count);decimal=decimal+temp;//AddToDec();ch=prog[p++];}sum=sum+decimal;}if(ch=='e'||ch=='E'){isExp=1;if(ch=='-'){isNegative=1;ch=prog[p++];}while((ch>='0')&&(ch<='9')){//指数index=index*10+ch-'0';ch=prog[p++];}//10的幂//123e3代表123*10(3)//sum=sum*pow(10,index);是错误的if(isNegative)sum=sum*pow(0.1,index);elsesum=sum*pow(10,index);}if(isSignal==1){sum=-sum; isSignal=0;}p--;syn=20;}else switch(ch){case '<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=35;token[m++]=ch;}else {syn=34;p--;}break;case '>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=33;token[m++]=ch;}else {syn=32;p--;}break;case '=':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=36;token[m++]=ch;}else {syn=21;p--;}break;case '+':temp2=prog[p];token[m++]=ch;if((temp2>='0')&&(temp2<='9')&&(repeat==1)){isSignal=2; ch=prog[p++];repeat=0;goto IsNum;}if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) 的+,-视为正负号{repeat=1;//ch=prog[p++];}syn=22;break;case '-'://如果重复出现符号,才将后边temp2=prog[p];token[m++]=ch;if((temp2>='0')&&(temp2<='9')&&(repeat==1)){isSignal=1;ch=prog[p++]; //读"-"下一个字符repeat=0;goto IsNum;//转到数字的识别}if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) 的+,-视为正负号{repeat=1;//预言会重复//ch=prog[p++];//读下一个字符}syn=23;break;case '*':temp2=prog[p];token[m++]=ch;if(temp2=='+'){isSignal=2;repeat=1;}else if(temp2=='-'){isSignal=1;repeat=1;}syn=24;break;case '/':token[m++]=ch;break;case '(':temp2=prog[p];token[m++]=ch;//如果重复出现符号,才将后边if(temp2=='+'){isSignal=2;repeat=1;}else if(temp2=='-'){isSignal=1;repeat=1;}syn=26;break;case ')':syn=27;token[m++]=ch;break;case '{':syn=28;token[m++]=ch;break;case '}':syn=29;token[m++]=ch;case ',':syn=30;token[m++]=ch; break;case ';':syn=31;token[m++]=ch; break;case'#':syn=0;token[m++]=ch; break; default:syn=-1;}} zhongjiandaima(){ p=0;count=0; isDecimal=0; index=0;repeat=0;kk=0;printf("\nPlease input your source string:\n");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;isError=0;scanner();lrparser();for(i=1;i<nextq;i++) //循环输出四元式{printf("\n%d\t",i);printf("(%3s,%3s,%3s,%3s)\n",fourCom[i].opera,fourCom[i].arg1,fourCom[i].arg 2,fourCom[i].result);}return;}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;//char * string1scanf("%s",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++; //比其高,现将栈顶运算符出栈,再进栈。
中缀表达式转后缀表达式并计算结果

中缀表达式转后缀表达式并计算结果⽬录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、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三中缀表达式转换成后缀表达式,并按后缀表达式计算[实验目的]
对中缀表达式转换成后缀表达式,然后按后缀表达式计算进行分析与设计,并上机运行。
使学生能通该实验理解对一个简单表达式的编译实现过程。
[实验要求]
要求对中缀表达式转换成后缀表达式,然后按后缀表达式计算作设计性实验,并上机运行,写出实验报告。
[实验时数]
2学时。
[实验内容]
中缀表达式转换成后缀表达式,然后按后缀表达式计算,例如:A*(B+C)/D-E*(F+G)。
[实验环境]
硬件坏境:实验室209、一人一台机子。
软件坏境:Windows XP、Visual studio 6.0
[算法描述及实验步骤]
根据本实验内容的要求,实验要实现的是一个中缀表达式转换成后缀表达式并输出。
通过设计一个算法来实现以上实验。
[调试过程]
运行Visual studio 6.0。
打开事先编写的程序:中缀到后缀.cpp。
在Visual studio 6.0环境下进编译、调试、运行。
多次重复无错误后,输出结果。
[实验结果]
[实验总结]
[附录]
#include<stack>
#include<iostream>
using namespace std;
bool prior(char op1,char op2) {
bool ret=false;
switch (op1)
{
case'+':
case'-':
switch(op2)
{
case'+':
case'-':
case'*':
case'/':
ret= false;break;
case'#':
case'(':
ret = true;break;
}
break;
case'*':
case'/':
switch(op2)
{
case'#':
case'+':
case'-':
case'(':
ret= true;break;
case'*':
case'/':
ret= false;break;
}
break;
}
return ret;
}
int main(int argc, char* argv[])
{
char s[]="A*(B+C)/D-E*(F+G)";
int k;
for(k=0;k<17;k++)
{
cout<<s[k];
}
cout<<endl;
stack<char> operS;//操¨´作Á¡Â符¤?栈?
int i=0;
operS.push('#');
while(s[i]!='\0')
{
if(s[i]==' ')
{
i++;
continue;
}
if(s[i]>='A' && s[i]<'Z' ) //是º?字Á?母?
{
cout<<s[i];
}
else//不?是º?字Á?母?
{
switch(s[i])
{
case'+':
case'-':
case'*':
case'/':
if(prior(s[i],operS.top()))//比À¨¨栈?顶£¤优®?先¨¨级?高?,直¡À接¨®进?栈?
{
operS.push(s[i]);
}
else if(operS.top()!='(') //比À¨¨栈?顶£¤优®?先¨¨级?低̨ª,ê?先¨¨出?栈?,s[i]进?栈?
{
cout<<operS.top();
operS.pop();
operS.push(s[i]);
}
break;
case'(': //直¡À接¨®进?栈?
operS.push(s[i]);
break;
case')': //匹£¤配?栈?内¨²的Ì?'(',都?出?栈?,ê?并¡é删¦?除y'(' while(operS.top()!='(')
{
cout<<operS.top();
operS.pop();
}
operS.pop();
break;
case'#':
break;
}
}
i++;
}
while(!operS.empty())
{
cout<<operS.top();
operS.pop();
}
cout<<endl;
int a;
cin >> a;
return 0;
}
[教师评语]。