树结构的应用:表达式类型的实现

#include <iostream>
#include<cmath>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
using namespace std;
struct BiTNode					//结点的数据
{
	bool tag;			//true为数字,false为字符		
	int num;
	char c;
	BiTNode *lchild,*rchild;
};

struct SqStack										//顺序栈
{
	BiTNode *base;									// 在栈构造之前和销毁之后,base的值为NULL 
	int stacksize;									//当前已分配的存储空间,以元素为单位 
	int top1;
	BiTNode **address;                        //存储当前最顶端数据的地址,在构造二叉树的时候会有地址的存储返回子树的根节点

	int InitStack(int n)					// 构造一个空栈S
	{  
		base=new BiTNode[n];
		stacksize=n;
		address=new BiTNode *[n];
		top1=0;             //从0开始存数据
		return OK;
	}

	int StackEmpty()						// 若栈S为空栈,则返回TRUE,否则返回FALSE 
	{ 
		if(top1==0)   
			return TRUE;
		else  
			return FALSE;
	}

	int Push(BiTNode *e)						// 插入元素e为新的栈顶元素
	{  
		*(base+top1)=*e;
		address[top1]=e;
		top1++;
		return OK;
	}

	BiTNode* Pop()						// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR/
	{ 
		if(top1<0) return ERROR;
		top1--;
		return address[top1];
	}
};

BiTNode *tree;									//定义树
SqStack Stack;								 //定义栈,在建立二叉树的的时候作为中间变量,存储部分子树的根节点

void judge_value(BiTNode *t,char exprstring)		//判断字符string[i],加引用是为了在调用函数的时候改变原来t的值
{

	if(exprstring>='0'&&exprstring<='9')		//为常量
	{
		t->tag=true;
		t->c='#';                              //有数字的时候,字符赋值为#
		t->num=exprstring-48;
	}
	else									//为变量
	{
		t->tag=false;
		t->num=-1;                          //当是字符形式,则数字赋值为-1
		t->c=exprstring;
	}
}

int ReadExpr(char *exprstring,int len)				//以字符序列的形式输入语法正确的前缀表示式并构造表达式
{
	int i;								//len为表达式的长度 
	BiTNode *p,*q;
	tree=new BiTNode;					//申请二叉树的根结点的空间 
	tree->lchild=NULL;
	tree->rchild=NULL;
	if(len==1)											//表达式长度为1时,二叉树只有根结点 	
		judge_value(tree,exprstring[0]);			//将exprstring[0]存入二叉树的结点中 
	else 
	{
		judge_value(tree,exprstring[0]);		//同理
		Stack.InitStack(len);					//初始化栈 
		q=tree;
		Stack.Push(tree);									//入栈 
		Stack.Push(tree);										//入栈,根结点入栈两次是为判断先序输入的表达式是不是正确的表达式 
		for(i=1;i<len&&!Stack.StackEmpty();i++)
		{
			p=new BiTNode;
			judge_value(p,exprstring[i]);						//将exprstring[i]存入二叉树的结点中 
			p->lchild=NULL;
			p->rchild=NULL;				
			if(exprstring[i]=='+'||exprstring[i]=='-'||exprstring[i]=='*'||exprstring[i]=='/'||exprstring[i]=='^')
			{											//为运算符,运算符入栈,左孩子不空,向左孩子走,否则,如果右孩子不空,向右孩子走 
				if(!q->lchild)	
				{
					q->lchild=p;
					Stack.Push(p);
					q=p;
				}
				else	
				{
					q->rchild=p;
					Stack.Push(p);
					q=p;
				}
			}
			else						//不是运算符,运算符出栈 
			{
				if(!q->lchild)	
				{
					q->lchild=p;
					q=Stack.Pop();
				}
				else	
				{
					q->rchild=p;
					q=Stack.Pop();
				}
			}
		}
		if(Stack.StackEmpty()&&i>=len)	return OK;                      //只有栈为空的时候才把二叉树构造成功
		else	
		{
			cout<<"                      输入的字符串无法构造成表达式!"<<endl;
			return ERROR;
		}
	}
	return OK;
}
int Compare(char c1,char c2)				//比较两个运算符的优先级,c1比c2优先,返回OK,否则返回ERROR 
{		
	if((c1=='^'||c1=='*'||c1=='-'||c1=='+'||c1=='/')&&(c2=='^'||c2=='*'||c2=='-'||c2=='+'||c2=='/'))		//c1和c2为运算符 
	{
		if(c1=='^')							//c1为指数运算符,则当c2不为'^'时,c1比c2优先 
		{
			if(c2!='^') return OK;
			else return ERROR;
		}
		else if(c1=='*'||c1=='/')					//c1为乘法或除法运算符,则当c2为'+'或'-',c1比c2优先 
		{
			if(c2=='^'||c2=='*'||c2=='/') return ERROR;
			else return OK;
		}
		else return ERROR;					//其余,c1不比c2优先 
	}
	else return ERROR;				//c1和c2不是运算符 
}
	

