表达式树(二叉树)的实现

表达式树(二叉树)的实现

一、 该程序的功能,实现了前缀表达式转换为中缀表达式,并进行相应的求值和赋值运算,与及构造复合表达式的功能。

二、实现原理,利用二叉树实现,也可以称为语法树,树中维护了中缀表达式。

三、 概要设计:

实现该程序所要用到的函数如下(从左到右为相关函数调用层次),除main函数外,其他函数均是两个类的成员函数,这两个类分别是:TreeNode类和BinaryTreeAndExpr类:

四、 详细设计(这里直接给出源码,由于比较容易,就不做过多说明):

1、Expression.h文件的实现

#ifndef _EXPRESSION_H_

#define _EXPRESSION_H_

//--------------------    树节点类

class TreeNode

{

public:

TreeNode(char_data,TreeNode* _left,TreeNode* _right);

~TreeNode();

charGetData();

voidSetData(char _data);

voidSetLeft(TreeNode* _left);

voidSetRight(TreeNode* _right);

TreeNode*GetLeft();

TreeNode*GetRight();

private:

charData;

TreeNode*left,*right;

};

//--------------------  二叉树几及表达式类

class BinaryTreeAndExpr

{

public:

BinaryTreeAndExpr();

~BinaryTreeAndExpr();

TreeNode*GetRoot();

voidSetRoot(TreeNode* _root);

voidReadExpr(char* E);

voidWriteExpr(char* E);

voidAssign(char v,int c);

staticint Value(char* E);

staticBinaryTreeAndExpr* CompoundExpr(char p,char* E1,char* E2);

voidRelease();

private:

voidReleaseRecursion(TreeNode* &p);

voidReadExprRecursion(TreeNode* &p,char* E);

voidWriteExprRecursion(TreeNode* p,char* E);

voidAssignRecursion(TreeNode* p,char v,int c);

intValueRecursion(TreeNode* p);

intPriority(char c1,char c2);

boolIsOperator(char c);

intEvaluation(int a,char op,int b);

TreeNode*root;

intExpr_i,Expr_len;

};

#endif

2、Expression.cpp文件的实现

#include<iostream>

#include<cmath>

#include"Expression.h"

usingnamespace std;

//----------------------树节点类成员函数

TreeNode::TreeNode(char_data,TreeNode* _left,TreeNode* _right)

{

Data=_data;

left=_left;

right=_right;

}

TreeNode::~TreeNode(){}

charTreeNode::GetData()

{

return Data;

}

voidTreeNode::SetLeft(TreeNode* _left)

{

left=_left;

}

voidTreeNode::SetRight(TreeNode* _right)

{

right=_right;

}

TreeNode*TreeNode::GetLeft()

{

return left;

}

TreeNode*TreeNode::GetRight()

{

return right;

}

voidTreeNode::SetData(char _data)

{

Data=_data;

}

//----------------------------
二叉树几及表达式类成员函数

BinaryTreeAndExpr::BinaryTreeAndExpr():root(NULL)

{

Expr_i=Expr_len=0;

}

BinaryTreeAndExpr::~BinaryTreeAndExpr(){}

voidBinaryTreeAndExpr::Release()

{

if(root!=NULL)

{

ReleaseRecursion(root);           //调用释放树的递归函数,实现树的释放

delete(root);

root=NULL;

}

}

voidBinaryTreeAndExpr::ReleaseRecursion(TreeNode* &p)

{

if(p->GetLeft()!=NULL)

{

TreeNode* p1;

p1=p->GetLeft();

ReleaseRecursion(p1);

delete(p1);

}

else if(p->GetRight()!=NULL)

{

TreeNode*p2;

p2=p->GetRight();

ReleaseRecursion(p2);

delete(p2);

}

p=NULL;

}

TreeNode*  BinaryTreeAndExpr::GetRoot()

{

return root;

}

voidBinaryTreeAndExpr::ReadExpr(char* E)

{

if(root!=NULL) {Release();root=NULL;}

Expr_i=0;

Expr_len=strlen(E);

if(Expr_len==0) return ;

ReadExprRecursion(root,E);

}

voidBinaryTreeAndExpr::ReadExprRecursion(TreeNode* &p,char* E)

{

if(Expr_i==Expr_len)return ;

p=(TreeNode*)newTreeNode(E[Expr_i++],NULL,NULL);

char temp=p->GetData();

if(!IsOperator(temp)) return ;

else

{

TreeNode* q1,* q2;

ReadExprRecursion(q1,E);

p->SetLeft(q1);

ReadExprRecursion(q2,E);

p->SetRight(q2);

}

}

voidBinaryTreeAndExpr::WriteExpr(char* E)

