对于自然数的表达式求值,操作有加、减、乘、除和幂运算,分别用+,-, *, /,^来表示,为方便运算,加入#运算符,其运算优先级最低,由于运算符优先级不一样,可以利用栈实现此操作。
算法思想
(1)规定运算符的优先级表
(2)设置两个栈:OVS(运算数栈)和OPTR(运算符栈),为了操作方便可以先在OPTR栈中先放一个#运算符
(3)自左向右扫描,进行如下处理:
若遇到运算数则金OVS栈;若遇到运算符则与OPTR栈顶运算符进行比较:
•如果当前运算符的优先级大于OPTR栈顶运算符的优先级,则当前运算符进入OPTR栈;
•如果当前运算符的优先级大于等于OPTR栈顶运算符的优先级,则OPTR退栈一次,得到栈顶运算符op, 连续退栈OVS两次,得到运算数a和b,执行op运算,得到结果T,将T进OVS栈。
可以自己画一个表达式两个栈的变化图,有助于理解
#include<stdio.h> #include<stdlib.h> #include<math.h> #include<stdbool.h> typedef struct node{ int data;//无论对于运算符还是运算数,都用int型变量来保存 node *next; }LinkStackNode, *LinkStack; void InitStack(LinkStack *S){//初始化链栈 *S = (LinkStack)malloc(sizeof(LinkStackNode)); (*S)->next = NULL; } int Push(LinkStack top, int x){// 进栈操作 LinkStackNode *temp; temp = (LinkStackNode*)malloc(sizeof(LinkStackNode)); if(temp == NULL) return 0; temp->data = x; temp->next = top->next; top->next = temp; return 1; } int Pop(LinkStack top, int *x){//出栈操作 LinkStackNode *temp; temp = top->next; if(temp == NULL) return 0; *x = temp->data; top->next = temp->next; free(temp); return 1; } int GetNum(char ch){//返回字符对应的数字 return ch - '0'; } bool IsEmpty(LinkStack top){//栈为空返回假 if(top->next == NULL) return false; return true; } int GetTop(LinkStack top){//返回栈顶元素 if(top->next == NULL) return 1; return top->next->data; } char Compare(char ch1, char ch2){//实现运算符优先级比较 switch(ch1){ case '#': switch(ch2){ case '#': return '='; case '+': case '-': case '*': case '/': case '^': return '<'; } case '+': switch(ch2){ case '#': return '>'; case '+': case '-': return '='; case '*': case '/': case '^': return '<'; } case '-': switch(ch2){ case '#': return '>'; case '+': case '-': return '='; case '*': case '/': case '^': return '<'; } case '*': switch(ch2){ case '#': case '+': case '-': return '>'; case '*': case '/': return '='; case '^': return '<'; } case '/': switch(ch2){ case '#': case '+': case '-': return '>'; case '*': case '/': return '='; case '^': return '<'; } case '^': switch(ch2){ case '#': case '+': case '-': case '*': case '/': return '>'; case '^': return '='; } } } int Calculate(int a, char op, int b){//计算 a op b 的值 int c; switch(op){ case '-': c = a - b; break; case '+': c = a + b; break; case '*': c = a * b; break; case '/': c = a / b; break; case '^': c = pow(a, b); break; default : c = 0; } return c; } int ExpEvaluation(){//实现 LinkStack ovs, optr; InitStack(&ovs); InitStack(&optr); Push(optr, (int)'#'); printf(" Please input an expression(Ending with '#'): "); char ch = getchar(); int num = 0, a, b, t, op, zan; while(ch != '#' || (char)GetTop(optr) != '#'){ while(ch >= '0' && ch <= '9'){//如果数字不是一位数字,便把字符转化为数字 num = num * 10 + GetNum(ch); ch = getchar(); } if(num != 0){//如果num不为0便进OVS栈 Push(ovs, num); num = 0;//把num置零 } else{ switch(Compare(ch, (char)GetTop(optr))){//对运算符优先级进行比较,实现对应三种关系的操作 case '>': Push(optr, (int)ch); ch = getchar(); break; case '=': case '<': Pop(optr, &op); Pop(ovs, &a); Pop(ovs, &b); t = Calculate(b, (char)op, a); Push(ovs, t); break; } } } t = GetTop(ovs);//取栈顶元素,返回值 return t; } int main(){ int ans = ExpEvaluation(); printf("%d ", ans); return 0; }