算法思想:表达式中的对象为操作数和运算符,因此需要维护两个栈表:运算符栈和操作数(中间运算结果)栈,具体算法步骤如下。
S1
和储存中间结果的栈S2
;S2
;S1
栈顶运算符的优先级:S1
为空,或栈顶运算符为右括号)
,则直接将此运算符入栈;S1
;S1
栈顶的运算符弹出并压入到S2
中,再次转到(4-1)与S1中新的栈顶运算符相比较;)
,则直接压入S1
;(
,则依次弹出S1
栈顶的运算符,并压入S2
,直到遇到右括号为止,此时将这一对括号丢弃;S1
中剩余的运算符依次弹出并压入S2
;S2
中的元素并输出,结果即为中缀表达式对应的前缀表达式。#include
#include
#include
#include
#include
using namespace std;
stack<char> q1; // 运算符号栈
stack<char> q2; // 答案栈
// 判断优先级函数
bool y(char a1,char a2){
if(a1=='+'||a1=='-'){ //优先级判断1
if(a2==')'||a2 == '+'||a2 == '-')
return true;
else return false;
}
else if(a1=='*'||a1=='/'||a1=='%') //优先级判断2
return true;
return false;
}
//弹出函数
void se(){
//如果是左括号,开始弹出两个括号之间多有的内容
while(1){
if(q1.top()!='('&&q1.top()!=')'){
q2.push(q1.top());
}
if(q1.top()==')'||q1.empty())break;
q1.pop(); //弹出操作
}
if(q1.top()==')')q1.pop(); //将最后一个右括号也弹出
}
int main(int argc, const char * argv[]) {
string s1 ;
cin>>s1;
for(int i = s1.size()-1;i>=0;i--){
if(s1[i]>='0'&&s1[i]<='9')q2.push(s1[i]);
else{
if(q1.size()==0||q1.top()==')'||s1[i]==')')q1.push(s1[i]); //如果是空或者右括号,直接压入q1栈
else if(s1[i]=='('){q1.push(s1[i]);se();} // 如果是左括号,先压入栈,然后开始找右括号
else if(y(s1[i],q1.top()))q1.push(s1[i]); // 如果优先级高,直接压入栈
else {
while(!q1.empty()&&!y(s1[i],q1.top())){ //优先级低 开始一个一个弹出栈
if(q1.empty()||q1.top()==')'||q1.top()=='(')break;
q2.push(q1.top());
q1.pop();
}
q1.push(s1[i]); //最后还得把这个操作符入栈
}
}
}
//最后q1栈如果不是空,把剩余的非括号都压入栈
while(!q1.empty()){
if(q1.top()!='('&&q1.top()!=')')
q2.push(q1.top());
q1.pop();
}
//遍历q2栈
while(!q2.empty()){
cout<<q2.top();
q2.pop();
}
cout<<endl;
return 0;
}
与转换为前缀表达式相似,遵循以下步骤:
S1
和储存中间结果的栈S2
;S2
;S1
栈顶运算符的优先级:S1
为空,或栈顶运算符为左括号(
,则直接将此运算符入栈;S1
(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);S1
栈顶的运算符弹出并压入到S2
中,再次转到(4-1)与S1
中新的栈顶运算符相比较;(
,则直接压入S1
;)
,则依次弹出S1
栈顶的运算符,并压入S2
,直到遇到左括号为止,此时将这一对括号丢弃;S1
中剩余的运算符依次弹出并压入S2
;S2
中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。//
// main.cpp
// step1
//
// Created by ljpc on 2018/8/31.
// Copyright © 2018年 ljpc. All rights reserved.
//
#include
#include
#include
#include
#include
using namespace std;
stack<char> q1; // 运算符号栈
stack<char> q2; // 答案栈
bool y(char a1,char a2){
if(a1=='+'||a1=='-'){ //优先级判断1
if(a2=='(')
return true;
else return false;
}
else if(a1=='*'||a1=='/'||a1=='%') { //优先级判断2
if(a2 == '+'||a2 == '-')
return true;
}
return false;
}
void se(){
//如果是左括号,开始弹出两个括号之间多有的内容
while(1){
if(q1.top()!=')'&&q1.top()!='('){
q2.push(q1.top());
}
if(q1.top()=='('||q1.empty())break;
q1.pop(); //弹出操作
}
if(q1.top()=='(')q1.pop(); //将最后一个左括号也弹出
}
int main(int argc, const char * argv[]) {
string s1 ;
cin>>s1;
for(int i = 0 ;i<s1.size();i++){
if(s1[i]>='0'&&s1[i]<='9')q2.push(s1[i]);
else{
if(q1.size()==0||q1.top()=='('||s1[i]=='(')q1.push(s1[i]); //如果是空或者左括号,直接压入q1栈
else if(s1[i]==')'){q1.push(s1[i]);se();} // 如果是左括号,先压入栈,然后开始找右括号
else if(y(s1[i],q1.top()))q1.push(s1[i]); // 如果优先级高,直接压入栈
else {
while(!q1.empty()&&!y(s1[i],q1.top())){ //优先级低 开始一个一个弹出栈
if(q1.empty()||q1.top()=='('||q1.top()==')')break;
q2.push(q1.top());
q1.pop();
}
q1.push(s1[i]); //最后还得把这个操作符入栈
}
}
}
//最后q1栈如果不是空,把剩余的非括号都压入栈
while(!q1.empty()){
if(q1.top()!='('&&q1.top()!=')')
q2.push(q1.top());
q1.pop();
}
//遍历q2栈
char arr[1000] ={0};
int l = q2.size();
int i=0;
while(!q2.empty()){
arr[i++] = q2.top();
q2.pop();
}
for(int i=l-1;i>=0;i--)cout<<arr[i];
cout<<endl;
return 0;
}
算法思想:从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 - 运算符 - 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。可见用计算机计算前缀表达式的值是非常容易的。
例如前缀表达式- * + 3 4 5 6
:
(1) 从右至左扫描,将6、5、4、3
压入堆栈; (2) 遇到+
运算符,因此弹出3
和4
(注意3
为栈顶元素,4
为次顶元素),计算出3+4
的值,得7
,再将7
入栈; (3) 接下来是*
运算符,因此弹出7
和5
,计算出7*5=35
,将35
入栈; (4) 最后是-
运算符,计算出35-6
的值,即29
,由此得出最终结果。
#include
#include
#include
#include
#include
using namespace std;
stack<string> q;
string s;
// 计算运算结果
string yun(int a1,int a2,char s1){
if(s1=='+')return to_string(a1+a2);
else if(s1=='-')return to_string(a1-a2);
else if(s1=='*')return to_string(a1*a2);
}
//压入栈
void se(char s1){
int q1 = stoi(q.top());
q.pop();
int q2 = stoi(q.top());
q.pop();
string q3 = yun(q1,q2,s1);
q.push(q3);
}
int main(int argc, const char * argv[]) {
cin>>s;
for(int i=s.size()-1;i>=0;i--){
if(s[i]==')'||s[i]=='(')continue;
else if(s[i]>='0'&&s[i]<='9'){string d ;d+=s[i] ;q.push(d);} //用字符串的形式来储存元素
else se(s[i]);
}
cout<<q.top()<<endl;
return 0;
}
算法思想:与前缀表达式类似,从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 - 运算符 - 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式3 4 + 5 * 6 -
: (1) 从左至右扫描,将3
和4
压入堆栈; (2) 遇到+运算符,因此弹出4
和3
(注意4
为栈顶元素,3
为次顶元素,注意与前缀表达式做比较),计算出3+4
的值,得7
,再将7
入栈; (3) 将5
入栈; (4) 接下来是*
运算符,因此弹出5
和7
,计算出7*5=35
,将35
入栈; (5) 将6
入栈; (6) 最后是-
运算符,计算出35-6
的值,即29
,由此得出最终结果。
#include
#include
#include
#include
#include
using namespace std;
stack<string> q;
string s;
string yun(int a1,int a2,char s1){
if(s1=='+')return to_string(a1+a2);
else if(s1=='-')return to_string(a2-a1);
else if(s1=='*')return to_string(a1*a2);
}
void se(char s1){
int q1 = stoi(q.top());
q.pop();
int q2 = stoi(q.top());
q.pop();
string q3 = yun(q1,q2,s1);
q.push(q3);
}
int main(int argc, const char * argv[]) {
cin>>s;
for(int i=0;i<s.size();i++){
if(s[i]==')'||s[i]=='(')continue;
else if(s[i]>='0'&&s[i]<='9'){string d ;d+=s[i] ;q.push(d);}
else se(s[i]);
}
cout<<q.top()<<endl;
return 0;
}