波兰序列和逆波兰序列
目录
例如表达式:8+(3-1)*5
则:建立二叉树,根节点都是运算符,叶子节点都是操作数。
前序遍历:波兰序列(前缀表达式)
中序遍历:原始表达式(中缀表达式)
后序遍历:逆波兰序列(后缀表达式)
整个过程既可以由栈来实现,也可以由二叉树来实现,下面分别来实现两种方法。
1、栈
中缀表达式——>后缀表达式
从前往后遍历:
- 若为操作数,则直接输出
- 若为(,则直接压栈
- 若为),则弹出栈顶元素,直到遇到(
- 其他运算符,栈为空、栈顶为(、栈顶优先级低,则直接压栈;否则先弹出栈顶元素,再压入新元素
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
//数组的横纵顺序:+ - * /
//x<y则为1,否则为0
int cmp[4][4]={{0,0,1,1},{0,0,1,1},{0,0,0,0},{0,0,0,0}};
//若top优先级低于c,则返回1,否则返回0
int compare(char top,char c){
int x,y;
if(top=='+') x=0;
else if(top=='-') x=1;
else if(top=='*') x=2;
else x=3;
if(c=='+') y=0;
else if(c=='-') y=1;
else if(c=='*') y=2;
else y=3;
return cmp[x][y];
}
int main(){
string s;
cin>>s;
cout<<"中缀表达式:"<<s<<endl;
stack<char> stk;
string res; //输出的结果
for(auto c:s){
if(c>='0'&&c<='9') res+=c; //1.若为操作数,则直接输出
else if(c=='(') stk.push(c);//2.若为(,则直接压栈
else if(c==')'){ //3.若为),则弹出栈顶元素,直到遇到(
while(stk.size()&&stk.top()!='('){//弹出栈顶元素,直到遇到(
res+=stk.top();
stk.pop();
}
stk.pop(); //弹出左括号
}
else{ //4.其他运算符,栈为空/栈顶为(/栈顶优先级低,则直接压栈
if(stk.empty()) stk.push(c);//栈为空
else{
if(stk.top()=='(') stk.push(c);//若栈顶是(,则直接压栈
else if(compare(stk.top(),c)) stk.push(c);//栈顶优先级低
else { //栈顶优先级不低,则先弹出栈顶元素,再压入新元素
while(stk.size()&&stk.top()!='('&&!compare(stk.top(),c)){
res+=stk.top();
stk.pop();
}
stk.push(c);//压入新元素
}
}
}
}
while(stk.size()){//若栈还非空,弹出栈元素
res+=stk.top();
stk.pop();
}
cout<<"后缀表达式:"<<res<<endl;
return 0;
}
中缀表达式——>前缀表达式
从后往前遍历:
- 若为数值,则直接输出
- 若为),则压入栈中
- 若为(,则弹出栈顶元素,直到遇到)
- 其他运算符,若栈为空、栈顶为)、比栈顶元素优先级高或相等,则直接压栈,否则弹出元素,再压入新元素
- 反转最后结果
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
//数组的横纵顺序:+ - * /
//x>y则为0,否则为1
int cmp2[4][4]={{1,1,1,1},{1,1,1,1},{0,0,1,1},{0,0,1,1}};
//若top优先级高,则不能压栈
int compare2(char top,char c){
int x,y;
if(top=='+') x=0;
else if(top=='-') x=1;
else if(top=='*') x=2;
else x=3;
if(c=='+') y=0;
else if(c=='-') y=1;
else if(c=='*') y=2;
else y=3;
return cmp2[x][y];
}
int main(){
string s;
cin>>s;
cout<<"中缀表达式:"<<s<<endl;
/*********************************前缀表达式*************************************/
string res2; //存放输出结果
stack<char> stk2;
for(int i=s.size()-1;i>=0;i--){//从后往前遍历
if(s[i]>='0'&&s[i]<='9') res2+=s[i]; //1.若为数值,则直接输出
else if(s[i]==')') stk2.push(s[i]); //2.若为),则压入栈中
else if(s[i]=='(') { //3.若为(,则弹出栈顶元素,直到遇到)
while(stk2.top()!=')'){
res2+=stk2.top();
stk2.pop();
}
stk2.pop(); //弹出右括号
}
else{ //4.其他运算符,若栈为空、栈顶为)、比栈顶元素优先级高或相等,则直接压栈
if(stk2.empty()) stk2.push(s[i]); //栈为空
else if(stk2.top()==')') stk2.push(s[i]); //栈顶为)
else{
if(compare2(stk2.top(),s[i])) stk2.push(s[i]); //比栈顶元素优先级高或相等
else{
while(stk2.size()&&stk2.top()!=')'&&!compare2(stk2.top(),s[i])){//栈顶元素优先级高,弹出元素
res2+=stk2.top();
stk2.pop();
}
stk2.push(s[i]);//压入新元素
}
}
}
}
while(stk2.size()) { //若栈非空,弹出元素
res2+=stk2.top();
stk2.pop();
}
reverse(res2.begin(),res2.end()); //反转最后结果
cout<<"前缀表达式:"<<res2<<endl;
return 0;
}
2、树
递归建立树
#include<iostream>
#include<algorithm>
using namespace std;
//二叉树节点结构
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode(char x):val(x),left(NULL),right(NULL){
}
};
const int N=4;
//x>=y——>1
int cmp[N][N]={
//+ - * /
{1,1,0,0},//+
{1,1,0,0},//-
{1,1,1,1},//*
{1,1,1,1}};///
//运算符集合
char op[N]={'+','-','*','/'};
//若a>=b返回1(这里>=指优先级)
int compare(char a,char b){
int x,y;
for(int i=0;i<N;i++){
if(a==op[i]) x=i;
if(b==op[i]) y=i;
}
return cmp[x][y];
}
//判断c是否是运算符
bool check(char c){
for(int i=0;i<N;i++)
if(c==op[i]) return true;
return false;
}
//在s的[left,right]区间内找到优先级最低的下标返回
int find(const string &s,int left,int right){
char minc='*';
int res=-1;
int bracket;
for(int i=left;i<=right;i++){
bracket=0;
if(s[i]=='('){//遇到括号,把(...)看成一个:(一个运算数)
bracket++;
while(bracket){
i++;
if(s[i]=='(') bracket++;
else if(s[i]==')') bracket--;
}
continue; //作用于外for循环
}
if(check(s[i])&&compare(minc,s[i])){
res=i;
minc=s[i];
}
}
return res;
}
//...w... w是优先级最低的下标,为当前根节点,继续递归处理w左半边和w右半边,分别为左子树和右子树
TreeNode* createTree(const string &s,int left,int right){
auto root=new TreeNode(-1);
if(left>=right){
root->val=s[left];
return root;
}
int bracket=0;//括号标记判断
if(s[left]=='('&&s[right]==')'){
bracket++;
int j=left;
while(bracket){//若是(...)则处理,若是(.).(.)则不处理
j++;
if(s[j]=='(') bracket++;
else if(s[j]==')') bracket--;
}
if(j==right) {//剥下最外层括号(...)——>...
left++;
right--;
}
}
int w=find(s,left,right);
root->val=s[w];
root->left=createTree(s,left,w-1);
root->right=createTree(s,w+1,right);
return root;
}
//先序遍历:前缀表达式
void preOrder(TreeNode* root){
if(root){
cout<<root->val<<" ";
preOrder(root->left);
preOrder(root->right);
}
}
//中序遍历:中缀表达式
void inOrder(TreeNode* root){
if(root){
inOrder(root->left);
cout<<root->val<<" ";
inOrder(root->right);
}
}
//后序遍历:后缀表达式
void postOrder(TreeNode* root){
if(root){
postOrder(root->left);
postOrder(root->right);
cout<<root->val<<" ";
}
}
int main(){
string s;
cin>>s;
auto root=createTree(s,0,s.size()-1);
cout<<"前缀表达式:";
preOrder(root);
cout<<endl;
cout<<"中缀表达式:";
inOrder(root);
cout<<endl;
cout<<"后缀表达式:";
postOrder(root);
cout<<endl;
return 0;
}