表达式求值,可以用栈,这里有栈的一些表达和使用、包括表达式求值。
这里是伪代码以及AC代码可以去HDOJ测评。
现在我用后缀表达式来重做一次。可以计算简单的加减乘除带括号。
#include<stdio.h>
#include<stdlib.h>
/*
* 1建立两个栈:符栈、逆波兰表达式栈(存放数字和运算符)
* 2char ch;
* 3while(ch!='\n')
* if(ch==' ') continue;scanf("%c",&ch)
* if(isNum(ch)) 逆栈.push(ch);scanf("%c",&ch)
* else
* if(Empty(符栈)) 符栈.Push(ch);scanf("%c",&ch)
* else Top(符栈,e);
* if(precede(e,ch)=='<') 符栈.Push(ch);scanf("%c",&ch) //符栈顶的优先级低
* else if(precede(e,ch)=='>') Pop(符栈,e);逆栈.Push(e);//ch不变,继续和符栈顶比较
* else Pop(符栈,e);scanf("%c",&ch)
* while(!Empty(符栈)) Pop(符栈,e);逆栈.Push(e);
* 至此,逆波兰表达式建立
*
* 接下来,通过逆波兰表达式计算结果
*
* 数据结构采用顺序栈,栈的数据是char类型
* 所以会出现一些限制:
* 因为栈存储的数据是char,所以表达式中的数字不能是双数,且不能出现小数包括由于除法导致的小数,以及不能是负数
* 仅限于十以内整数加减乘除以及括号
*/
#define STACK_INIT_SIZE 25 //栈空间最大/表达式最长
#define Status char
#define SElemType char
typedef struct{
SElemType * base;
SElemType * top;
int stacksize; //栈当前已分配的空间
}SqStack;
//S.top指向栈顶元素的下一个
Status InitStack(SqStack &S){
S.base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return 1;
}
char precede(char a, char b){ //运算符的优先关系
char mark[6][6] = { {'>','>','<','<','<','>'},
{'>','>','<','<','<','>'},
{'>','>','>','>','<','>'},
{'>','>','>','>','<','>'},
{'<','<','<','<','<','='},
{'>','>','>','>',' ','>'}
};
char ch[6]={'+','-','*','/','(',')'};
for(int i=0;i<6;i++){
if(a==ch[i])
for(int j=0;j<6;j++)
if(b==ch[j]) return mark[i][j];
}
}
int operate(char x, char o, char y){ //二元运算
int a = (int)x-48; int b = (int)y-48;
switch(o){
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/': return a/b;
}
}
Status StackEmpty(SqStack S){
if(S.top==S.base) return 1;
return 0;
}
Status Top(SqStack &S, SElemType &e){
if(S.top==S.base) return 0;
e = *(S.top-1);
return 1;
}
Status Push(SqStack &S, SElemType e){
if(S.top-S.base>=STACK_INIT_SIZE)
S.base = (SElemType *)realloc( S.base, (STACK_INIT_SIZE+S.stacksize)*sizeof(SElemType));
*S.top++ = e;
return 1;
}
Status Pop(SqStack &S, SElemType &e){
if(S.top==S.base) return 0;
e = *--S.top;
return 1;
}
int StackLength(SqStack S){
int n=0;
while(S.top--!=S.base) n++;
return n;
}
void EvaluateExpression(){
SqStack S,T; //符栈,逆波兰表达式栈(逆栈)
InitStack(S);
InitStack(T);
//中序表达式输入,转换成后序表达式
char ch,e;
scanf("%c",&ch);
while (ch!='\n'){
if (ch==' '){scanf("%c",&ch);continue;}
if ((48<=ch && ch<=57)||97<=ch && ch<=122) {Push(T,ch);scanf("%c",&ch);}
else
if(StackEmpty(S)) {Push(S,ch);scanf("%c",&ch);}
else{
Top(S,e);
if(precede(e,ch)=='<') {Push(S,ch);scanf("%c",&ch);}
else if(precede(e,ch)=='=') {Pop(S,e);scanf("%c",&ch);}
else {
Pop(S,e);
Push(T,e);
}
}
}
while(!StackEmpty(S)){
Pop(S,e);
Push(T,e);
}
//至此,T为逆波兰表达式
int i=0;
while(T.top!=(T.base+i)) printf("%c",*(T.base+i++));//输出逆波兰表达式
printf("\n");
// 计算逆波兰表达式
// 接下来就是通过利用逆波兰表达式的特点,通过逻辑,计算结果
SqStack p;
while (StackLength(T)>=3){
i=0;
while (*(T.base+i)>47) i++;
char sum = (char)(operate(*(T.base+(i-2)), *(T.base+i), *(T.base+i-1))+48);
*(T.base+i-2)=sum;
for(int j=i-1;T.top!=(T.base+j+2);j++) *(T.base+j)=*(T.base+j+2);
T.top = T.top-2;
}
printf("%c",*T.base);
}
int main(){
EvaluateExpression();
return 1;
}
/*
中序:
1+2*(4-1)-8/4
后序:
1241-*+84/-
表达式结果:5
中序:
(2*4)-6/3*(2-1)-1+1*2
*/