将中缀表达式转换为后缀表达式-C++程序
将中缀表达式转换为后缀表达式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语⾔实现中缀表达式转后缀表达式代码如下:#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define STACK_INIT_SIZE 20#define STACKINCREMENT 10typedef char ElemType;typedef struct {ElemType *base;ElemType *top;int StackSize;}sqStack;void InitStack(sqStack *s){s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));if( !s->base ){exit(0);}s->top = s->base;s->StackSize = STACK_INIT_SIZE;}void push(sqStack *s,ElemType e) {if( s->top - s->base >= s->StackSize){s->base = (ElemType *)realloc(s->base,(s->StackSize+STACKINCREMENT)*sizeof(ElemType));if( !s->base ){exit(0);}}*(s->top) = e;s->top++;}void pop(sqStack *s,ElemType *e){if( s->top == s->base){return;}*e = *--(s->top);}int Stacklen(sqStack s){return (s.top-s.base);}int main(){sqStack s;char c, e;InitStack(&s);printf("请输⼊中缀表达式,以#作为结束标志:");scanf("%c",&c);while( c != '#' ){while ( c>='0' && c<='9' ){printf("%c",c);scanf("%c",&c);if (c<'0'||c>'9'){printf("");}}if ( ')' == c ){pop(&s, &e);while( '(' != e ){printf("%c ",e);pop(&s,&e);}}else if ( '+'==c || '-'==c){if ( !Stacklen(s) ){push(&s,c);}else{do{pop(&s,&e);if ( '('==e ){push(&s,e);}else{printf("%c ",e);}}while( Stacklen(s) && '('!=e ); push(&s,c);}}else if ( '*'==c || '/'==c || '('==c ){push(&s,c);}else if ('#'==c) {break;}else{printf("出错,输⼊格式错误\n");return -1;}scanf("%c",&c);}while( Stacklen(s) ){pop(&s,&e);printf("%c ",e);}return0;}运⾏结果:。
c语言实现中缀、后缀、前缀表达式相互转化并求值

