一、准备工作
- 对于使用栈来进行表达式求值,使用顺序栈即可
- 定义两个栈,一个操作数栈(int 数据类型),一个运算符栈(char 数据类型)。
- 两个栈都应该具备:初始化,入栈,出栈,取栈顶元素这些功能函数。
- 需要运算符的优先级关系所定义的功能函数。
优先级关系表:
右 左 | + | - | * | / | ( | ) | # |
+ | > | > | < | < | < | > | > |
- | > | > | < | < | < | > | > |
* | > | > | > | > | < | > | > |
/ | > | > | > | > | < | > | > |
( | < | < | < | < | < | = | |
) | > | > | > | > | > | > | |
# | < | < | < | < | < | = |
优先级分析:
优先级函数代码:
//比较运算符优先级
char compare(char a,char b)
{
if(a=='+'||a=='-') //a为 + - 时
{
if(b=='+'||b=='-'||b==')'||b=='#') return '>';
else return '<';
}
else if(a=='*'||a=='/') //a为 * / 时
{
if(b=='(') return '<';
else return '>';
}
else if(a=='(') //a为( 时
{
if(b=='+'||b=='-'||b=='*'||b=='/'||b=='(') return '<';
else if(b==')') return '=';
else{
printf("输入有误");
return 0;
}
}
else if(a==')') //a为 ) 时
{
if(b=='+'||b=='-'||b=='*'||b=='/'||b==')'||b=='#') return '>';
else if(b=='(')
{
printf("输入有误");
return 0;
}
}
else if(a=='#') //a为 # 时
{
if(b==')')
{
printf("输入有误");
return 0;
}
else if(b=='#') return '=';
else return '<';
}
}
二、实操
分析:
如果是操作数,则直接进栈,并依次读入下一个。
如果是运算符,则先与符号栈top做优先级比较,做以下处理:
- 如果读入的优先级>top,则进栈。
- 如果读入的优先级=top,则括号相遇,运算符栈顶退栈。
- 如果读入的优先级<top,则在操作数栈中连续退两个(符号邻近的两个),符号栈退一个,进行运算。
- 如果读入为结束符'#',则表达式处理完毕,通过循环和分支来计算栈中存在的值。
具体代码:
//运算符 初始化
int Initsign(fustack &s){
s=(FUStack *)malloc(sizeof(FUStack));
s->top=-1;
if(s==NULL){
return false;
}else{
return true;
}
}
//操作数 初始化
int Initshu(shustack &s){
s=(SHUStack *)malloc(sizeof(SHUStack));
s->top=-1;
if(s==NULL){
return false;
}else{
return true;
}
}
//运算符入栈
int pushfu(fustack &s,char c){
if(s->top==max-1){
printf("栈满!");
return false;
}else{
s->top++;
s->data[s->top]=c;
return true;
}
}
//操作数 入栈
int pushshu(shustack &s,int x){
if(s->top==max-1){
printf("栈满!");
return false;
}else{
s->top++;
s->data[s->top]=x;
return true;
}
}
//运算符 出栈
char popfu(fustack &s,char &a)
{
if(s->top==-1){
printf("栈空fu!");
return false;
}else{
a= s->data[s->top];
s->data[s->top]=0;
s->top--;
return a;
}
}
//操作数 出栈
int popshu(shustack &s,int &x){
if(s->top==-1){
printf("栈空shu!");
return false;
}else{
x=s->data[s->top];
s->data[s->top]=0;
s->top--;
return x;
}
}
//运算符 取栈顶
char getfutop(fustack s){
if(s->top==-1){
printf("栈空fu!");
return false;
}else{
return s->data[s->top];
}
}
//操作数 取栈顶
int getshutop(shustack s){
if(s->top==-1){
printf("栈空shu!");
return false;
}else{
return s->data[s->top];
}
}
//计算函数 f为运算符的top元素
int operate(int a,char f,int b)
{
if(f=='+'){
return a+b;
}else if(f=='-'){
return a-b;
}else if(f=='*'){
return a*b;
}else if(f=='/'){
return a/b;
}
}
//这里定义的只适用于10以内的加减乘除
/* getfutop:取符号栈栈顶 getshutop:取操作数栈栈顶
popfu:符号栈出栈 popshu:操作栈出栈
pushfu:符号栈入栈 pushshu:操作栈入栈
Initsign:初始化符号栈 Initshu:初始化操作数栈
*/
int main(){
shustack s; //数栈
fustack f; //符号栈
Initshu(s);
Initsign(f);
int a,b,data;
char F,F1;
pushfu(f,'#'); //运算符栈以'#'压栈
char ch=getchar(); //取元素
while(ch!='#'||getfutop(f)!='#'){ //当取到的元素和 运算符top值不为‘#’
if(ch>='0'&&ch<='9') //如果为操作数
{
data=ch-'0'; //这里是将读入的操作数转换为十进制
pushshu(s,data); //操作数进栈
ch=getchar(); //重新取值
}
else{ //如果不为操作数
switch(compare(getfutop(f),ch)) //compare函数是比较符号栈top指针和ch取到的符号的优先级
{
case'<':pushfu(f,ch); //如果优先级< 符号进栈
ch=getchar();break; //重新取
case'=':popfu(f,F); //如果优先级 = 符号出栈(代表有左右括号)
ch=getchar();break; //重新取
case'>': //如果优先级>
popfu(f,F1); //出符号栈top赋值给F1
popshu(s,b); //出操作数赋值给b
popshu(s,a); //出操作数赋值给a
int q=operate(a,F1,b); //计算a,F1,b 的值赋给q
pushshu(s,q); //q进操作数栈
break;
}
}
}
int shuzhi=getshutop(s); //取操作数栈顶元素
printf("%d",shuzhi); //输出
}
运行结果:
1.不带括号:
2.带括号:
程序能run,需要的可以直接复制下来,代码规范可能不太好,每个函数的意思在main函数前已经标识,望大家谅解!