通过前缀表达式构建二叉树,遍历二叉树输出中缀表达式和计算表达式的值

问题描述

add(加),sub(减),mult(乘),div(除以),neg(取反),doubleMe(平方)。用二元树来表示(上述)函数式表达式,通过对二元树进行递归处理,对表达式求值,并得到带必要括号的中缀表达式。

【样例输入】

add sub neg 4 12  mult doubleMe 2 5

【样例输出】

(-4)-12+(2)^2*5 = 4

题解

分为几个模块:1.构建二叉树 2.遍历二叉树输出中缀表达式 3.遍历二叉树递归求值

构建二叉树

二叉树的基本结构

typedef struct bitnode
{
	double data;//存储运算符的ascll码和运算数
	bitnode *lchild;
	bitnode *rchild;
	
	int n;//标记,0为叶子,1为根。因为存储数据时存储的ascll码会产生冲突。
	bitnode(int e,int m=0,bitnode *lch=0,bitnode *rch=0):data(e),n(m),lchild(lch),rchild(rch){}//初始化二叉树
}bitnode,*bitree;

定义二叉树的结构体和自定义数据类型(bitnode和*bitree)

当n=0时表示存储的运算数;当n=1时表示存储运算符,用加减乘除的ascll码表示加减乘除,用-1表示取反,用-2表示平方。

递归构建二叉树

用stringstream对象取子串,构建二叉树,首先需要一个判断子串是否为运算数的函数

bool trnum(string s)

bool trnum(string s)
{
	int i;
	if(s[0]=='+'||s[0]=='-')//可以判断运算数的正负
	{
		for(i=1;i<s.size()&&isdigit(s[i]);i++);
		return i>=s.size();
	}
	for(i=0;i<s.size()&&isdigit(s[i]);i++);
	return i>=s.size();
}

然后就用递归的方法构建二叉树