1.问题描述(1)表达式求值问题表达式是数据运算的基本形式。
人们的书写习惯是中缀式,如:11+22*(7-4)/3 。
中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。
表达式还有后缀式(如:2274-*3/11+)和前缀式(如: + 11 / * 22–7 4 3)。
后缀表达式和前缀表达式中没有括号,给计算带来方便。
如后缀式计算时按运算符出现的先后进行计算。
本设计的主要任务是进行表达式形式的变换及不相同形式的表达式计算。
2.数据结构设计( 1)表达式求值问题由于表达式中有字符与数字两各种类,故定义结点一个标志域 data ,标志结点储藏的为字符 data=2 还是数字 data=1 ,再搜寻结点中对应的储藏地址,读取数字域 data1, 字符域 data2 。
而在前缀表达式时,存在表达式逆序,因表达式种类不一致,用栈逆序极不方便,选择成立双向链表,储藏表达式。
typedef struct Node//定义储藏中缀表达式的结点种类{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2//定义储藏前缀表达式的结点种类{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;3. 运行、测试与解析( 1)表达式求值问题(1)按提示输入中缀表达式,以下列图。
如输入中缀表达式不正确,提示输入有误,如图 , 所示。
图图图(2)选择表达式变换并求值方式。
按“1”选择中缀表达式求值,以下列图。
图(3)按“ 2”选择中缀表达式转变为后缀表达式并求值,以下列图。
图(4)按“ 3”选择中缀表达式转变为前缀表达式并求值,以下列图。
图附录:源代码( 1)表达式求值问题#include<>#include<>#define MAXNUM 100typedef struct Node//定义储藏中缀表达式的结点种类{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2//定义储藏前缀表达式的结点种类{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;typedef int selemtype1;//定义运算数栈的结点typedef struct //定义运算数栈的种类{selemtype1 *base;selemtype1*top; }sqstack1;void InitStack1(sqstack1 &s) //新建一个空运算数栈{=(selemtype1 *)malloc(MAXNUM*sizeof(selemtype1));=;if(! printf("出错:申请空间失败!\n");}void Push1(sqstack1 &s,selemtype1 &e)//运算数栈,入栈:插入元素 e 为新的栈顶元素{ if printf("出错:表达式过长!1\n");*++=e;}void GetTop1(sqstack1 s,selemtype1 &e) //运算数栈,用e返回栈顶元素{e=*;}void Popopnd1(sqstack1 &s,selemtype1 &e) // 运算数栈,退栈:删除栈顶元素,并用 e 返回其值{e=*;}int stackempy1(sqstack1 s) // 运算数栈,若为空栈返回 1,否则返回 0 {if== return 1;else return 0;}typedef char selemtype2;//定义运算符栈的结点种类typedef struct //定义运算符栈种类{selemtype2 *base;selemtype2*top; }sqstack2;void InitStack2(sqstack2 &s) //新建一个空运算符栈{=(selemtype2 *)malloc(MAXNUM*sizeof(selemtype2));=;if(! printf("出错:申请空间失败!\n");}void Push2(sqstack2 &s,selemtype2 &e)//运算符栈,入栈:插入元素 e 为新的栈顶元素{ if printf("出错:表达式过长!2\n");*++=e;}void GetTop2(sqstack2 s,selemtype2 &e) //运算符栈,用e返回栈顶元素{e=*;}void Popopnd2(sqstack2 &s,selemtype2 &e) // 运算符栈,退栈:删除栈顶元素,并用 e 返回其值{e=*;}int stackempy2(sqstack2 s) // 运算符栈,若为空栈返回 1,否则返回 0 {if== return 1;else return 0;}void priority(char c,int &i)//确定运算符优先级{if (c=='*'||c=='/'||c=='%') i=2 ;else if (c=='+'||c=='-') i=1 ;else i=0;}int compare(char a,char b) //比较栈顶元素运算符与外面运算符优先级大小,外面优先级大则返回1,反之返回 0{int in,out;priority(a,in);priority(b,out);if(out>in) return 1;else return 0;}void Operat(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num2);Popopnd1(OPND,num1);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}void Operatqianzhui(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num1);Popopnd1(OPND,num2);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}//后缀表达式求值void houzhuiqiuzhi(Lnode *p,int &e){sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operat(OPND,OPTR);break;default:printf("结点有误 ");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void zhongzhui(Lnode *p)//中缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c,c2;Lnode *first;first=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(!stackempy2(OPTR)||p){while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else { switch(c){case '(': Push2(OPTR,c);break;case ')': GetTop2(OPTR,c2);while(c2!='('){Operat(OPND,OPTR);GetTop2(OPTR,c2);}Popopnd2(OPTR,c2);break;default: GetTop2(OPTR,c2);if(compare(c2,c)) Push2(OPTR,c);else { Operat(OPND,OPTR);Push2(OPTR,c);}break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR))Operat(OPND,OPTR);}Popopnd1(OPND,n);p=first->next;while(p){if(p->data==1) printf("%d ",p->data1);if(p->data==2) printf("%c",p->data2);p=p->next;}printf("=%d ",n);}void houzhui(Lnode*p)//中缀表达式转变为后缀表达式{sqstack2 OPTR; //运算符栈Lnode *r,*q,*head;int n;char c,c2;InitStack2(OPTR);p=p->next;q=(Lnode*)malloc(sizeof(struct Node));head=q;while(p){ switch(p->data){case 1:n=p->data1;r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=1;q->data1=n;break;case 2:c=p->data2; if(stackempy2(OPTR))Push2(OPTR,c); else { switch(c){ case '(': Push2(OPTR,c);break;case ')': Popopnd2(OPTR,c2);while(c2!='('){r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(structNode));q->next=r;q=q->next;q->data=2;q->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;}q->next=NULL;q=head->next;while(q){if(q->data==1) printf("%d ",q->data1);if(q->data==2) printf("%c",q->data2);q=q->next;}houzhuiqiuzhi(head,n);printf("=%d ",n);}void qianzhuiqiuzhi(Lnode2 *p,int &e)//前缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;Lnode2 *head;head=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p!=head){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operatqianzhui(OPND,OPTR);break;default:printf("结点有误 ");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void qianzhui(Lnode *p)//中缀表达式转变为前缀表达式{sqstack2 OPTR; //运算符栈InitStack2(OPTR);int n;char c,c2;Lnode *first;Lnode2 *q,*head,*r,*head2,*s;first=p;p=p->next;q=(Lnode2*)malloc(sizeof(struct Node2));//成立存中缀表达式的双向循环链表head=q;while(p){r=(Lnode2*)malloc(sizeof(struct Node2));q->next=r;r->prior=q;q=q->next;q->data=p->data;q->data1=p->data1;q->data2=p->data2;p=p->next;}q->next=head;head->prior=q;s=(Lnode2*)malloc(sizeof(struct Node2));//成立存前缀表达式的双向循环链表head2=s;while(q!=head){switch(q->data){case 1:n=q->data1;r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=1;s->data1=n;break;case 2:c=q->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else{ GetTop2(OPTR,c2);if(c2==')') Push2(OPTR,c);else{ switch(c){ case ')':Push2(OPTR,c);break;case '(': Popopnd2(OPTR,c2);while(c2!=')'){r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}}break;default:printf("结点有误 ");break;}q=q->prior;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next; s->data=2; s->data2=c2;}s->next=head2;head2->prior=s;while(s!=head2){if(s->data==1) printf("%d ",s->data1);if(s->data==2) printf("%c",s->data2);s=s->prior;}qianzhuiqiuzhi(head2,n);printf("=%d ",n);}int main(){ char n[10];char c;int i,j,k,a,b,z,y,e; Lnode *p,*q,*first;i=0;e=1;a=0;b=1;z=0;y=0;p=(Lnode*)malloc(sizeof(struct Node)); first=p;printf("请输入中缀表达式 ");do{ c = getchar();if('0'<=c&&c<='9'){ n[i]=c;i++;}else{ switch (c){ case '+':case '-':case '*':case '/':case '%':case '(':case ')':case '\n':{ if(n[0]>'0'&&n[0]<='9'){ q=(Lnode*)malloc(sizeof(struct Node));p->next=q;p=p->next;for(k=0;k<i;k++){ for(j=0;j<=i-k-2;j++)e=e*10;a=a+(n[k]-'0')*e;e=1;n[k]='0';}p->data=1;p->data1=a;i=0;a=0;}if(c!='\n'){ if(p->data==2){ if(p->data2!=')'&&c!='(')b=0;}q=(Lnode*)malloc(sizeof(struct Node));p->next=q;p=p->next;p->data=2;p->data2=c;if(c=='(') z++;if(c==')') y++;}}default:if(c!='+'&&c!='-'&&c!='*'&&c!='/'&&c!='%'&&c!='\n'&&c!='('&&c!=')')b=0;}}}while (c != '\n');if(z!=y) b=0;p->next=NULL;if(b==0)printf("输入中缀表达式有误 ");else{printf(" 输入 1 中缀表达式求值,输入 2 后缀表达式求值,输入 3 前缀表达式求值 ");scanf("%d",&b);if(b==1) zhongzhui(first); if(b==2) houzhui(first); if(b==3) qianzhui(first); }return 1;}。
中缀表达式转换为后缀表达式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语⾔实现中缀表达式转换为后缀表达式本⽂实例为⼤家分享了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(" ");}}/*加减运算符优先级最低,如果栈顶元素为空则直接⼊栈,否则将栈中存储的运算符全部弹栈,如果遇到左括号则停⽌,将弹出的左括号从新压栈,因为左括号要和⼜括号匹配时弹出,这个后⾯单独讨论。
用C语言写解释器(三)——中缀转后缀

用C语言写解释器(三)——中缀转后缀用C语言写解释器(三)——中缀转后缀分类:用C语言写解释器算法讨论拍拍脑袋 2009-11-01 22:25 4983人阅读评论(4) 收藏举报语言ctokennulllist数据结构声明为提高教学质量,我所在的学院正在筹划编写C语言教材。
《用C语言写解释器》系列文章经整理后将收入书中“综合实验”一章。
因此该系列的文章主要阅读对象定为刚学完C语言的学生(不要求有数据结构等其他知识),所以行文比较罗嗦,请勿见怪。
本人水平有限,如有描述不恰当或错误之处请不吝赐教!特此声明。
操作符排序如果你忘记了后缀表达式的概念,赶紧翻回上一篇《用C语言写解释器(二)》回顾一下。
简单地说,将中缀表达式转换成后缀表达式,就是将操作符的执行顺序由“优先级顺序”转换成“在表达式中的先后顺序”。
因此,所谓的中缀转后缀,其实就是给原表达式中的操作符排序。
比如将中缀表达式 5 * ((10 - 1) / 3) 转换成后缀表达式为 5 10 1 - 3 / *。
其中数字 5 10 1 3 仍然按照原先的顺序排列,而操作符的顺序变为 - / ×,这意味着减号最先计算、其次是除号、最后才是乘号。
也许你还在担心如何将操作符从两个操作数的中间移到它们的后边。
其实不用担心,在完成了排序工作后你就发现它已经跑到操作数的后面了 ^_^。
从中缀表达式1+2×3+4 中逐个获取操作符,依次是+ × +。
如果当前操作符的优先级不大于前面的操作符时,前面操作符就要先输出。
比如例子中的第二个加号,它前面是乘号,因此乘号从这个队伍中跑到输出的队伍中当了“老大”;此时第二个加号再前面的加号比较,仍然没有比它大,因此第一个加号也排到新队伍中去了;最后队伍中只剩下加号自己了,所以它也走了。
得到新队伍里的顺序× + + 就是所求解。
下面的表格中详细展示每一个步骤。
序号输入临时空间输出1 +2 ×+3 + + ×4 + × +5 + + ×6 + × +7 × + +相信你心里还是牵挂着那些操作数。
中缀表达式转后缀表达式 c++代码

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

//ÈçºÎÓÃC++±àд¸ö³ÌÐòÖÐ׺±í´ïʽ±ä³Éºó׺±í´ïʽ£¬²¢Óúó׺±í´ïʽÇóÖµ#include <iostream>#include <string>#include <stack>#include <vector>namespace{class Expression{public:Expression();static void Remove_space(std::string &Translated);static int Compare(char op);static void RPN(std::string expression);static int Clculate();static void Display(const std::vector<int> &opnd, const std::string &soper);static std::vector<std::string> sResult;static std::stack<int> snum;};std::vector<std::string> Expression::sResult;std::stack<int> Expression::snum;Expression::Expression(){sResult.reserve(100);}void Expression::Remove_space(std::string &Translate){std::string::size_type position_start = 0;std::string::size_type position_end = 0;std::string Result;Result.reserve(100);while( (position_end = Translate.find_first_of(' ',position_start)) != std::string::npos){std::string temp = Translate.substr(position_start,position_end - position_start);Result += temp;position_start = ++position_end;}Result += Translate.substr(position_start,position_end - position_start);Translate = Result;}int Expression::Compare(char op){int Level = 0;switch(op){case '+':case '-':Level = 1;break;case '*':case '/':Level = 2;break;default:break;}return Level;}void Expression::RPN(std::string expression){std::string::size_type nCount = expression.length();std::string::size_type index = 0;std::stack<char> stmp;bool flag = false;stmp.push('@');while( index < nCount){if( expression[index] == '('){stmp.push('(');index++;}else if( expression[index] == ')'){while( stmp.top() != '('){sResult.push_back( std::string(1, stmp.top()) );stmp.pop();}stmp.pop();index++;}else if( expression[index] == '+' || expression[index] == '-' ||expression[index] == '*' || expression[index] == '/' ) {if( expression[index] == '-' || expression[index] == '+' ) {if(index == 0)//Èç¹ûµÚÒ»¸öÊý×ÖÊǸºÊý{index ++;flag = true;}else if( expression[index-1] == '(' )//Èç¹ûÀ¨ºÅÀïµÚÒ»¸öÊýÊǸºÊý{index++;flag = true;}else{while( Compare( expression[index] ) <= Compare( stmp.top() )){sResult.push_back( std::string(1, stmp.top()) );stmp.pop();}stmp.push( expression[index] );index++;}}else{while( Compare( expression[index] ) <= Compare( stmp.top() )){sResult.push_back( std::string(1, stmp.top()) );stmp.pop();}stmp.push( expression[index] );index++;}}else{std::string temp;if(flag == true){temp += expression[index - 1];flag = false;}while( expression[index] >= '0' && expression[index] <= '9') {temp += expression[index];index ++;}sResult.push_back( temp );}}//whilewhile(stmp.top() != '@'){if(stmp.top() == '('){std::cout << "Error in expression" << std::endl;exit(-1);}sResult.push_back( std::string(1, stmp.top()) );stmp.pop();}}//RPNint Expression::Clculate(){std::vector<int> opnd;size_t index = 0;int num1 = 0, num2 = 0;std::cout<< "OPNDÕ»" << "\t\t" <<"OPTRÕ»" << "\t\t" <<"ÊäÈë×Ö·û"<<"\t"<<"Ö÷Òª²Ù×÷"<<std::endl;for(index = 0; index < sResult.size(); ++index){std::string oper = sResult[index];if( (oper.size()>1) && (oper[0] == '+' || oper[0] == '-') ) {snum.push( atoi(sResult[index].c_str()) );opnd.push_back(atoi(sResult[index].c_str()));}else{switch(oper[0]){case '+':{num1 = snum.top();Display(opnd, sResult[index]);std::cout<< num1 << "\t\t" << num1<<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();num2 = snum.top();Display(opnd, sResult[index]);std::cout<< num2 << "\t\t" << num2 <<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();snum.push( num2 + num1);opnd.push_back(num2 + num1);Display(opnd, " ");std::cout<< "+" << "\t\t" << "¼ÆËã" << num2 << "+" << num1 << "²¢½«½á¹ûѹOPNDÕ»";std::cout<< std::endl;}break;case '-':{num1 = snum.top();Display(opnd, sResult[index]);std::cout<< num1 << "\t\t" << num1<<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();num2 = snum.top();Display(opnd, sResult[index]);std::cout<< num2 << "\t\t" << num2 <<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();snum.push( num2 - num1);opnd.push_back(num2 - num1);Display(opnd, " ");std::cout<< "+" << "\t\t" << "¼ÆËã" << num2 << "-" << num1 << "²¢½«½á¹ûѹOPNDÕ»";std::cout<< std::endl;}break;case '*':{num1 = snum.top();Display(opnd, sResult[index]);std::cout<< num1 << "\t\t" << num1<<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();num2 = snum.top();Display(opnd, sResult[index]);std::cout<< num2 << "\t\t" << num2 <<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();snum.push( num2 * num1);opnd.push_back(num2 * num1);Display(opnd, " ");std::cout<< "+" << "\t\t" << "¼ÆËã" << num2 << "*" << num1 << "²¢½«½á¹ûѹOPNDÕ»";std::cout<< std::endl;}break;case '/':{num1 = snum.top();Display(opnd, sResult[index]);std::cout<< num1 << "\t\t" << num1<<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();num2 = snum.top();Display(opnd, sResult[index]);std::cout<< num2 << "\t\t" << num2 <<" ³öOPNDÕ»";std::cout<< std::endl;snum.pop();opnd.pop_back();if(num1 == 0){std::cerr << "Expression worng!" << std::endl;exit(-1);}snum.push( num2 / num1);opnd.push_back(num2 / num1);Display(opnd, " ");std::cout<< "+" << "\t\t" << "¼ÆËã" << num2 << "*" << num1 << "²¢½«½á¹ûѹOPNDÕ»";std::cout<< std::endl;}break;default:{snum.push( atoi(sResult[index].c_str()) );opnd.push_back( atoi(sResult[index].c_str()) );}break;}//swith}}//whileint result = snum.top();snum.pop();return result;}void Expression::Display(const std::vector<int> &opnd, const std::string &soper){size_t index = 0;for(index; index< opnd.size(); index++){std::cout << opnd[index] << " ";}std::cout<< "\t\t" << soper << "\t\t";}}//classint main(){std::string Input;std::cout << "please input the expression (Enter key for end)" << std::endl;std::getline(std::cin, Input, '\n');Expression expression;Expression::Remove_space(Input);Expression::RPN(Input);std::cout << std::endl;std::cout << "ºó׺±í´ïʽ:" << std::endl;for(size_t index = 0; index < Expression::sResult.size(); ++index) {std::cout << Expression::sResult[index] << " ";}std::cout << std::endl;std::cout<< Expression::Clculate() << std::endl;return 0;}/*please input the expression (Enter key for end)11-(22-11)*2-(-10)+10/5ºó׺±í´ïʽ:11 22 11 - 2 * - -10 - 10 5 / +OPNDÕ» OPTRÕ» ÊäÈë×Ö·û Ö÷Òª²Ù×÷11 22 11 - 11 11 ³öOPNDÕ»11 22 - 22 22 ³öOPNDÕ»11 11 + ¼ÆËã22-11²¢½«½á¹ûѹOPNDÕ»11 11 2 * 2 2 ³öOPNDÕ»11 11 * 11 11 ³öOPNDÕ»11 22 + ¼ÆËã11*2²¢½«½á¹ûѹOPNDÕ» 11 22 - 22 22 ³öOPNDÕ»11 - 11 11 ³öOPNDÕ»-11 + ¼ÆËã11-22²¢½«½á¹ûѹOPNDÕ»-11 -10 - -10 -10 ³öOPNDÕ»-11 - -11 -11 ³öOPNDÕ»-1 + ¼ÆËã-11--10²¢½«½á¹ûѹOPNDÕ» -1 10 5 / 5 5 ³öOPNDÕ»-1 10 / 10 10 ³öOPNDÕ»-1 2 + ¼ÆËã10*5²¢½«½á¹ûѹOPNDÕ»-1 2 + 2 2 ³öOPNDÕ»-1 + -1 -1 ³öOPNDÕ»1 + ¼ÆËã-1+2²¢½«½á¹ûѹOPNDÕ»1Press any key to continu*/。
中缀表达式转后缀表达式并计算结果(c语言版)

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

