栈的应用4

来源:互联网 发布:linux ssh连接失败 编辑:程序博客网 时间:2024/05/29 04:46
//将中缀表达式转换为后缀表达式并计算后缀表达式
//算法分析。
//中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。
//转换过程需要用到栈,具体过程如下:


//1.如果遇到左括号我们就将其直接入栈。
//2.如果遇到读取的元素为右括号的时候,我们就开始吧元素弹出到后缀表达式,(记得这时候我们也要把后缀表达式弹出来,但是不放到后缀表达式)
//3.遇到加减乘除的运算符,这时我们就把栈不为空(栈为空就直接入栈了)栈顶的元素大于等于读取的字符,就把栈顶的额元素出栈放到后缀表达式里。直到
//栈为空或者小于读取字符的优先级,就入栈了。
//4.遇到数字直接放到后缀表达式里


//后缀表达式的算法分析
//1.如果遇到数字直接入栈。
//2.如果遇到字符,将数字出栈两次,同时将出栈运算的结果重新压栈。
//3.最后栈顶的元素就为本粗运算的结果
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define MAXSIZE 20
typedef struct 
{
char str[MAXSIZE];
int top;
}*OPTR,optr;
typedef struct
{
int date[MAXSIZE];
int top;
}*OPND,opnd;
//对字符的基本操作
OPTR initOPTR();
int emptyOPTR(OPTR);//判断是否栈空
void pushOPTR(OPTR,char);
void popOPTR(OPTR,char *);
char gettopOPTR(OPTR);//返回出栈的元素


//对数据栈的基本操作
OPND initOPND();
int emptyOPND(OPND);
void pushOPND(OPND,int);
void popOPND(OPND,int*);
int gettopOPND(OPND);
int is_character(char);//判断是不是字符
void transform();//将中缀转换为后缀表达式
void EvaluateExpression(char*);//计算后缀表达式
int main(void)
{
transform();
return 0;
}


OPTR initOPTR()
{
OPTR ps;
if((ps=(OPTR)malloc(sizeof(optr)))==NULL)
{
printf("动态内存分配失败!\n");
exit(0);
}
else
{
ps->top=-1;
}
return ps;
}
int emptyOPTR(OPTR ps)
{
if(ps->top==-1)
{
//printf("字符栈栈为空!\n");
return 0;
}
else
return 1;
}
void pushOPTR(OPTR ps,char ch)
{
if(ps->top==MAXSIZE-1)
{
printf("栈已满,入栈失败!\n");
exit(0);
}
else
{
ps->top++;
ps->str[ps->top]=ch;
}
}
void popOPTR(OPTR ps,char * ch)
{
if((emptyOPTR(ps))==0)
{
printf("栈已空,字符栈出栈失败!\n");
exit(0);
}
else
{
*ch=ps->str[ps->top];
ps->top--;
}
}
char gettopOPTR(OPTR ps)
{
return (ps->str[ps->top]);
}
//上面是对字符栈的一些基本操作




OPND initOPND()//对数据栈的一些基本操作
{
OPND ps;
if((ps=(OPND)malloc(sizeof(optr)))==NULL)
{
printf("内存分配失败!\n");
exit(0);
}
else
{
ps->top=-1;
}
return ps;
}
int emptyOPND(OPND ps)
{
if(ps->top==-1)
return 0;
else
return 1;
}
void pushOPND(OPND ps,int ch)
{
if(ps->top==MAXSIZE-1)
{
printf("栈已满,入栈失败!\n");
exit(0);
}
else
{
ps->top++;
ps->date[ps->top]=ch;
}
}
void popOPND(OPND ps,int*ch)
{
if(emptyOPND(ps)==0)
{
printf("栈已空,数据栈出栈失败!\n");
exit(0);
}
else
{
*ch=ps->date[ps->top];
ps->top--;
}
}
int gettopOPND(OPND ps)
{
return (ps->date[ps->top]);
}


int is_character(char ch)//首先判断是不是字符
{
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')')
return 1;
else
return 0;
}
void transform()
{
char Z[MAXSIZE],H[MAXSIZE],ch;//Z[MAXSIZE],H[MAXSIZE]分别用来存放中缀和后缀表达式
int i,j=0;
OPTR ps=initOPTR();//初始化这个字符栈
printf("请输入中缀表达式:");
gets(Z);
for(i=0;Z[i]!='\0';i++)//一次遍历这个中缀表达式。
{
if(is_character(Z[i]))
{
switch(Z[i])
{
case'(':pushOPTR(ps,Z[i]);break;//如果遇到左括号,二话不说,直接进栈
case')':while(gettopOPTR(ps)!='(')//如果遇到右括号,将栈顶元素一直弹出放到后缀表达式里的数组。。但是最后还要将栈顶的右括号直接弹出来
{
popOPTR(ps,&ch);
H[j++]=ch;
}
popOPTR(ps,&ch);//然后此时将栈顶的左括号直接弹出来。
break;
case'+':
case'-':while(gettopOPTR(ps)!='('&&emptyOPTR(ps)!=0)//当栈顶不为空而且不为右括号的话。
{
popOPTR(ps,&ch);
H[j++]=ch;
}
pushOPTR(ps,Z[i]);
break;
case'*':
case'/':
while(emptyOPTR(ps)!=0&&(gettopOPTR(ps)=='*'||gettopOPTR(ps)=='/'))     //当不为空且栈顶为栈顶为*/的时候,把出栈的元素放到后缀表达式里。
{
popOPTR(ps,&ch);//1-2*3+4
H[j++]=ch;
}
pushOPTR(ps,Z[i]);
break;
}
}
else if(Z[i]<='9'&&Z[i]>='0')//这里的局限性只能转换(参与运算的单个整数)
{
H[j++]=Z[i];
}
else
{
printf("表达式中含有不符合运算的字符!\n");
exit(0);
}
}
while(emptyOPTR(ps))//最后将栈里的元素全部出栈
{
popOPTR(ps,&ch);
H[j++]=ch;
}
H[j]='\0';
printf("后缀表达式为:%s\n",H);
EvaluateExpression(H);//对后缀表达式的求值
return ;}
void EvaluateExpression(char* H)
{
int i,a,b;
OPND ps=initOPND();//初始化数据栈
for(i=0;H[i]!='\0';i++)
{
if(is_character(H[i]))//如果为运算符的话
{
switch(H[i])
{
case'+':popOPND(ps,&a);popOPND(ps,&b);pushOPND(ps,b+a);break;
case'-':popOPND(ps,&a);popOPND(ps,&b);pushOPND(ps,b-a);break;
case'*':popOPND(ps,&a);popOPND(ps,&b);pushOPND(ps,b*a);break;
case'/':popOPND(ps,&a);popOPND(ps,&b);pushOPND(ps,b/a);break;
}

}
else if(H[i]>='0'&&H[i]<='9')
{
pushOPND(ps,H[i]-'0');//将char型数字转换为int型的对应的数字
}
else;
}
printf("表达式的值:%d\n",gettopOPND(ps));
}
0 0
原创粉丝点击