严蔚敏《数据结构》表达式求值
容器:两个栈,一个存放字符CS,一个存放数字S;两个数组,一个放中缀表达式c[N],一个放逆波兰式s[N]
方式:1.先将中缀表达以字符的形式全部输入(运用了gets()函数)并放到一个数组c[N]中;
2.求逆波兰式,遍历数组c[N],利用isdigit()函数判断字符数组里面的字符是数字字符还是非数字字符,是数字字符的话,将其放入数组s[N],s[N]中利用,作为分隔符;遍历c[N],遇到+,-,(则将他们放入CS中,遇到)则不用把他放入CS,然后POP字符栈中的元素,判断元素是否为(,如果是(,则把(POP出来,继续访问数组c[N],遇到*或者/则要把他放入s[N]中,还要判断CS中是否有(,有的话,还要全部POP出CS中的元素,并放入s[N]中。
3.求值,先处理s[N]数组,利用atoi()函数将数字字符(char型)转化为(int型),然后把它放入数字栈S,遇到操作符就POP两个数字,进行计算,如此重复。
#include<bits/stdc++.h>
using namespace std;
#define N 100
#define STACK_INIT_SIZE 5
#define STACKINCREMENT 10
#define OK 1
#define ERROR 0
typedef char CSElemType;
typedef int SElemType;
typedef int Status;
//字符栈
typedef struct{//栈的顺序存储表示
CSElemType *top;//栈顶
CSElemType *base;//栈底
int cstacksize;//栈当前存储空间
}CSqStack;
//数字栈
typedef struct{//栈的顺序存储表示
SElemType *top;//栈顶
SElemType *base;//栈底
int stacksize;//栈当前存储空间
}SqStack;
//字符栈的初始化
Status InitCStack(CSqStack &CS)
{
CS.base=(CSElemType*)malloc(sizeof(CSElemType)*STACK_INIT_SIZE);
if(!CS.base)
{
exit(OVERFLOW);
}
CS.top=CS.base;
CS.cstacksize=STACK_INIT_SIZE;
return OK;
}
//数字栈的初始化
Status InitStack(SqStack &S)
{
S.base=(SElemType*)malloc(sizeof(SElemType)*STACK_INIT_SIZE);
if(!S.base)
{
exit(OVERFLOW);
}
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
//判断字符栈是否为空
Status CStackEmpty(CSqStack &CS)
{
if(CS.top==CS.base)
{
return OK;
}
else
{
return ERROR;
}
}
//判断数字栈是否为空
Status StackEmpty(SqStack &S)
{
if(S.top==S.base)
{
return OK;
}
else
{
return ERROR;
}
}
//判断字符栈是否满
Status CStackFull(CSqStack &CS)
{
if(CS.top-CS.base>=CS.cstacksize)
{
return OK;
}
else
{
return ERROR;
}
}
//判断数字栈是否满
Status StackFull(SqStack &S)
{
if(S.top-S.base>=S.stacksize)
{
return OK;
}
else
{
return ERROR;
}
}
//用e返回栈顶元素的值
Status GetTop(SqStack S,SElemType &e)
{
if(StackEmpty(S))
{
return ERROR;
}
e=*(S.top-1);
return OK;
}
//将字符e插入栈顶
Status CPush(CSqStack &CS,CSElemType e)
{
if(CStackFull(CS))
{
CS.base=(CSElemType*)realloc(CS.base,sizeof(CSElemType)*(CS.cstacksize+STACK_INIT_SIZE));
if(!CS.base)
{
exit(OVERFLOW);
}
CS.top=CS.base+CS.cstacksize;
CS.cstacksize+=STACKINCREMENT;
}
*CS.top++=e;
return OK;
}
//将数字e插入栈顶
Status Push(SqStack &S,SElemType e)
{
if(StackFull(S))
{
S.base=(SElemType*)realloc(S.base,sizeof(SElemType)*(S.stacksize+STACK_INIT_SIZE));
if(!S.base)
{
exit(OVERFLOW);
}
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
return OK;
}
//取出字符栈顶元素,用e返回其值
Status CPop(CSqStack &CS,CSElemType &e)
{
if(CStackEmpty(CS))
{
return ERROR;
}
e=*--CS.top;
return OK;
}
//取出数字栈顶元素,用e返回其值
Status Pop(SqStack &S,SElemType &e)
{
if(StackEmpty(S))
{
return ERROR;
}
e=*--S.top;
return OK;
}
//展示数字栈的元素
void DisplayStack(SqStack &S)
{
int i;
SqStack t;
SElemType e;
printf("请输出栈顶的元素:");
while (!StackEmpty(S))
{
Pop(S,e);
printf("%d\n",e);
Push(t,e);
}
while (!StackEmpty(t))
{
Pop(t,e);
Push(S,e);
}
printf("\n");
return;
}
//回收栈
Status DestroyStack(SqStack &S)
{
free(S.base);
S.base=NULL;
S.stacksize=0;
return OK;
}
Status RPoland(char c[],char *s)
{
//求逆波兰
CSqStack CS;
InitCStack(CS);
int j=0;
char e;
for(int i=0;i<strlen(c);i++)
{
if(isdigit(c[i]))//判断字符串里面是否有数字,有的话,把这个数字放入新的数组s里面
{
s[j]=c[i];
j++;
if(isdigit(c[i+1]))
{
continue;
}
if(!CStackEmpty(CS))
{
CPop(CS,e);
if(e=='*'||e=='/')
{
s[j]=',';
j++;
s[j]=e;
j++;
s[j]=',';
j++;
while(!CStackEmpty(CS))
{
CPop(CS,e);
if(e!='(')
{
s[j]=e;
j++;
}
else if(e=='(')
{
break;
}
}
}
else
{
CPush(CS,e);
}
}
}
else if(c[i]=='+'||c[i]=='-')
{
if(!CStackFull(CS))
{
CPush(CS,c[i]);
s[j]=',';
j++;
}
}
else if(c[i]=='(')
{
if(!CStackFull(CS)&&c[i+1]!='-')
{
CPush(CS,c[i]);
}
if(!CStackFull(CS)&&c[i+1]=='-')
{
CPush(CS,c[i]);
s[j]='0';
j++;
}
}
else if(c[i]==')')
{
do
{
CPop(CS,e);
if(e!='(')
{
s[j]=',';
j++;
s[j]=e;
j++;
}
if(e=='(')
{
break;
}
}while(!CStackEmpty(CS)&&e!='(');
}
else if(c[i]=='*'||c[i]=='/')
{
CPush(CS,c[i]);
s[j]=',';
j++;
}
}
while(!CStackEmpty(CS))
{
CPop(CS,e);
s[j]=',';
j++;
s[j]=e;
j++;
}
return OK;
}
Status Evaluate(char s[])
{
SqStack S;
InitStack(S);
int r=0;
char str[N];
SElemType e0,e1,e2;
for(int k=0;k<strlen(s);k++)
{
if (isdigit(s[k]))
{
str[r]=s[k];
r++;
//cout<<endl;
//cout<<"r="<<r<<endl;
if (s[k+1]==',')
{
str[r]='\0';
Push(S,atoi(str));
//cout<<endl;
//cout<<"atoi(str)="<<atoi(str)<<endl;
r=0;
}
else
{
continue;
}
}
if(s[k]=='+'||s[k]=='-'||s[k]=='*'||s[k]=='/')
{
if(s[k]=='+')
{
Pop(S,e1);
Pop(S,e2);
e0=e1+e2;
Push(S,e0);
}
if(s[k]=='-')
{
Pop(S,e1);
Pop(S,e2);
cout<<endl;
e0=e2-e1;
Push(S,e0);
}
if(s[k]=='*')
{
Pop(S,e1);
Pop(S,e2);
e0=e1*e2;
Push(S,e0);
}
if(s[k]=='/')
{
Pop(S,e1);
Pop(S,e2);
e0=e2/e1;
Push(S,e0);
}
}
}
Pop(S,e0);
printf("结果为:");
printf("%d",e0);
return OK;
}
int main()
{
char c[N];//存放中缀表达式
char s[N];//存放后缀表达式
printf("请输入中缀表达式:");
scanf("%s",c);
RPoland(c,s);
printf("输出后缀表达式:");
for(int k=0;k<strlen(s)-1;k++)
{
printf("%c",s[k]);
}
printf("\n");
Evaluate(s);
return 0;
}
代码冗长,还有瑕疵,新手上路,多多关照,欢迎大家留言和私信!