c语言中缀表达式转后缀表达式在C语言中,可以使用栈的数据结构来实现中缀表达式转后缀表达式的操作。
下面是一个示例代码:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_SIZE 100// 定义运算符的优先级int getPriority(char operator) {switch(operator) {case '+':case '-':return 1;case '*':case '/':return 2;case '^':return 3;default:return 0;}}// 判断字符是否为操作符int isOperator(char character) {return (character == '+' || character == '-' || character == '*' ||character == '/' || character == '^');}// 中缀表达式转后缀表达式void infixToPostfix(char* infixExpression, char* postfixExpression) {char stack[MAX_SIZE];int top = -1;int infixLength = strlen(infixExpression);int postfixIndex = 0;for(int i = 0; i < infixLength; i++) {// 如果是操作数,直接输出到后缀表达式if(!isOperator(infixExpression[i]) && infixExpression[i] != '(' && infixExpression[i] != ')') {postfixExpression[postfixIndex] = infixExpression[i];postfixIndex++;}// 如果是‘(’,入栈if(infixExpression[i] == '(') {stack[++top] = infixExpression[i];}// 如果是操作符if(isOperator(infixExpression[i])) {// 当当前操作符的优先级小于等于栈顶操作符的优先级时,将栈顶操作符输出到后缀表达式,再将当前操作符入栈 while(top != -1 && getPriority(infixExpression[i]) <=getPriority(stack[top])) {postfixExpression[postfixIndex] = stack[top];postfixIndex++;top--;}stack[++top] = infixExpression[i];}// 如果是')',将栈中的操作符输出到后缀表达式直到遇到‘(’if(infixExpression[i] == ')') {while(top != -1 && stack[top] != '(') {postfixExpression[postfixIndex] = stack[top];postfixIndex++;top--;}// 弹出‘(’top--;}}// 输出栈中剩余的操作符while(top != -1) {postfixExpression[postfixIndex] = stack[top];postfixIndex++;top--;}postfixExpression[postfixIndex] = '\0';}int main() {char infixExpression[MAX_SIZE];char postfixExpression[MAX_SIZE];printf("请输入中缀表达式:");scanf("%s", infixExpression);infixToPostfix(infixExpression, postfixExpression);printf("后缀表达式:%s\n", postfixExpression);return 0;}```该程序通过读入一个中缀表达式,将其转换为后缀表达式并输出。
中缀转后缀(数据结构 C语言版)

