- 说明
- 基于二叉树实现的表达式树
- 参考文献
一、说明:
1、本文中表达式树指的是保存算术表达式的二叉树,分支结点存储操作符,而叶结点存储操作数;
2、教材中为减少空间上的浪费将叶结点和分支结点的定义分开了。本文为了避免麻烦,不分别定义叶结点和分支结点;
3、本文中实现二叉树的方式是链表实现的子结点法;
4、输入的是一个合法的表达式,输入的表达式中操作符仅包括+、-、*、/以及(),单个操作数设置为5位,最后结果不要超过int型的最大值;
5、读入表达式的一部分产生相应的二叉树后,在读入运算符时,运算符与根结点的运算符比较优先级的高低(*、/为2,+、-为1,其他为0),如果高于根结点,读入的运算符作为根结点的右子树,原来的右子树作为读入运算符的左子树;如果低于或等于,读入的运算符作为树根,原来的二叉树作为它的左子树;
6、遇到括号,先使括号内的表达式产生一颗二叉树,再把它的根结点连到前面已产生的二叉树的右子树上;
7、由二叉树的三种遍历方式可得到表达式的三种不同表示方式:前缀表达式(波兰表达式,先序遍历得)、中缀表达式(中序遍历得)和后缀表达式(逆波兰表达式,后序遍历得);
8、以先序遍历的方式求出整个表达式的值;
9、以下代码仅供参考。
二、基于二叉树实现的表达式树
1、BinNode.h
#include<iostream>
using namespace std;
#ifndef _BinNode
#define _BinNode
namespace wangzhe
{
class BinNode
{
private:
char Opx;//operator value
int Var;//operand
BinNode* lc;
BinNode* rc;
public:
BinNode()
{
Opx='\0';
Var=0;
lc=rc=NULL;
}
int getPriority()//运算符优先级'+'和'-'返回1,'*'和'/' 返回2,其他情况返回0
{
if(Opx=='+'||Opx=='-') return 1;
else if(Opx=='*'||Opx=='/') return 2;
return 0;
}
char& opx()
{
return Opx;
}
void setopx(char c)
{
Opx=c;
}
int& var()
{
return Var;
}
void setvar(int it)
{
Var=it;
}
BinNode* left() const
{
return lc;
}
void setLeft(BinNode* b)
{
lc=b;
}
BinNode* right() const
{
return rc;
}
void setRight(BinNode* b)
{
rc=b;
}
bool isLeaf()
{
return (lc==NULL)&&(rc==NULL);
}
BinNode* operator =(const BinNode& b)
{
Opx=b.Opx;
Var=b.Var;
lc=lc;
rc=b.rc;
return this;
}
};
}
#endif
2、BinTree.h
#include<iostream>
using namespace std;
#include"BinNode.h"
#ifndef _BinTree
#define _BinTree
namespace wangzhe
{
class BinTree
{
private:
BinNode* root;//树根
public:
BinTree();//构造函数
BinNode* getNode(char* str,int& pos);//获取结点
BinNode* createBinTree(char* str,int& pos);//建树
int result(BinNode*);//计算
void preorder(BinNode* b);
};
}
#endif
3、BinTree.cpp
#include<iostream>
#include<cstdlib>
using namespace std;
#include"BinTree.h"
namespace wangzhe
{
BinTree::BinTree()
{
root=NULL;
}
BinNode* BinTree::getNode(char* str,int& pos)
{
BinNode* p=new BinNode;
char ch=str[0];
if(isdigit(ch))//如果是数
{
int i=0;
char data[5];//别超过5位数呀
while(isdigit(ch=str[i])) data[i++]=ch;
p->setvar(atoi(data));
pos+=i;
}
else if(ch=='+'||ch=='-'||ch=='*'||ch=='/')
{
p->setopx(ch);
pos+=1;
}
else if(ch=='(')
{
pos+=1;
p=createBinTree(str+1,pos);
}
else if(ch==')')
{
pos+=1;
p=NULL;
}
else if(ch=='\0') p=NULL;
return p;
}
BinNode* BinTree::createBinTree(char* str,int& pos)
{
int pos1=0;
BinNode* lch=getNode(str+pos1,pos1);
BinNode* R=getNode(str+pos1,pos1);
BinNode* rch=getNode(str+pos1,pos1);
R->setLeft(lch);
R->setRight(rch);
BinNode* node;
while((node=getNode(str+pos1,pos1)))
{
if(R->getPriority()>node->getPriority())
{
node->setLeft(R);
node->setRight(getNode(str+pos1,pos1));
R=node;
}
else
{
node->setLeft(R->right());
R->setRight(node);
node->setRight(getNode(str+pos1,pos1));
}
}
pos+=pos1;
return R;
}
int BinTree::result(BinNode* b)
{
int n1,n2;
switch(b->opx())
{
case '+':
n1=result(b->left() );
n2=result(b->right());
b->setvar(n1+n2);
break;
case '-':
n1=result(b->left());
n2=result(b->right());
b->setvar(n1-n2);
break;
case '*':
n1=result(b->left());
n2=result(b->right());
b->setvar(n1*n2);
break;
case '/':
n1=result(b->left());
n2=result(b->right());
b->setvar(n1/n2);
break;
default:return b->var();
}
return b->var();
}
void BinTree::preorder(BinNode* b)
{
if(b==NULL) return;
if(b->opx() !='\0') cout<<b->opx()<<' ';
if(b->var() !=0) cout<<b->var() <<' ';
preorder(b->left() );
preorder(b->right() );
}
}
4、main.cpp
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#include"BinTree.h"
using namespace wangzhe;
int main(int argc, char** argv)
{
BinTree tree;
cout<<"请输入表达式:(数字+“+,-,*,/,(,)”:\n";
char str[101];
int pos=0;
gets(str);
BinNode* rt=tree.createBinTree(str,pos);
cout<<"该表达式的结果是:\n";
cout<<tree.result(rt);
//tree.preorder(rt);
return 0;
}
三、参考文献
[1]陈海珠,郑卉.基于二叉树的算术表达式计算与实现[J].中国科技信息,2012,13:190-193.
[2]何志宏,毛志军.表达式与二叉树的相互转换[A].计算机工程应用技术,2010,6:1201-1203