运用表达式树求解表达式的值--洛谷AC

题目背景

表达式的计算曾用算符优先法,本题用表达式树来计算表达式的值。

题目描述

表达式树是一种特殊类型的树,其叶结点是操作数(operand),而其它结点为操作符(operator):
(1)由于操作符一般都是双目的,通常情况下该树是一棵二叉树;
(2)对于单目操作符(如++),其只有一个子结点。
如表达式:a+b*(c-d)-e/f的后缀表示式为abcd-+ef/-
对应的表达式树为:(见PPT)
题目要求从标准输入中读入一个整数算术运算表达式,计算表达式结果,并输出。
说明:
1、表达式运算符只有+、-、、/,表达式末尾的=字符表示表达式输入结束,表达式中可以出现空格;
2、表达式中会出现圆括号,括号可能嵌套,不会出现错误的表达式;
3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。
4、要求采用表达式树来实现表达式计算。

输入格式

从键盘输入一个以=结尾的整数算术运算表达式。操作符和操作数之间可以有空格分隔。

输出格式

首先在屏幕上输出表达式树根、左子节点及右子节点上的运算符或操作数,中间由一个空格分隔,最后有一个回车(如果无某节点,则该项不输出)。然后输出表达式计算结果。

输入输出样例

在这里插入图片描述

说明/提示

按照运算符及括号优先级依次计算表达式的值。在生成的表达树中,*是根节点的运算符,/ 是根节点的左子节点上运算符,/是根节点的右子节点上运算符。

#include
#include<stdio.h>
#include <string.h>
#include
using namespace std;
/---------------------------二叉树的链式存储-----------------------/
typedef struct BiTNode
{
char data; //结点数据域(符号)
string combine_data; //结点数据域(数值,可大于9)
BiTNode *lchild, rchild; //左右孩子指针
}BiTree;
/
------------------------------链式堆栈---------------------------
/
typedef struct StackNode
{
BiTree data_tree; //存储的是二叉树
char data_op; //存储的是符号
StackNode *next;
}*LinkStack;
//栈的初始化
int InitStack(LinkStack &S)
{
S = NULL;
return 1;
}
//二叉树入栈
int Push_tree(LinkStack &S, BiTree e)
{
LinkStack p = new StackNode;
p->data_tree = e;
p->next = S;
S = p;
return 1;
}
//字符(运算符号)入栈
int Push_op(LinkStack &S, char e)
{
LinkStack p = new StackNode;
p->data_op = e;
p->next = S;
S = p;
return 1;
}
//二叉树出栈
int Pop_tree(LinkStack &S, BiTree &T1)
{
if (S == NULL) return 0;
LinkStack p = S;
T1 = p->data_tree;
S = S->next;
delete p;
return 1;
}
//字符(运算符号)出栈
int Pop_op(LinkStack &S, char &ch)
{
if (S == NULL) return 0;
LinkStack p = S;
ch = p->data_op;
S = S->next;
delete p;
return 1;
}