exp[t]='|';t++;//分隔后缀中的数值元素
break;
}
ch=str[i];i++;
}
while(op.top!=-1)//栈顶不为空
{
exp[t++]=op.data[op.top];
while(ch!='\0')
{
switch(ch)
{
case'+':
od.data[od.top-1]=od.data[od.top-1]+oห้องสมุดไป่ตู้.data[od.top];od.top--;
break;
case'-':
scanf("%d\n");
return 0;
}
t++;
}
}
sum=d+f;
od.top++;
od.data[od.top]=sum;*/
}
ch=exp[t];t++;
}
return od.data[od.top];//返回计算结果
od.top++;
od.data[od.top]=d;
/*{
if(ch=='.')
{ch=exp[t];t++;
while(ch<='9'&&ch>='0')
{
j=j*10;
case'-':
C语言实现中缀、后缀、前缀表达式 相互转化并求值

C语言实现中缀、后缀、前缀表达式相互转化并求值1.问题描述(1)表达式求值问题表达式是数据运算的基本形式。
人们的书写习惯是中缀式,如:11+22*(7-4)/3。
中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。
表达式还有后缀式(如:22 7 4 - * 3 / 11 +)和前缀式(如:+ 11 / * 22 –7 4 3)。
后缀表达式和前缀表达式中没有括号,给计算带来方便。
如后缀式计算时按运算符出现的先后进行计算。
本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。
2.数据结构设计(1)表达式求值问题由于表达式中有字符与数字两种类型,故定义结点一个标志域data,标志结点存储的为字符data=2还是数字data=1,再寻找结点中对应的存储位置,读取数字域data1,字符域data2。
而在前缀表达式时,存在表达式逆序,因表达式类型不统一,用栈逆序极不方便,选择构建双向链表,存储表达式。
typedef struct Node //定义存储中缀表达式的结点类型{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2 //定义存储前缀表达式的结点类型{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;3.运行、测试与分析(1)表达式求值问题(1)按提示输入中缀表达式,如图1.1所示。
如输入中缀表达式不正确,提示输入有误,如图1.2,1.3所示。
图1.1图1.2图1.3(2)选择表达式转换并求值方式。
按“1”选择中缀表达式求值,如图1.4所示。
图1.4(3)按“2”选择中缀表达式转变为后缀表达式并求值,如图1.5所示。
图1.5(4)按“3”选择中缀表达式转变为前缀表达式并求值,如图1.6所示。
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();}*/。
中缀表达式转后缀表达式 c++代码