{

if(root==NULL) {E[0]=‘\0‘;return ;}

WriteExprRecursion(root,E);

}

voidBinaryTreeAndExpr::WriteExprRecursion(TreeNode* p,char* E)            //把树中内容转化为字符串

{

char c1,c2,c3[100],c4[100];

if(p->GetLeft()==NULL ||p->GetRight()==NULL)

{

E[0]=p->GetData();

E[1]=‘\0‘;

return ;

}

c1=p->GetLeft()->GetData();

c2=p->GetRight()->GetData();

if(!IsOperator(c1) &&!IsOperator(c2))

{

E[0]=c1;E[1]=p->GetData();E[2]=c2;E[3]=‘\0‘;

}

else if(IsOperator(c1) &&!IsOperator(c2))

{

WriteExprRecursion(p->GetLeft(),c3);

if(Priority(p->GetData(),p->GetLeft()->GetData())>0)

{

E[0]=‘(‘;

for(inti=0;i<strlen(c3);i++) E[i+1]=c3[i];

E[i+1]=‘)‘;

E[i+2]=p->GetData();

E[i+3]=p->GetRight()->GetData();

E[i+4]=‘\0‘;

}

else

{

for(inti=0;i<strlen(c3);i++) E[i]=c3[i];

E[i]=p->GetData();

E[i+1]=p->GetRight()->GetData();

E[i+2]=‘\0‘;

}

}

else if(!IsOperator(c1) &&IsOperator(c2))

{

WriteExprRecursion(p->GetRight(),c3);

if(Priority(p->GetData(),p->GetRight()->GetData())>0)     //符号优先级判断,以便于添加括号,以下相同

{

E[0]=p->GetLeft()->GetData();

E[1]=p->GetData();

E[2]=‘(‘;

for(inti=0;i<strlen(c3);i++) E[i+3]=c3[i];

E[i+3]=‘)‘;

E[i+4]=‘\0‘;

}

else

{

E[0]=p->GetLeft()->GetData();

E[1]=p->GetData();

for(inti=0;i<strlen(c3);i++) E[i+2]=c3[i];

E[i+2]=‘\0‘;

}

}

else

{

WriteExprRecursion(p->GetLeft(),c3);

WriteExprRecursion(p->GetRight(),c4);

if(Priority(p->GetData(),p->GetLeft()->GetData())>0)

{

E[0]=‘(‘;

for(inti=0;i<strlen(c3);i++) E[i+1]=c3[i];

E[i+1]=‘)‘;

E[i+2]=‘\0‘;

}

else

{

for(inti=0;i<strlen(c3);i++) E[i]=c3[i];

E[i]=‘\0‘;

}

int j=strlen(E);

E[j]=p->GetData();

if(Priority(p->GetData(),p->GetRight()->GetData())>0)

{

E[j+1]=‘(‘;

for(int i=0;i<strlen(c4);i++)E[j+2+i]=c4[i];

E[j+2+i]=‘)‘;

E[j+3+i]=‘\0‘;

}

else

{

for(inti=0;i<strlen(c4);i++) E[j+1+i]=c4[i];

E[j+1+i]=‘\0‘;

}

}

}

intBinaryTreeAndExpr::Priority(char c1,char c2)                    //优先级判断函数

{

switch(c1)

{

case ‘+‘:

case ‘-‘:

return -1;

case ‘*‘:

switch(c2)

{

case ‘+‘:

case ‘-‘:

return 1;

}

return -1;

case ‘/‘:

switch(c2)

{

case ‘+‘:

case ‘-‘:

return 1;

}

return -1;

case ‘^‘:

return 1;

}

return 0;

}

boolBinaryTreeAndExpr::IsOperator(char c)

{

return !(c>=97 && c<=122|| c>=48 && c<=57);

}

voidBinaryTreeAndExpr::Assign(char v,int c)

{

AssignRecursion(root,v,c);

}

voidBinaryTreeAndExpr::AssignRecursion(TreeNode* p,char v,int c)

{

if(p!=NULL)

{

if(p->GetData()==v)p->SetData(c+48);

AssignRecursion(p->GetLeft(),v,c);

AssignRecursion(p->GetRight(),v,c);

}

}

BinaryTreeAndExpr*BinaryTreeAndExpr::CompoundExpr(char p,char* E1,char* E2)                //构造复合表达式

{

BinaryTreeAndExpr BTAE1,BTAE2,*BTAE3;

BTAE1.ReadExpr(E1);

BTAE2.ReadExpr(E2);

TreeNode* q=(TreeNode*)newTreeNode(p,NULL,NULL);

q->SetLeft(BTAE1.GetRoot());

q->SetRight(BTAE2.GetRoot());

BTAE3=(BinaryTreeAndExpr*)newBinaryTreeAndExpr;

BTAE3->SetRoot(q);

return BTAE3;

}

