表达式树的实现与计算

  • 说明
  • 基于二叉树实现的表达式树
  • 参考文献

一、说明:

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

猜你喜欢

转载自blog.csdn.net/qq_40889820/article/details/83933578