中缀表达式转后缀表达式 c++代码中缀表达式转后缀表达式是计算机科学中非常重要的一项技术。
在这篇文章中,我们将介绍如何使用C++编写一个中缀表达式转后缀表达式的程序。
中缀表达式是我们通常使用的表达式形式,例如a+b*c。
而后缀表达式(也称为逆波兰表达式)是一种更加方便进行计算的表达式形式,例如abc*+。
以下是一个简单的中缀表达式转换为后缀表达式的C++代码:```C++#include <iostream>#include <stack>#include <string>using namespace std;// 定义运算符的优先级int getPriority(char ch) {switch(ch) {case '+':case '-':return 1;case '*':case '/':return 2;case '^':return 3;default:return 0;}}// 中缀表达式转后缀表达式string infixToPostfix(string infix) {stack<char> s;string postfix;for(int i = 0; i < infix.length(); i++) {char ch = infix[i];// 如果是运算数,直接添加到后缀表达式中if(isalnum(ch)) {postfix += ch;}// 如果是左括号,将其压入栈中else if(ch == '(') {s.push(ch);}// 如果是右括号,将栈中的运算符弹出并添加到后缀表达式中,直到遇到左括号为止else if(ch == ')') {while(!s.empty() && s.top() != '(') {postfix += s.top();s.pop();}if(!s.empty() && s.top() == '(') {s.pop();}}// 如果是运算符,将其压入栈中,但要先判断其与栈顶运算符的优先级,// 如果栈顶运算符优先级高于或等于该运算符,则弹出栈顶运算符并添加到后缀表达式中,再次转到与新的栈顶运算符比较。
c语言实现中缀,后缀,前缀表达式转换并求值

c语言实现中缀,后缀,前缀表达式转换并求值九#include<stdio.h>#include<stdlib.h>#define MAXNUM 100typedef struct Node //定义存储中缀表达式的结点类型{int data;int data1;char data2;struct Node *next;}Lnode;typedef struct Node2 //定义存储前缀表达式的结点类型{int data;int data1;char data2;struct Node2 *next;struct Node2 *prior;}Lnode2;typedef int selemtype1; //定义运算数栈的结点typedef struct //定义运算数栈的类型{selemtype1 *base;selemtype1 *top;}sqstack1;void InitStack1(sqstack1 &s) //新建一个空运算数栈{s.base=(selemtype1 *)malloc(MAXNUM*sizeof(selemtype1));s.top=s.base;if(!s.base) printf("出错:申请空间失败!\n");}void Push1(sqstack1 &s,selemtype1 &e) //运算数栈,入栈:插入元素e为新的栈顶元素{ if(s.top-s.base>=MAXNUM)printf("出错:表达式过长!1\n");*s.top++ =e;}void GetTop1(sqstack1 s,selemtype1 &e) //运算数栈,用e返回栈顶元素{e=*(s.top-1);}void Popopnd1(sqstack1 &s,selemtype1 &e) //运算数栈,退栈:删除栈顶元素,并用e返回其值{e=*--s.top;}int stackempy1(sqstack1 s) //运算数栈,若为空栈返回1,否则返回0{if(s.top==s.base) return 1;else return 0;}typedef char selemtype2; //定义运算符栈的结点类型typedef struct //定义运算符栈类型{selemtype2 *base;selemtype2 *top;}sqstack2;void InitStack2(sqstack2 &s) //新建一个空运算符栈{s.base=(selemtype2 *)malloc(MAXNUM*sizeof(selemtype2));s.top=s.base;if(!s.base) printf("出错:申请空间失败!\n");}void Push2(sqstack2 &s,selemtype2 &e) //运算符栈,入栈:插入元素e为新的栈顶元素{ if(s.top-s.base>=MAXNUM)printf("出错:表达式过长!2\n");*s.top++ =e;}void GetTop2(sqstack2 s,selemtype2 &e) //运算符栈,用e返回栈顶元素{e=*(s.top-1);}void Popopnd2(sqstack2 &s,selemtype2 &e) //运算符栈,退栈:删除栈顶元素,并用e返回其值{e=*--s.top;}int stackempy2(sqstack2 s) //运算符栈,若为空栈返回1,否则返回0{if(s.top==s.base) return 1;else return 0;}void priority(char c,int &i) //确定运算符优先级{if (c=='*'||c=='/'||c=='%') i=2 ;else if (c=='+'||c=='-') i=1 ;else i=0;}int compare(char a,char b) //比较栈顶元素运算符与外部运算符优先级大小,外部优先级大则返回1,反之返回0{int in,out;priority(a,in);priority(b,out);if(out>in) return 1;else return 0;}void Operat(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num2);Popopnd1(OPND,num1);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}void Operatqianzhui(sqstack1 &OPND,sqstack2 &OPTR){int num1,num2,num;char c;Popopnd1(OPND,num1);Popopnd1(OPND,num2);Popopnd2(OPTR,c);switch(c){case '+':num=num1+num2;break;case '-':num=num1-num2;break;case '*':num=num1*num2;break;case '/':num=num1/num2;break;case '%':num=num1%num2;break;}Push1(OPND,num);}void houzhuiqiuzhi(Lnode *p,int &e) //后缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operat(OPND,OPTR);break;default:printf("结点有误");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void zhongzhui(Lnode *p) //中缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c,c2;Lnode *first;first=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(!stackempy2(OPTR)||p){while(p){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else { switch(c){case '(': Push2(OPTR,c);break;case ')': GetTop2(OPTR,c2);while(c2!='('){Operat(OPND,OPTR);GetTop2(OPTR,c2);}Popopnd2(OPTR,c2);break;default: GetTop2(OPTR,c2);if(compare(c2,c)) Push2(OPTR,c);else { Operat(OPND,OPTR);Push2(OPTR,c);}break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR))Operat(OPND,OPTR);}Popopnd1(OPND,n);p=first->next;while(p){if(p->data==1) printf("%d ",p->data1); if(p->data==2) printf("%c",p->data2);p=p->next;}printf("=%d ",n);}void houzhui(Lnode *p) //中缀表达式转化为后缀表达式{sqstack2 OPTR; //运算符栈Lnode *r,*q,*head;int n;char c,c2;InitStack2(OPTR);p=p->next;q=(Lnode*)malloc(sizeof(struct Node));head=q;while(p){ switch(p->data){case 1:n=p->data1;r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=1;q->data1=n;break;case 2:c=p->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else { switch(c){ case '(': Push2(OPTR,c);break;case ')': Popopnd2(OPTR,c2);while(c2!='('){ r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}break;default: printf("结点有误");break;}p=p->next;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode*)malloc(sizeof(struct Node));q->next=r;q=q->next;q->data=2;q->data2=c2;}q->next=NULL;q=head->next;while(q){if(q->data==1) printf("%d ",q->data1);if(q->data==2) printf("%c",q->data2);q=q->next;}houzhuiqiuzhi(head,n);printf("=%d ",n);}void qianzhuiqiuzhi(Lnode2 *p,int &e) //前缀表达式求值{sqstack1 OPND; //运算数栈sqstack2 OPTR; //运算符栈int n;char c;Lnode2 *head;head=p;p=p->next;InitStack1(OPND);InitStack2(OPTR);while(p!=head){switch(p->data){case 1:n=p->data1;Push1(OPND,n);break;case 2:c=p->data2;Push2(OPTR,c);Operatqianzhui(OPND,OPTR);break;default:printf("结点有误");break;}p=p->next;}Popopnd1(OPND,n);e=n;}void qianzhui(Lnode *p) //中缀表达式转化为前缀表达式{sqstack2 OPTR; //运算符栈InitStack2(OPTR);int n;char c,c2;Lnode *first;Lnode2 *q,*head,*r,*head2,*s;first=p;p=p->next;q=(Lnode2*)malloc(sizeof(struct Node2)); //建立存中缀表达式的双向循环链表head=q;while(p){r=(Lnode2*)malloc(sizeof(struct Node2));q->next=r;r->prior=q;q=q->next;q->data=p->data;q->data1=p->data1;q->data2=p->data2;p=p->next;}q->next=head;head->prior=q;s=(Lnode2*)malloc(sizeof(struct Node2)); //建立存前缀表达式的双向循环链表head2=s;while(q!=head){switch(q->data){case 1:n=q->data1;r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=1;s->data1=n;break;case 2:c=q->data2;if(stackempy2(OPTR)) Push2(OPTR,c);else{ GetTop2(OPTR,c2);if(c2==')') Push2(OPTR,c);else{ switch(c){ case ')':Push2(OPTR,c);break;case '(': Popopnd2(OPTR,c2);while(c2!=')'){ r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;Popopnd2(OPTR,c2);}break;default: GetTop2(OPTR,c2);while(!compare(c2,c)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;GetTop2(OPTR,c2);}Push2(OPTR,c);break;}}}break;default:printf("结点有误");break;}q=q->prior;}while(!stackempy2(OPTR)){ Popopnd2(OPTR,c2);r=(Lnode2*)malloc(sizeof(struct Node2));s->next=r;r->prior=s;s=s->next;s->data=2;s->data2=c2;}s->next=head2;head2->prior=s;while(s!=head2){if(s->data==1) printf("%d ",s->data1);if(s->data==2) printf("%c",s->data2);s=s->prior;}qianzhuiqiuzhi(head2,n);printf("=%d ",n);}int main(){ char n[10];char c;int i,j,k,a,b,z,y,e;Lnode *p,*q,*first;i=0;e=1;a=0;b=1;z=0;y=0;p=(Lnode*)malloc(sizeof(struct Node));first=p;printf("请输入中缀表达式");do{ c = getchar();if('0'<=c&&c<='9'){ n[i]=c;i++;}else{ switch (c){ case '+':case '-':case '*':case '/':case '%':case '(':case ')':case '\n':{ if(n[0]>'0'&&n[0]<='9') { q=(Lnode*)malloc(sizeof(struct Node));p->next=q;p=p->next;for(k=0;k<i;k++){ for(j=0;j<=i-k-2;j++)e=e*10;a=a+(n[k]-'0')*e;e=1;n[k]='0';}p->data=1;p->data1=a;i=0;a=0;}if(c!='\n'){ if(p->data==2){ if(p->data2!=')'&&c!='(')b=0;}q=(Lnode*)malloc(sizeof(struct Node));p->next=q;p=p->next;p->data=2;p->data2=c;if(c=='(') z++;if(c==')') y++;}}default:if(c!='+'&&c!='-'&&c!='*'& &c!='/'&&c!='%'&&c!='\n' &&c!='('&&c!=')')b=0;}}}while (c != '\n');if(z!=y) b=0;p->next=NULL;if(b==0)printf("输入中缀表达式有误");else{printf("输入1中缀表达式求值,输入2后缀表达式求值,输入3前缀表达式求值");scanf("%d",&b); if(b==1) zhongzhui(first);if(b==2) houzhui(first);if(b==3) qianzhui(first);}return 1;}。
数据结构代码中缀转后缀表达式算法及源代码

#include<stdio.h>#include<stdlib.h>#include<math.h>#define MAX 100 /* 表达式最大长度 */#define true 1#define false 0/* 定义数据栈 */typedef struct LinkStack1{float data 。
struct LinkStack1 *next 。
}LinkStack1,*Top1 。
int initStack1(Top1 *t> /* 数据栈初始化 */{*t=NULL 。
return true 。
}int push1(Top1 *t,float val> /* 数据栈插入元素 */{Top1 p=(Top1>malloc(sizeof(LinkStack1>> 。
/* 开内存 */if(p==NULL>return false 。
p->data=val 。
p->next=*t 。
*t=p 。
return true 。
}float getTop1(Top1 *t> /* 取数据栈元素 */{return (*t>->data 。
}int pop1(Top1 *t,float *val> /* 推出数据栈元素并存到 *val 中 */ { Top1 p=*t 。
if(p==0>return false 。
*t=p->next 。
*val=p->data 。
free(p> 。
/* 释放所占内存 */ return true 。
}/* 定义操作符栈 */typedef struct LinkStack2{int data 。
struct LinkStack2 *next 。
}LinkStack2,*Top2 。
int initStack2(Top2 *t> /* 数据栈初始化 */{*t=NULL 。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5 将中缀表达式转换为后缀表达式
【问题描述】表达式转换。
输入的中缀表达式为字符串,转换得到的后缀表达式存入字符数组中并输出。
例如:a*(x+y)/(b-x) 转换后得:a x y + * b x - /
【数据结构】
●定义一个暂时存放运算符的转换工作栈opst。
●中缀表达式字符串char *infix;
●后缀表达式字符串char *postfix;
【算法提示】转换规则:把运算符移到它的两个操作数后面,删除掉所有的括号。
从头到尾扫描中缀表达式,对不同类型的字符按不同情况处理:
●数字或小数点,直接写入字符串postfix,并在每个数值后面写入一个空格;
●左括号,进栈,直到遇见相配的右括号,才出栈;
●右括号,表明已扫描过括号内的中缀表达式,把从栈顶直到对应左括号之间的运算
符依次退栈,并把结果推入栈内;
●对于运算符,分两种情况处理:
◆该运算符的优先级大于栈顶符号的优先级,则入栈;
◆若该运算符的优先级小于栈顶优先级,则先弹出栈顶运算符、写入postfix串;继续将该
运算符与栈顶运算符比较,直到能把它推入栈内为止(即优先级大于栈顶运算符)。
说明:自行设计运算符优先级的表示。
【主要代码】
#include<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()函数。
这个程序编写起来比较顺利,编写过程中没有遇到什么非常大的问题。
最值得注意的是栈内优先级和栈外优先级的函数,我并没有在类内定义,我是在类外定义的。
所以调用的时候并不用某个对象来调用,而是直接在调用。
这就要注意成员函数和常规函数的区别。