逆波兰表达式
逆波兰表达式又叫做后缀表达式。在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示。波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法,按此方法,每一运算符都置于其运算对象之后,故称为后缀表示。
a+b ---> a,b,+
a+(b-c) ---> a,b,c,-,+
a+(b-c)*d ---> a,b,c,-,d,*,+
a+d*(b-c)--->a,d,b,c,-,*,+
1、将一个中序表达式转化成为逆波兰表达式
构造两个栈S1,S2,S1用来存放表达式,S2用来暂时存放运算符,最后完成后,该栈是清空的。
(1)如果遇到的是数字,直接进栈S1
(2)如果遇到的是左括号,进栈S2
(3)如果遇到的是右括号,将S2中的运算符全部出栈压入S1中,注意括号不压入
(4)如果遇到的运算符
1.如果此时栈S2为空,则直接将运算符加入到栈S2中;
2.如果此时栈S2不为空,当前运算符的优先级大于等于栈顶运算符的优先级,那么直接入栈S2;
3.如果此时栈S2不为空,当前运算符的优先级小于栈顶运算符的优先级,则将栈顶运算符一直出栈压入到栈S1中, 直到栈为空或者遇到一个运算符的优先级小于等于当前遍历的运算符的优先级,然后将该运算符压入到栈S2中。
(5)遍历完整个中序表达式之后,如果栈S2中仍然存在运算符,那么将这些运算符依次出栈压入到栈S1中,直到栈为空。
2、利用逆波兰表达式求值
维护一个结果栈S3,该栈最后存放的是表达式的值。从左至右的遍历栈S1
(1)如果遇到的是数字,直接将数字压入到S3中
(2)如果遇到的是单目运算符,取S3栈顶的一个元素进行运算之后,将结果压入到栈S3中
(3)如果遇到的是双目运算符,取S3栈顶的两个元素,首先出栈的在左,后出栈的在右进行双目运算符的计算,将结果压入到S3中
遍历完整个栈S1,最后S3中的值就是逆波兰表达式的值。
栈实现表达式计算【数据结构】
思路:
所包含的运算符有‘+’,‘-’,‘*’,‘/’,‘(’,‘)’。
(1)建立两个栈,一个用来存储操作数,另一个用来存储运算符, 开始时在运算符栈中先压入‘/0’,一个表达式的结束符。
(2)然后从左至右依次读取表达式中的各个符号(操作数或者运算符);
(3)如果读到的是操作数直接存入操作数栈;
(4)如果读到的是运算符,则作进一步判断:
若读到的是‘/0’结束符,而且此时运算符栈的栈顶元素也是‘/0’结束符,则运算结束,输出操作数栈中的元素即为最后结果。
若读到的是‘(’或者读到的运算符的优先级比目前的运算符栈中的栈顶元素的优先级高,则将运算符直接存入运算符栈,继续读表达式中的下一个符号,重复步骤(3)和(4);
若读到的是‘)’,而且此时运算符栈的栈顶元素是‘(’结束符,则将运算符栈中的栈顶元素退出来,继续读表达式中的下一个符号,重复步骤(3)和(4);
若读到的运算符的优先级等于或小于之前的运算符的优先级,则从操作数中退出2个,从运算符中退出一个进行运算,将运算结果存入操作数栈;再把之前读到的运算符与目前的运算符栈顶比较,重复步骤(4)(即现在不读下一个元素);
/*
输入:
9+(3-1)*3+10/2
输出
20
注意:其实注释的地方可以用来调试,本人主要根据大话数据结构的思路写出来的
如果有什么地方错了,多谢提出。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
struct stack{
char data[101];
int top;
};
struct stack2{
int data1[101];
int top;
};
struct stack tak;
struct stack2 tak2;
bool jia(char s){
if(s=='+' || s=='-')
return true;
else
return false;
}
bool ch(char s){
if(s=='*' || s=='/')
return true;
else
return false;
}
int number(int y, int x, char s){
if(s=='+')
return x + y;
if(s=='-')
return x - y;
if(s=='*')
return x * y;
if(s=='/' )
return x / y;
}
int main(){
char s1[20];
scanf("%s",&s1);
getchar();
tak.top = 0;
tak2.top = 0;
//中缀表达式转化为后缀表达式
for(int i=0;i<strlen(s1);i++){
if(s1[i]>='0' && s1[i]<='9'){
int tep = s1[i]-'0';
while(s1[i+1]>='0' && s1[i+1]<='9'){
tep *= 10;
i++;
tep += s1[i]-'0';
}
// printf("%d ",tep);
tak2.top++;
tak2.data1[tak2.top] = tep;
}else{
if(tak.top==0 || tak.data[tak.top]=='('){
tak.top++;
tak.data[tak.top] = s1[i];
}else{
char temp = tak.data[tak.top];
if( jia(temp) && (ch(s1[i]) || jia(s1[i]) || s1[i]=='(') ){
tak.top++;
tak.data[tak.top] = s1[i];
}else if(ch(temp) && (ch(s1[i]) || s1[i]=='(')){
tak.top++;
tak.data[tak.top] = s1[i];
}else if(s1[i]==')'){
while(tak.top>0){
if(tak.data[tak.top]=='('){
tak.top--;
break;
}
// printf("%c ",tak.data[tak.top]);
int t1 = tak2.data1[tak2.top];
tak2.top--;
int t2 = tak2.data1[tak2.top];
int t3 = number(t1,t2,tak.data[tak.top]);
tak2.data1[tak2.top] = t3;
tak.top--;
}
}else if(ch(temp) && jia(s1[i])){
while(tak.top>0){
if(tak.data[tak.top]=='('){
break;
}
// printf("%c ",tak.data[tak.top]);
int t1 = tak2.data1[tak2.top];
tak2.top--;
int t2 = tak2.data1[tak2.top];
int t3 = number(t1,t2,tak.data[tak.top]);
tak2.data1[tak2.top] = t3;
tak.top--;
}
tak.top++;
tak.data[tak.top] = s1[i];
}
}
}
}
while(tak.top>0){
// printf("%c ",tk.data[tak.top]);
int t1 = tak2.data1[tak2.top];
tak2.top--;
int t2 = tak2.data1[tak2.top];
int t3 = number(t1,t2,tak.data[tak.top]);
tak2.data1[tak2.top] = t3;
// cout<<" t3 = "<<t3<<endl;
tak.top--;
}
printf("%d",tak2.data1[tak2.top]);
return 0;
}