void WriteExpr(BiTNode *Tree)						//用带括弧的中缀表示式输出表达式
{
	if(Tree)										//树不为空 
	{												//先递归左子树 
		if(Tree->lchild&&!Tree->lchild->tag)		//二叉树的左孩子不为空,且左孩子为字符 
		{
			if(Compare(Tree->c,Tree->lchild->c))    //Tree->c的优先级大于Tree->lchild->c必须带有并输出() 
			{
				cout<<"(";
				WriteExpr(Tree->lchild);
				cout<<")";
			}
			else									//否则,不带括弧输出左子树 	
				WriteExpr(Tree->lchild);			
		}
		else 										//否则,输出左子树 
			WriteExpr(Tree->lchild);				
			
		if(Tree->tag)								//访问输出根结点的值 
		{
			cout<<Tree->num;
		}
		else
			cout<<Tree->c;
			
		if(Tree->rchild&&!Tree->rchild->tag)				//后递归右子树,树的右孩子不为空,且右孩子为字符 
		{
			if(Compare(Tree->c,Tree->rchild->c))			//Tree->c比Tree->rchild->c优先 
			{
				cout<<"(";
				WriteExpr(Tree->rchild);
				cout<<")";
			
			}													//带括弧输出右子树 
			else 
				WriteExpr(Tree->rchild);							//否则,不带括弧输出右子树 
		}
		else 
			WriteExpr(Tree->rchild);//否则,输出右子树 
	}
}
//赋值语句

void Assign(BiTNode *Tree,char V,int c,int *flag)
{
	if(Tree)
	{
		if(Tree->tag==false&&Tree->c==V)		//如果找到要赋值的变量,赋值 
		{
			Tree->tag=true;
			Tree->num=c;
			*flag=1;
		}
		Assign(Tree->lchild,V,c,flag);//递归左子树 
		Assign(Tree->rchild,V,c,flag);//递归左子树 
	}
}

int Check(BiTNode *Tree)                   //检查二叉树中是否还存在没有赋值的变量,以便求算数表达式的值 
{
	if(Tree&&Tree->tag==false)            //二叉树不为空,并且根节点为字符
	{		
		if(Tree->c!='*'&&Tree->c!='^'&&Tree->c!='-'&&Tree->c!='+'&&Tree->c!='/')return ERROR;        //是字符但不是运算符
		if(Check(Tree->lchild))               //递归左子树 
			Check(Tree->rchild);              //递归右子树 	
	}
}

int Calculate(int n1,char opr,int n2)             //运算符计算,返回计算结果值
{
	int result;
	switch(opr)                                   //匹配多种情况
	{
		case '+':
			result=n1+n2;
			return result;
			break;
		case '-':
			result=n1-n2;
			return result;
			break;
		case '*': 
			result=n1*n2;
			return result;
			break;
		case '/':
			result=n1/n2;
			return result;
			break;
		case '^':
			result=pow(n1,n2);
			return result;
			break;
		default:break;
	}	
}
int Value(BiTNode *Tree)                   //计算返回整个表达式的值
{
	if(Tree)							//二叉树不为空 
	{
		if(!Tree->lchild&&!Tree->rchild&&Tree->tag) return (Tree->num);    //结点的左孩子和右孩子为空,为叶子结点,返回结点的值 
		return Calculate(Value(Tree->lchild),Tree->c,Value(Tree->rchild));   //运算求值,后根遍历的次序对表达式求值 
	}
}
void main()
{
	char Expr_string[1000];                           //存放刚开始输入的字符串
	int n,ttt=1;
	while(ttt)
	{
con:	cout<<"                 是否还要计算,是请按1,否请按0:";
		cin>>ttt;
		system("cls");
		flushall();                              //输入之前清理缓冲区
		cout<<"                       请输入前缀表达式:";
		cin.getline(Expr_string,1000);                //从键盘输入一串字符串作为表达式
		n=strlen(Expr_string);
		if(n==1)                                 //输入的表达式字符串长度为1
		{
			if(Expr_string[0]=='+'||Expr_string[0]=='-'||Expr_string[0]=='*'||Expr_string[0]=='/'||Expr_string[0]=='^')//输入的表达式只有一个运算符 
			{ 
				cout<<"                       表达式只有一个运算符,错误!"<<endl;
				goto con;
			} 
			else 
				if((Expr_string[0]>='0'&&Expr_string[0]<'9')||(Expr_string[0]>='a'&&Expr_string[0]<='z')||(Expr_string[0]>='A'&&Expr_string[0]<='Z'))
				{ 
					cout<<"                       表达式只有一个字符"<<endl;
					goto con;
				}
				else 
				{
					cout<<"     输入的字符不是运算符也不是变量或常量,错误!"<<endl;
					goto con;
				}
		}
		if(ReadExpr(Expr_string,n))
		{
				cout<<"                       二叉树构造成功!"<<endl;
				cout<<"                       中缀表达式为:";
				WriteExpr(tree);
				cout<<endl;
			int s=0,Assign_flag=0,t=Check(tree);              //s记录有几个变量
			while(!t)                  //检验表达式中是否有变量,如果有的话就重新赋予整数值,跳出循环式则整个表达式完整
			{
				if(t)cout<<"                       表达式不存在未赋值的变量!"<<endl;
				else
				{
					int c;char V;
					cout<<"                       表达式中存在变量未赋值!"<<endl;
					cout<<"                       请输入要赋值的值:";	cin>>V;
					cout<<"                       请输入要将赋值为:";	cin>>c;
					Assign(tree,V,c,&Assign_flag);                 //把所有的要赋予的值全在Assign赋值完成
					if(Assign_flag)	
					{
						cout<<"                       赋值成功!"<<endl;
					}
					else
					{
						cout<<"表达式里没有"<<V<<",请重新输入!"<<endl;
					}
				}
				t=Check(tree);
			}
			cout<<"                       整个表达式赋值成功!"<<endl;
			cout<<"                       表达式为:";
			WriteExpr(tree);
			cout<<endl;
			int result=Value(tree);
			cout<<"                       算数表达式的值为: ";
			WriteExpr(tree);
			cout<<"="<<result<<endl;
		}
		else
			goto con;
	}
}


测试数据:

0
a
-91
+a*bc
+*5^x2*8x
+++*3^x3*2^x2x6
-^+5a32
--+++*3^x3*2^x2x6

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值