题目描述
给定一串计算表达式
例如 (1+2*4-2)*3+4 * (2+4)/2
计算此表达式的值,并输出此表达式树的前序中序后序序列。
题解思路
首先,给定的表达式为正常逻辑的中缀表达式,我们需要将其转化为逆波兰式(后缀表达式),如下给出理由
例如 a*b-c
它的二叉树如下
前序序列为:- * a b c
中序序列为: a * b - c
后序序列为: a b * c -
对于前序序列,运算顺序应该为首先对离运算符最近的ab操作,ab前有乘号,将ab相乘,代替ab的位置,然后此时离运算符最近的为ab的结果与c,前方的操作符为-号则进行a*b-c操作。而此种运算顺序实际上不利于代码模拟。
相反,对于后序序列,则可以用栈轻松模拟,首先创建一个操作数栈,从左到右遍历。
- 首先为a,压入操作数栈
- 对b来说,压入操作数栈
- 对*来说,取出操作数栈中栈顶元素和次栈顶元素b,a并将这两个元素pop操作。将b,a进行相乘后重新压入操作数栈
- 对c来说,压入操作数栈
- 对-来说,取出操作数栈中栈顶元素和次栈顶c和a*b,将这两个元素进行先相减操作,重新压入栈。(注意为次栈顶减栈顶)
- 结束后栈中剩下的一个数则为表达式的值
因此我们想要计算表达式,可以先将其转化成逆波兰式(后缀表达式),就可以计算出值,而对于如何从中缀表达式转成后缀表达式,思路如下:
首先创建一个运算符栈,从左到右遍历,利用vector存储答案
- 如果为操作数,直接压入vector
- 如果为运算符
- 如果此时运算符栈为空,直接压入运算符栈
- 如果运算符为(,左括号的话,直接压入运算符栈
- 如果此时运算符为),右括号的话,不断将运算符栈顶元素压入vector,直到匹配到(,左括号为止(注意:左右括号都不进入vector)
- 如果此时运算符优先级大于栈顶元素,直接压入运算符栈
- 如果运算符优先级小于等于栈顶元素,不断将运算符栈顶元素压入vector,直到栈空或者栈顶元素优先级小于此运算符,然后将此运算符压入运算符栈。
vector中即为后缀表达式。
对于正确性,可以自己写几个例子简单模拟一下。
解决了从中缀转后缀,就可以算出值,而对于通过后缀表达式建立二叉树,思路与后缀表达式计算一样。
思路如下:(从左到右遍历后缀表达式)
首先创建一个指针栈
- 如果此时为操作数,创建指针指向此数,将指针压入栈
- 如果此时为操作符,创建指针指向此操作符,再将栈顶指针和次栈顶指针拿出,将此操作符指针的左孩子指针指向原次栈顶指针,右孩子指针指向原栈顶指针。再将此操作符指针压入栈中。
结束后栈中剩下的指针即为此二叉树的根结点指针。
代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#include <vector>
using namespace std;
const int N=100010;
typedef struct node
{
char data[1000];
struct node *lchild;
struct node *rchild;
}node,*root;
string str,str1;
vector<string>res;
int ans=0;
int fun2(string a)//运算符优先级判断
{
if(a[0]=='+'||a[0]=='-')return 0;
if(a[0]=='*'||a[0]=='/')return 1;
if(a[0]=='(')return -1;
}
bool cmp(string a,string b)
{
int x=fun2(a),y=fun2(b);
if(x<y)return 1;
return 0;
}
void fun1()//中缀表达式转后缀表达式
{
vector<string>v;
string p="";
for(int i=