- 输入一行中缀表达式,转换一颗二叉表达式树,并求解.
- 表达式只包含
+
,-
,*
,/
,(
,)
运算符,操作数只有一位,且为整数(有兴趣同学可以考虑负数小数,两位数做法)。按照先括号,再乘除,后加减的规则构造二叉树。 - 如图所示是"1+(2+3)*2-4/5"代数表达式对应二叉树,用对应的二叉树计算表达式的值。
转换二叉树如下:
###输入要求
输入一行字符串
###输出要求
输出结算结果,如遇到除0,提示divide 0 error!
函数接口定义:
void InitExpTree(BTree &T,string str) ; //建表达式的二叉树
double EvaluateExTree(BTree T);//计算表达式树
T
:二叉树str
:输入的表达式
裁判测试程序样例:
#include<iostream>
#include<string>
#include<stack>
using namespace std;
typedef struct BiTNode{ //二叉树的二叉链表存储表示
char data;
struct BiTNode *lchild,*rchild;
}BTNode,*BTree;
void InitExpTree(BTree &T,string str) ; //建二叉表达式树
double EvaluateExTree(BTree T);//计算表达式树
char Precede(char t1,char t2) ;//比较t1,t2运算符优先级函数
int In(char c) ;//判断c是否运算符
void CreateExpTree(BTree &T,BTree a,BTree b,char ch);//建简单二叉树
void DestroyBTree(BTree bt);//销毁树
int main()
{
string str;
BTree T;
getline(cin,str);
InitExpTree(T,str); //创建表达式树
cout<<EvaluateExTree(T); //输出值
DestroyBTree(T);
return 0;
}
char Precede(char t1,char t2)
{ /*判断两符号的优先关系 */
char f;
switch(t2)
{
case '+': if(t1=='('||t1=='#') f='<';
else f='>';
break;
case '-': if(t1=='('||t1=='#') f='<';
else f='>';
break;
case '*':if(t1=='*'||t1=='/'||t1==')') f='>';
else f='<';
break;
case '/':if(t1=='*'||t1=='/'||t1==')') f='>';
else f='<';
break;
case '(': if(t1!=')') f='<';
break;
case')': if(t1=='(') f='=';
else f='>';
break;
case'#': if(t1=='#') f='=';
else f='>';
}
return f;
}
int In(char c)
{ /* 判断c是否为运算符 */
switch(c)
{
case '+':
case'-':
case'*':
case '/':
case'#':
case '(':
case')':return 1;break;
default:return 0;
}
}
void CreateExpTree(BTree &T,BTree a,BTree b,char ch)
{ //简单二叉树的创建
T=new BTNode;
T->data=ch;
T->lchild=a;
T->rchild=b;
}
void DestroyBTree(BTree bt)//销毁树
{
if(bt!=NULL)
{
DestroyBTree(bt->lchild);
DestroyBTree(bt->rchild);
delete bt;
}
}
/* 请在这里填写答案 */
输入样例:
1+2*3
输出样例:
7
这题涉及的知识点比较多
思路:
输入str=1+(2+3)*2-4/5
中序in=1+2+3*2-4/5(对应是表达树的中序遍历)
后序la=123+2*+45/-(对应树的后序遍历)
然后中序后序求表达树
计算树就是后序遍历尾递归结果求值。
除数是0就exit(0);
代码里面有测试代码,去掉注释可以看过程。
#include<iostream>
#include<string>
#include<stack>
using namespace std;
typedef struct BiTNode { //二叉树的二叉链表存储表示
char data;
struct BiTNode* lchild, * rchild;
}BTNode, * BTree;
//---------------------------------------------------//
#include<bits/stdc++.h>
#define node BiTNode
#define x data
#define lc lchild
#define rc rchild
//必须吐槽集美作业
void last(node* p)//测试函数
{
if (p)
{
last(p->lc);
last(p->rc);
cout << p->data;
}
else
{
return;
}
}
void inorder(node* p)//测试函数
{
if (p)
{
inorder(p->lc);
cout << p->data;
inorder(p->rc);
}
else
{
return;
}
}
int in2[1000];
int la2[1000];
string str2;
void getsuf(string& s, string str)
{
stack<char>sta;
stack<int>sta2;
int idx = 0;
int cnt = 0;
while (idx < str.size())
{
if (isdigit(str[idx]))
{
s += str[idx];
la2[cnt] = idx;cnt++;
}
else if (str[idx] == '+' || str[idx] == '-')
{
while (!sta.empty() && sta.top() != '(')
{
s += sta.top();sta.pop();
la2[cnt] = sta2.top();cnt++;sta2.pop();
}
sta.push(str[idx]);
sta2.push(idx);
}
else if (str[idx] == '*' || str[idx] == '/' || str[idx] == '(')
{
sta.push(str[idx]);
sta2.push(idx);
}
else if (str[idx] == ')')
{
while (sta.top() != '(')
{
s += sta.top();sta.pop();
la2[cnt] = sta2.top();cnt++;sta2.pop();
}
sta.pop();
sta2.pop();
}
idx++;
}
while (!sta.empty())
{
s += sta.top();sta.pop();
la2[cnt] = sta2.top();cnt++;sta2.pop();
}
}
string la;
string in;
int n;
int find(int num,int l,int r)
{
for (int i = r;i >= l;i--)//因为有重复结点,要用下标确定唯一性
if (in2[i] == num)
return i;
}
void build(node*& now, int l, int r, int idx)//lr是中序的范围
{//中序找长度,后序找位置,idx是后序对于的字符下标
if (l > r || idx >= n)
{
now = NULL;
return;
}
now = new node;now->lchild = NULL;now->rchild = NULL;
now->x = str2[la2[idx]];
// cout << la2[idx] << endl;
int pos = find(la2[idx],l,r);
if (pos>r||l==r)
return;
int len = r - pos;
//cout << "右" << endl;
build(now->rc, pos + 1, r, idx + 1);
//cout << "左" << endl;
build(now->lc, l, pos - 1, idx + 1 + len);
//cout << "退" << endl;
}
void InitExpTree(BTree& T, string str)
{
str2 = str;
T = NULL;//T->lchild = NULL;T->rchild = NULL;
int cnt = 0;
for (int i = 0;i < str.size();i++)
{
if (str[i] != '(' && str[i] != ')')
{
in += str[i];
in2[cnt] = i;cnt++;
}
}
getsuf(la, str);
n = la.size();
//cout << "suffix:" << la << endl;
reverse(la.begin(), la.end());
reverse(la2, la2+n);
build(T, 0, n - 1, 0);
// last(T);cout << endl;
// inorder(T);cout << endl;
}
double EvaluateExTree(BTree T)
{
if (isdigit(T->data))
{
//cout << "返回值:" << T->data - '0' << endl;
return T->data - '0';
}
double res1 = EvaluateExTree(T->lchild);
double res2 = EvaluateExTree(T->rchild);
// cout << "计算:" <<res1<< T->data <<res2<< endl;
if (T->data == '+')
return res1 + res2;
else if (T->data == '-')
return res1 - res2;
else if (T->data == '*')
return 1.0 * res1 * res2;
else if (T->data == '/')
{
if (res2 == 0)
{
cout << "divide 0 error!";
exit(0);
}
return 1.0 * res1 / res2;
}
}
#undef node
#undef x
#undef lchild
#undef rchild
//---------------------------------------------------//
int main()
{
string str;
BTree T;
getline(cin, str);
InitExpTree(T, str); //创建表达式树
cout << EvaluateExTree(T); //输出值
return 0;
}
char Precede(char t1, char t2)
{ /*判断两符号的优先关系 */
char f;
switch (t2)
{
case '+': if (t1 == '(' || t1 == '#') f = '<';
else f = '>';
break;
case '-': if (t1 == '(' || t1 == '#') f = '<';
else f = '>';
break;
case '*':if (t1 == '*' || t1 == '/' || t1 == ')') f = '>';
else f = '<';
break;
case '/':if (t1 == '*' || t1 == '/' || t1 == ')') f = '>';
else f = '<';
break;
case '(': if (t1 != ')') f = '<';
break;
case')': if (t1 == '(') f = '=';
else f = '>';
break;
case'#': if (t1 == '#') f = '=';
else f = '>';
}
return f;
}
int In(char c)
{ /* 判断c是否为运算符 */
switch (c)
{
case '+':
case'-':
case'*':
case '/':
case'#':
case '(':
case')':return 1;break;
default:return 0;
}
}
void CreateExpTree(BTree& T, BTree a, BTree b, char ch)
{ //简单二叉树的创建
T = new BTNode;
T->data = ch;
T->lchild = a;
T->rchild = b;
}
void DestroyBTree(BTree bt)//销毁树
{
if (bt != NULL)
{
DestroyBTree(bt->lchild);
DestroyBTree(bt->rchild);
delete bt;
}
}
/* 请在这里填写答案 */