//取栈顶元素
char GetTop_op(LinkStack S)
{
if (S != NULL) return S->data_op;
else return ’ ';
}
BiTree GetTop_tree(LinkStack S)
{
if (S != NULL) return S->data_tree;
else return NULL;
}
/------------------------------表达式树的创建算法------------------------------/
//创建以T为根结点的二叉树(存储符号)
void CreateExpTree(BiTree &T, BiTree a, BiTree b, char theta)//a是左孩子,b是右孩子,theta是数据域
{
BiTree L = new BiTNode;
L->data = theta;
L->lchild = a;
L->rchild = b;
T = L;
}
//创建以T为根结点的二叉树(存储数值,可大于9)
//a是左孩子,b是右孩子,theta是数据域
void CreateExpTree_str(BiTree &T, BiTree a, BiTree b, string theta)
{
BiTree L = new BiTNode;
L->combine_data = theta;
L->lchild = a;
L->rchild = b;
T = L;
}
//比较运算符的优先级
//top是栈顶元素,ch是需要比较的元素
char Precede(char top, char ch)
{
if (ch == ‘)’&&top == ‘(’) return ‘=’;
else if (ch == ‘)’) return ‘>’;
if (top == ’ ’ || top == ‘(’ || ch == ‘(’) return ‘<’;
if (ch == ‘=’) return ‘>’;
if (top == ‘+’ || top == ‘-’) {
if (ch == ‘+’ || ch == ‘-’) return ‘>’;
else if (ch == ‘/’ || ch == ‘’) return ‘<’;
}
else if (top == '
’ || top == ‘/’) return ‘>’;
}
//创建表达式树
//expt栈(根结点),optr栈(运算符)
void InitExpTree(char ep[], LinkStack &expt, LinkStack &optr)
{
int n = strlen(ep);
int i = 0;
BiTree T = NULL; //树根
BiTree T1 = NULL; //左子树
BiTree T2 = NULL; //右子树
char ch = ’ '; //弹出的符号
string combine_str = “”; //存储数值,可大于9
while (i != n)
{
if (ep[i] >= ‘0’ && ep[i] <= ‘9’) { //数值(二叉树),进入expt栈中
combine_str += ep[i];
if (ep[i + 1] >= ‘0’ && ep[i + 1] <= ‘9’) { //下一位仍是数字,需连接
i++;
continue;
}
CreateExpTree_str(T, NULL, NULL, combine_str);
combine_str = “”; //建完数值的二叉树后string要置空
Push_tree(expt, T);
i++;
}
else {
switch (Precede(GetTop_op(optr),ep[i])) //比较优先级
{
case ‘<’:
Push_op(optr, ep[i]);
i++;
break;
case ‘>’:
Pop_op(optr, ch); //弹出上一个字符
Pop_tree(expt, T1); //弹出上两个数值(二叉树)
Pop_tree(expt, T2);
CreateExpTree(T, T2, T1, ch); //以data_tree为根,连接T1和T2两颗子树
Push_tree(expt, T); //最后把T放进expt栈中
break;
case ‘=’:
Pop_op(optr, ch);
i++;
break;
default:
break;
}
}
}
}
//表达式树 打印前三个op or num
void showOp(BiTree T)
{
if (T)
{
cout << T->data;
if (T->lchild != NULL) cout << " " << T->lchild->data;
if (T->rchild != NULL) cout << " " << T->rchild->data;
cout << endl;
}

/if(T){
cout << T->data << " ";
if (T->lchild->lchild == NULL)
cout << T->lchild->combine_data << " ";
else
cout << T->lchild->data << " ";
if (T->rchild->lchild == NULL)
cout << T->rchild->combine_data << endl;
else
cout << T->rchild->data << endl;
}
/

}
/-----------------------------表达式树的求值-------------------------------/
//直接初始化一个数组好使,用getchar现输入有一点问题
double GetValue(char data, double lvalue, double rvalue)
{
switch (data)
{
case ‘+’:
return lvalue + rvalue;
break;
case ‘-’:
return lvalue - rvalue;
break;
case ‘*’:
return lvalue * rvalue;
break;
case ‘/’:
return lvalue / rvalue;
break;
default:
break;
}
}
//把string字符转换成数值
double change(string str)
{
int n = str.length(), m = str.length();
double sum = 0;
for (int i = 0; i < n; i++)
{
sum += (str[i] - ‘0’) * pow(10, m - 1);
m–;
}
return sum;
}
//遍历表达式树求表达式的值
int EvaluateExpTree(BiTree T)
{
int lvalue =0, rvalue = 0; //存放叶子结点的数据域初始为0
if (T->lchild == NULL&&T->rchild == NULL)
return change(T->combine_data); //return T->data - ‘0’;
else {
lvalue = EvaluateExpTree(T->lchild); //相当于后序遍历二叉树
rvalue = EvaluateExpTree(T->rchild);
return GetValue(T->data, lvalue, rvalue);
}
}
int main()
{
LinkStack expt;
InitStack(expt); //初始化expt栈(根结点)
LinkStack optr;
InitStack(optr); //初始化optr栈(运算符)

char ep[100];
char temp;
int i=0;
for(i=0;temp!=’=’;i++){
cin>>temp;
ep[i]=temp;
}
ep[i]=’\0’;

扫描二维码关注公众号,回复: 13255648 查看本文章

/char ep[100];
char temp;
int i=0;
while((temp=getchar())!=’=’) ep[i++]=temp;
ep[i]=’\0’;
/
//char ep[] = “24/(1+2+36/6/2-2)(12/2/2)="; //"24/(1+2+36/6/2-2)(12/2/2)=”

InitExpTree(ep, expt, optr); //构建表达式树
BiTree T = NULL;
Pop_tree(expt, T); //获取最后建好的二叉树

showOp(T);
cout << EvaluateExpTree(T) << endl; //表达式树求值结果

return 0;
}```cpp


猜你喜欢

转载自blog.csdn.net/weixin_45800653/article/details/107954130