一、概念
算术表达式是由操作数(运算数)、运算符(操作符)、和界线符(括号)三部分组成,在计算机中进行算术表达式的计算是通过堆栈来实现的。
二后缀表达式的逻辑和实现方式(逆波兰表达式求值)
1.定义
如果每个操作符跟在它的两个操作数之后,而不是两个操作数之间,那么这个表达式就是后缀表达,又称为逆波兰表达式,如:3 5 + 7 * 1 -
2.后缀表达式计算机求值
1.与前缀表达式类似,只是顺序是从左至右:
2.从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,其中先出栈的是右操作数,后出栈的是左操作数,
3.用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;
4.重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
3.例子
计算后缀表达式的值:1 2 3 + 4 × + 5 -
1)从左至右扫描,将1,2,3压入栈;
2)遇到+运算符,3和2弹出,计算2+3的值,得到5,将5压入栈;
3)遇到4,将4压入栈
4)遇到×运算符,弹出4和5,计算5×4的值,得到20,将20压入栈;
5)遇到+运算符,弹出20和1,计算1+20的值,得到21,将21压入栈;
6)遇到5,将5压入栈;
7)遇到-运算符,弹出5和21,计算21-5的值,得到16为最终结果
三代码实现:
#include<iostream>
using namespace std;
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAXSIZE 100
#define ok 1
#define error 0
#define ovrflow -1
typedef int status;
typedef struct number{// 数值
int data;
struct number *next;
}number,*number1;
typedef struct signal{// 字符
char data;
struct signal *next;
}sign,*sign1;
status push1(number1 &s,int elem);
status push2(sign1 &s,char elem);
status in(char elem);
int pop1(number1 &s);
int pop2(sign1 &s);
status gettop1(number1 s);
char gettop2(sign1 s);
int get_index(char str);
char precede(char a, char b);
int operate(int x,char a,int y);
char characters[7] = {'+', '-', '*', '/', '(', ')', '#'};
char priority[7][7] = {
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', ' '},
{'>', '>', '>', '>', ' ', '>', '>'},
{'<', '<', '<', '<', '<', ' ', '='}
}; // 各个运算符之间的优先级关系
int get_index(char str)
{// 获取相应运算符的索引
for(int i = 0; i < 7; i++)
{
if(str==characters[i]) return i;
}
printf("未找到匹配的字符\n");
}
char precede(char a, char b)
{ //获取两个运算符之间的优先级关系
int x = get_index(a);
int y = get_index(b);
return priority[x][y];
}
int main(int argc, char** argv){
while(1){
number1 s1=NULL;
sign1 s2=NULL;//初始化
int x,y,n,elem=0,flag=0,j,k=0;
char *a=new char[100],c,m;
while(1){
cout<<"请输入表达式:";
scanf("%s",a);
x=strlen(a);
push2(s2,'#');
for(int i=0;i<x;i++){
if(flag==1) break;
if(a[i]!='#'||gettop2(s2)!='#')
if(in(a[i])!=0){//如果是数值
k=0;
k=k*10+(a[i]-48);
i++;
while(in(a[i])!=0){
k=k*10+(a[i]-48);
i++;
}
i--;
push1(s1,k);
}
else {
if(a[i]==' '){
continue;
}
switch(precede(gettop2(s2),a[i])){
case '<':
push2(s2,a[i]);break;
case '=':
pop2(s2);break;
case '>':
c=pop2(s2);
y=pop1(s1);
n=pop1(s1);
elem=operate(n,c,y);
push1(s1,elem);
i--;break;
default:
cout<<"该优先级不存在,表达式错误,请重新输入"<<endl;
flag=1;
}
}
}
printf("%d\n",gettop1(s1));
}
}
return 0;
}
status in(char c){
if(c>=48&&c<=58){
return ok;
}
return error;
}
status push1(number1 &s,int elem){
number *p;
p=new number;
p->data=elem;
p->next=s;
s=p;
return ok;
}
status push2(sign1 &s,char elem){
sign *p;
p=new sign;
p->data=elem;
p->next=s;
s=p;
return ok;
}
int pop1(number1 &s){
int x;
if(s==NULL) return error;
number *p=s;
s=s->next;
x=p->data;
delete p;
return x;
}
int pop2(sign1 &s){
char c;
if(s==NULL) return error;
sign *p=s;
s=s->next;
c=p->data;
delete p;
return c;
}
status gettop1(number1 s){
if(s==NULL) return error;
return s->data;
}
char gettop2(sign1 s){
if(s==NULL) return error;
return s->data;
}
int operate(int x,char a,int y){
if(a=='+') return x+y;
if(a=='-') return x-y;
if(a=='*') return x*y;
if(a=='/') return x/y;
}