voidBinaryTreeAndExpr::SetRoot(TreeNode* _root)

{

root=_root;

}

intBinaryTreeAndExpr::Value(char* E)               //表达式求值

{

BinaryTreeAndExpr btae;

btae.ReadExpr(E);

returnbtae.ValueRecursion(btae.GetRoot());

}

intBinaryTreeAndExpr::ValueRecursion(TreeNode* p)  //表达式求值

{

char c1,c2;

int temp1,temp2;

if(p->GetLeft()==NULL ||p->GetRight()==NULL)

{

c1=p->GetData();

return (c1>=97 &&c1<=122)?0:c1-48;

}

c1=p->GetLeft()->GetData();

c2=p->GetRight()->GetData();

if(!IsOperator(c1) &&!IsOperator(c2))

{

if(c1>=97 &&c1<=122) temp1=0;

else temp1=c1-48;

if(c2>=97 &&c2<=122) temp2=0;

else temp2=c2-48;

returnEvaluation(temp1,p->GetData(),temp2);

}

else if(IsOperator(c1) &&!IsOperator(c2))

{

temp1=ValueRecursion(p->GetLeft());

if(c2>=97 &&c2<=122) temp2=0;

else temp2=c2-48;

returnEvaluation(temp1,p->GetData(),temp2);

}

else if(!IsOperator(c1) &&IsOperator(c2))

{

temp2=ValueRecursion(p->GetRight());

if(c1>=97 &&c1<=122) temp1=0;

else temp1=c1-48;

returnEvaluation(temp1,p->GetData(),temp2);

}

else

{

temp1=ValueRecursion(p->GetLeft());

temp2=ValueRecursion(p->GetRight());

returnEvaluation(temp1,p->GetData(),temp2);

}

}

intBinaryTreeAndExpr::Evaluation(int a,char op,int b)

{

switch(op)

{

case ‘+‘:

return a+b;

break;

case ‘-‘:

return a-b;

break;

case ‘*‘:

return a*b;

break;

case ‘/‘:

return a/b;

break;

case ‘^‘:

return pow(a,b);

break;

}

return 0;

}

3、ExpressionMain.cpp文件的实现(测试文件)

#include<iostream>

#include"Expression.h"

usingnamespace std;

intmain()

{

BinaryTreeAndExpr btae,*btae1;

char E1[100],E2[100],P,V;

int switchs,c,switchs2;

bool run=true,run2=true;

while(run)

{

cout<<"请选择功能,功能如下:"<<endl;

cout<<"1.构造复合表达试并输出相应结果."<<endl;

cout<<"2.输入前缀表达试并构造中缀表达试."<<endl;

cout<<"3.对前缀表达试求值."<<endl;

cout<<"4.退出."<<endl;

cin>>switchs;

switch(switchs)

{

case 4:

run=false;

break;

case 1:

cout<<"请输入相关数据.前缀表达试"<<endl;

getchar();

scanf("%s %c%s",E1,&P,E2);

btae1=BinaryTreeAndExpr::CompoundExpr(P,E1,E2);

while(run2)

{

cout<<"如有变量要赋值请输入1,否则输入2"<<endl;

cin>>switchs2;

if(switchs2==1)

{

cout<<"请输入相关数据."<<endl;

getchar();

scanf("%c%d",&V,&c);

btae1->Assign(V,c);

}

elserun2=false;

}

btae1->WriteExpr(E1);

cout<<"中缀表达试:"<<E1<<endl;

btae1->Release();

delete(btae1);

run2=true;

break;

case 2:

cout<<"请输入相关数据.前缀表达试"<<endl;

cin>>E1;

btae.ReadExpr(E1);

while(run2)

{

cout<<"如有变量要赋值请输入1,否则输入2"<<endl;

cin>>switchs2;

if(switchs2==1)

{

cout<<"请输入相关数据."<<endl;

getchar();

scanf("%c%d",&V,&c);

btae.Assign(V,c);

}

elserun2=false;

}

cout<<"中缀表达试:";

btae.WriteExpr(E2);

cout<<E2<<endl;

run2=true;

break;

case 3:

cout<<"请输入相关数据.前缀表达试"<<endl;

cin>>E1;

btae.ReadExpr(E1);

btae.WriteExpr(E2);

cout<<"中缀表达试为:";

cout<<E2<<endl;

cout<<"计算结果为:";

cout<<BinaryTreeAndExpr::Value(E1)<<endl;

break;

default:

cout<<"你的输入无效!请重新输入."<<endl;

break;

}

btae.Release();

if(run) cout<<endl;

}

return 0;

}

五、 测试结果:

时间: 2024-11-09 00:05:41

