对于栈的经典应用之一表达式求值。先贴代码然后在分析。代码实现基本的表达式求值
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
#define INITSIZE 100
#define INCREMENT 10
typedef struct Stack
{
int *base;
int *top;
int stacksize;//容量
}Stack;
void initStack(Stack &s)
{
s.base=(int *)malloc(sizeof(int)*INITSIZE);
if(!s.base)
{
printf("基址分配失败!\n");
}
s.top=s.base;
s.stacksize=INITSIZE;
}
int isFull(Stack s)
{
if(s.top-s.base==s.stacksize)
return 1;
else
return 0;
}
void PushOpnd(Stack &s,int e)
{
if(isFull(s))
{
s.base=(int *)malloc(sizeof(int)*(INCREMENT+INITSIZE));
if(!s.base)printf("基址分配失败!\n");
s.top=s.base+s.stacksize;
s.stacksize+=INCREMENT;
}
*s.top=e;
s.top++;
}
void PushOptr(Stack &s,char c)
{
if(isFull(s))
{
s.base=(int *)malloc(sizeof(int)*(INITSIZE+INCREMENT));
if(!s.base)printf("基址分配失败!\n");
s.top=s.base+s.stacksize;
s.stacksize+=INCREMENT;
}
*s.top=c;
s.top++;
}
void PopOpnd(Stack &s,int &e)
{
if(s.top==s.base)
{
printf("栈空!\n");
}
else
{
s.top--;
e=*s.top;
}
}
void PopOptr(Stack &s,char &c)
{
if(s.top==s.base)
{
printf("栈空!\n");
}
else
{
s.top--;
c=*s.top;
}
}
void destoryStack(Stack s)
{
free(s.base);
}
void getOp(Stack s,char &c)
{
c=*(--s.top);
}
int Operator(char c)
{
int flag;
switch(c)
{
case '+':
flag=1;
break;
case '-':
flag=2;
break;
case '*':
flag=3;
break;
case '/':
flag=4;
break;
case '(':
flag=5;
break;
case ')':
flag=0;
break;
default:
flag=-1;
break;
}
return flag;
}
char Prio(int a,int b)
{
if(a==4&&b==5)return '=';
else if(b==5)
return '<';
else if(a<=b)return '>';
else return '<';
}
int calcu(int a,char op,int b)
{
switch(op)
{
case '+':
return a+b;
break;
case '-':
return a-b;
break;
case '*':
return a*b;
break;
case '/':
return a/b;
break;
default:
return -1;
break;
}
}
int Exception(char *str)
{
int a,b,result;
strcat(str,"#");
Stack opnd,optr;
initStack(opnd);
initStack(optr);
PushOptr(optr,'#');
int i=0;
int l=strlen(str);
//for(int i=0;i<l;i++)
char op;
getOp(optr,op);
while(str[i]!='#'||op!='#')
{
if(isdigit(str[i]))//自带函数
{
int m=str[i]-'0';
PushOpnd(opnd,m);
}
else
{
int p1=Operator(str[i]);
int p2=Operator(op);
if(Prio(p1,p2)=='<')
{
PushOptr(optr,str[i]);
}
else if(Prio(p1,p2)=='>')
{
PopOpnd(opnd,a);
PopOpnd(opnd,b);
PopOptr(optr,op);
result=calcu(b,op,a);
PushOpnd(opnd,result);
getOp(optr,op);
if(str[i]==')'&&op=='(')
PopOptr(optr,op);
else if(i==l-1)
;
else
PushOptr(optr,str[i]);
}
else if(Prio(p1,p2)=='=')
{
PopOptr(optr,str[i]);
}
}
i++;
getOp(optr,op);
if(i<l-1)
i++;
}
destoryStack(optr);
PopOpnd(opnd,result);
return result;
}
int main()
{
char s[100];
printf("Input:");
gets(s);
printf("%d\n",Exception(s));
return 0;
}
对于栈的使用
#define INITSIZE 100
#define INCREMENT 10
typedef struct Stack
{
int *base;
int *top;
int stacksize;//容量
}Stack;
栈的定义,栈底,栈顶,以及栈容量,初始容量为100,动态分配增长为10。
对于栈的基本操作
//初始化栈并且分配100的空间
void initStack(Stack &s)
{
s.base=(int *)malloc(sizeof(int)*INITSIZE);
if(!s.base)
{
printf("基址分配失败!\n");
}
s.top=s.base;
s.stacksize=INITSIZE;
}
//判断栈是否满
int isFull(Stack s)
{
if(s.top-s.base==s.stacksize)
return 1;
else
return 0;
}
//对操作数进行入栈,首先判断栈是否满,操作树为int型
void PushOpnd(Stack &s,int e)
{
if(isFull(s))
{
s.base=(int *)malloc(sizeof(int)*(INCREMENT+INITSIZE));
if(!s.base)printf("基址分配失败!\n");
s.top=s.base+s.stacksize;
s.stacksize+=INCREMENT;
}
*s.top=e;
s.top++;
}
//对操作符进行入栈,操作符为char型
void PushOptr(Stack &s,char c)
{
if(isFull(s))
{
s.base=(int *)malloc(sizeof(int)*(INITSIZE+INCREMENT));
if(!s.base)printf("基址分配失败!\n");
s.top=s.base+s.stacksize;
s.stacksize+=INCREMENT;
}
*s.top=c;
s.top++;
}
//出栈,首先栈顶指针减一再取值。
void PopOpnd(Stack &s,int &e)
{
if(s.top==s.base)
{
printf("栈空!\n");
}
else
{
s.top--;
e=*s.top;
}
}
void PopOptr(Stack &s,char &c)
{
if(s.top==s.base)
{
printf("栈空!\n");
}
else
{
s.top--;
c=*s.top;
}
}
void destoryStack(Stack s)
{
free(s.base);
}
//取栈顶值
void getOp(Stack s,char &c)
{
c=*(--s.top);
}
核心思想是对运算符优先级进行比较,如果运算符优先级小于则运算,大于则压栈。对于括号需要特殊处理,如果遇到左右括号则将左括号pop出来。