bitree create(stringstream &x)
{
	string w;
	x>>w;
	if(trnum(w))//操作数,叶子结点 
		return new bitnode(atoi(w.c_str())); 
	else //操作符,根结点 
	{
		if(w=="add")
		{
			bitree t=new bitnode('+',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="sub")
		{
			bitree t=new bitnode('-',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="mult")
		{
			bitree t=new bitnode('*',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="div")
		{
			bitree t=new bitnode('/',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="neg") 
		{
			bitree t=new bitnode(-1,1); 
			t->lchild=create(x);
			t->rchild=NULL;
			return t;
		}
		else if(w=="doubleMe")
		{
			bitree t=new bitnode(-2,1); 
			t->lchild=create(x);
			t->rchild=NULL;
			return t;
		}
	}
}

遍历二叉树输出中缀表达式

输出过程中要注意括号问题:

bool l(bitree t)//判断左孩子的括号问题
{
	bitree t1=t->lchild;
	if(t->data=='*'||t->data=='/')
	{
		if(t1->data=='+'||t1->data=='-')return 1;
		else return 0;
	}
	else return 0;
}
bool r(bitree t)//判断右孩子的括号问题
{
	bitree t1=t->rchild;
	if(t->data=='+'||t->data=='-')
	{
		if(t1->data=='+'||t1->data=='-')return 1;
		else return 0;
	}
	else if(t->data=='*'||t->data=='/')return 1;
	else return 0;
}

如果是左孩子优先级 <根运算符优先级,则遍历左子树前后,加括号

如果是右孩子优先级 ≤ 根运算符优先级则遍历右子树前后,加括号

用递归的方法输出中缀表达式

void read(bitree t)
{
	if(t!=0)//不是空树 
	{
		bitree t1=t->lchild;
		if(t1!=0)//左孩子非空 
		{
			if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)//左孩子是运算符(加减乘除) 
			{
				if(l(t))//加括号 
				{
					cout<<"(";read(t1);cout<<")"; 
				}
				else read(t1);
			}
			else if(t->data==-2)//左孩子是平方 
			{
				cout<<"dohbleMe(";
				read(t->lchild);
				cout<<")";
				return;
			}
			else if(t->data==-1)//左孩子是取反 
			{
				cout<<"("<<"-";
				read(t->lchild);
				cout<<")";
				return;
			}	
			else read(t1);
		}
		if((t->data=='+'||t->data=='-'||t->data=='*'||t->data=='/')&&t->n==1)cout<<(char)t->data;//如果数据是根结点(操作符) 
		else cout<<t->data;//如果数据是叶子结点(操作数) 
		t1=t->rchild;
		if(t1!=0)//右孩子非空 
		{
			if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)
			{
				if(r(t)){
					cout<<"(";read(t1);cout<<")";
				}
				else read(t1);
			}
			else if(t->data==-2)//左孩子是平方 
			{
				cout<<"dohbleMe(";
				read(t->lchild);
				cout<<")";
				return;
			}
			else if(t->data==-1)//左孩子是取反 
			{
				cout<<"("<<"-";
				read(t->lchild);
				cout<<")";
				return;
			}
			else read(t1);
		}
	}
}

遍历二叉树递归求值

double f(bitree t)
{
	if(t!=0)
	{
		if(t->data=='+'&&t->n==1)return f(t->lchild)+f(t->rchild);
		else if(t->data=='-'&&t->n==1)return f(t->lchild)-f(t->rchild);
		else if(t->data=='*'&&t->n==1)return f(t->lchild)*f(t->rchild);
		else if(t->data=='/'&&t->n==1)return f(t->lchild)/f(t->rchild);
		else if(t->data==-1&&t->n==1)return -f(t->lchild);
		else if(t->data==-2&&t->n==1)return pow(f(t->lchild),2);
		else return t->data;
	}
}

源码

#include<iostream>
#include<iostream>
#include<sstream>
#include<fstream>
#include<stdlib.h>
#include<cmath>
using namespace std;
typedef struct bitnode
{
	double data;
	bitnode *lchild;
	bitnode *rchild;
	
	int n;//标记,0为叶子,1为根 
	bitnode(int e,int m=0,bitnode *lch=0,bitnode *rch=0):data(e),n(m),lchild(lch),rchild(rch){}
}bitnode,*bitree;
bool trnum(string s)
{
	int i;
	if(s[0]=='+'||s[0]=='-')
	{
		for(i=1;i<s.size()&&isdigit(s[i]);i++);
		return i>=s.size();
	}
	for(i=0;i<s.size()&&isdigit(s[i]);i++);
	return i>=s.size();
}
bitree create(stringstream &x)
{
	string w;
	x>>w;
	if(trnum(w))//操作数,叶子结点 
		return new bitnode(atoi(w.c_str())); 
	else //操作符,根结点 
	{
		if(w=="add")
		{
			bitree t=new bitnode('+',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="sub")
		{
			bitree t=new bitnode('-',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="mult")
		{
			bitree t=new bitnode('*',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="div")
		{
			bitree t=new bitnode('/',1);
			t->lchild=create(x);
			t->rchild=create(x);
			return t;
		}
		else if(w=="neg") 
		{
			bitree t=new bitnode(-1,1); 
			t->lchild=create(x);
			t->rchild=NULL;
			return t;
		}
		else if(w=="doubleMe")
		{
			bitree t=new bitnode(-2,1); 
			t->lchild=create(x);
			t->rchild=NULL;
			return t;
		}
	}
}
bool l(bitree t)
{
	bitree t1=t->lchild;
	if(t->data=='*'||t->data=='/')
	{
		if(t1->data=='+'||t1->data=='-')return 1;
		else return 0;
	}
	else return 0;
}
bool r(bitree t)
{
	bitree t1=t->rchild;
	if(t->data=='+'||t->data=='-')
	{
		if(t1->data=='+'||t1->data=='-')return 1;
		else return 0;
	}
	else if(t->data=='*'||t->data=='/')return 1;
	else return 0;
}
void read(bitree t)
{
	if(t!=0)//不是空树 
	{
		bitree t1=t->lchild;
		if(t1!=0)//左孩子非空 
		{
			if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)//左孩子是运算符(加减乘除) 
			{
				if(l(t))//加括号 
				{
					cout<<"(";read(t1);cout<<")"; 
				}
				else read(t1);
			}
			else if(t->data==-2)//左孩子是平方 
			{
				cout<<"dohbleMe(";
				read(t->lchild);
				cout<<")";
				return;
			}
			else if(t->data==-1)//左孩子是取反 
			{
				cout<<"("<<"-";
				read(t->lchild);
				cout<<")";
				return;
			}	
			else read(t1);
		}
		if((t->data=='+'||t->data=='-'||t->data=='*'||t->data=='/')&&t->n==1)cout<<(char)t->data;//如果数据是根结点(操作符) 
		else cout<<t->data;//如果数据是叶子结点(操作数) 
		t1=t->rchild;
		if(t1!=0)//右孩子非空 
		{
			if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)
			{
				if(r(t)){
					cout<<"(";read(t1);cout<<")";
				}
				else read(t1);
			}
			else if(t->data==-2)//左孩子是平方 
			{
				cout<<"dohbleMe(";
				read(t->lchild);
				cout<<")";
				return;
			}
			else if(t->data==-1)//左孩子是取反 
			{
				cout<<"("<<"-";
				read(t->lchild);
				cout<<")";
				return;
			}
			else read(t1);
		}
	}
}
double f(bitree t)
{
	if(t!=0)
	{
		if(t->data=='+'&&t->n==1)return f(t->lchild)+f(t->rchild);
		else if(t->data=='-'&&t->n==1)return f(t->lchild)-f(t->rchild);
		else if(t->data=='*'&&t->n==1)return f(t->lchild)*f(t->rchild);
		else if(t->data=='/'&&t->n==1)return f(t->lchild)/f(t->rchild);
		else if(t->data==-1&&t->n==1)return -f(t->lchild);
		else if(t->data==-2&&t->n==1)return pow(f(t->lchild),2);
		else return t->data;
	}
}
int main()
{
	char a[100];
	cin.getline(a,100);
	stringstream s(a);
	bitree t=create(s);
	read(t);
	cout<<" = "<<f(t);
}

输出结果

 

欢迎指正!! 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓零清

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值