表达式树(二叉树)的实现的相关文章

07_2.二叉数,二叉树的简单应用:表达式树

""" 二叉树的list实现 """ def BinTree(data, left=None, right=None): """ 二叉树 :param data: 根结点的元素 :param left: 左子树元素 :param right: 右子树元素 :return: """ return [data, left, right] def is_empty_BinTree(btree)

用C#表达式树优雅的计算24点

思路:一共4个数字,共需要3个运算符,可以构造一个二叉树,没有子节点的节点的为值,有叶子节点的为运算符 例如数字{1, 2, 3, 4},其中一种解的二叉树形式如下所示: 因此可以遍历所有二叉树可能的形式,4个数的全排列,从4种运算符中挑选3种运算符(运算符可以重复) 核心步骤1:需要遍历所有二叉树的可能,参考Eric Lippert的方法 class Node { public Node Left { get; private set; } public Node Right { get; p

中缀表达式生成二叉树

中缀表达式生成二叉树,大概应该有递规,迭代,和编译原理中的自顶向下的预测分析法等. 递规,迭代的思路每次读出一个数字,一个运算符,比较当前运算符和之前符号的优先级,进行相关的操作. 自顶向下的预测分析法,做了下,实在忘记的差不多了,先占个位.以后完成. tree.c #include "head.h" struct Node * CreateNodesetV(int number,char opr,int type) { struct nodeData db; db.numberVal

触手不及(巴科斯范式求表达式树)

本题为学军神犇 cxt 出的神题. 题意 为了避免流露出自己的感情伤害别人, 小 M.M.T. 决定通过一个表达式来传递心意. 给出一个等式. 等式左边是一个 \(int\) 范围内的数, 等式右边是一个合法的 c++ 表达式. 例如:\(233 = 66 ? 4 ? 31\) 保证等式右边只包含数字 \(x (x ∈ [0, p),p\) 是给定的质数\()\), 加号, 减号, 乘号, 除号, 左右括号. 保证等式中没有任何空格,tab 等不可见字符. 而且保证合法. 但是遗憾的是, 因为一

C# 表达式树 创建、生成、使用、lambda转成表达式树~表达式树的知识详解

笔者最近学了表达式树这一部分内容,为了加深理解,写文章巩固知识,如有错误,请评论指出~ 表达式树的概念 表达式树的创建有 Lambda法 和 组装法. 学习表达式树需要 委托.Lambda.Func<> 基础. 表达式树 形状可以参考 二叉树. 可以把表达式树理解成 数学表达式. 数学表达式的所有常量.符号为表达式树的底节点.每一次计算生成的结果是一个结点,或者说他们的共同结点就是他们应该进行的运算. 生成表达式树 表达式树的创建有 Lambda表达式法 和 组装法 为了方便,这里指定生成的表

Java实现后缀表达式建立表达式树

概述 表达式树的特点:叶节点是操作数,其他节点为操作符.由于一般的操作符都是二元的,所以表达式树一般都是二叉树. 根据后缀表达式"ab+cde+**"建立一颗树 文字描述: 如同后缀表达式求值一样,逐个读取后缀表达式的每一个符号,如果遇到操作数,建立一个节点把操作数的值加入这个节点,并把节点入栈:如果遇到操作符,弹出栈里的两个节点,并赋值为自己的左子节点.右子节点,最后把这个节点树入栈. 画图描述: 1.读入操作数a,创建节点,压入栈:读入操作数b,创建节点,压入栈 2.遇到操作符&q

C#中的表达式树的浅解

表达式树可以说是Linq的核心之一,为什么是Linq的核心之一呢?因为表达式树使得c#不再是仅仅能编译成IL,我们可以通过c#生成一个表达式树,将结果作为一个中间格式,在将其转换成目标平台上的本机语言.比如SQL.我们常用的Linq to sql就是这样生成SQL的. 表达式树是.NET 3.5之后引入的,它是一个强大灵活的工具(比如用在LINQ中构造动态查询). 先来看看Expression类的API接口: namespace System.Linq.Expressions { // // 摘

关于Expression表达式树的拼接

最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. 我们用的MVC+EF5.0的框架,在BLL层进行查询的 时候需要构建lambda表达式来作为查询条件,但是,我们怎么来构建lambda来确定查询的条件呢?我们知道Express<Func<T,bool>>这样的一个参数可以是lambda表达式,但是这里的按条件拼接式不能使用委托链的形

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习表达式在程序设计中的优点:比如构造动态查询.动态构造表达式树完成未知对象属性访问,比反射的性能高出很多.我们可以说表达式树才是Lambda的精髓,是我们必须要熟练掌握并灵活运用的. 1.关于表达式树(Expression Tree) 表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如