二叉树应用——计算表达式

由于时间比较匆忙,只实现了计算单个数字的,计算有十位或者更高位的还没去实现,之前用栈做的就可以,这里用二叉树做的,一开始把数据定为char类型,所以后来也就没去改它,就先实现了只有个位数的情况下的表达式的计算,更高位的表达式的计算,就是将数据的类型定位string类型,然后在数字组装和压栈的时候改些东西就好,这次由于重点是通过输入一个表达式,并建立起相对应的表达树,所以那里不想去深究。下面是代码,运算符号的优先级的判断,是用了栈的的结构特点,下一篇日记会贴出,只有栈和数组实现的表达式的计算,那个可以计算高位。

文件“tree.h”

#include<iostream>
#include<string>
#include<ctype.h>
using namespace std;

template<class T>
class My_stack;

template<class T>
class Node		//结点类
{
private:
	T data;
	Node<T> *next;
public:
	Node()
	{
		next=NULL;
	}
	Node(T d)
	{
		data=d;
		next=NULL;
	}
	friend My_stack<T>;
};

template<class T>
class My_stack
{
private:
	Node<T> *head;
public:
	My_stack()
	{
		head=new Node<T>();
	}
	
	~My_stack()
	{
		clean();
		delete head;
	}

	bool empty() const
	{
		return (head->next==0);
	}

	int size() const
	{
		int length=0;
		Node<T> *p=head->next;
		while(p)
		{
			length++;
			p=p->next;
		}
		return length;
	}

	void push(T d)	//入栈
	{
		Node<T> *p=new Node<T>(d);
		p->next=head->next;
		head->next=p;
	}

	T top()	//返回栈顶元素
	{
		if(empty())
		{
			cout<<"stack is empty."<<endl;
			exit(1);
		}
		Node<T> *p=head->next;
		T temp=p->data;
		return temp;
	}

	void pop()	//弹出栈顶元素
	{
		Node<T> *p=head->next;
		head->next=p->next;
		delete p;
	}

	void clean()	//清除整个栈
	{
		Node<T> *p=head->next;
		while(p)
		{
			head->next=p->next;
			delete p;
			head->next=p;
		}
	}
};

class BinTree;

class BinNode 
{
private:
	char data;
	BinNode *lchild;
	BinNode *rchild;
	friend BinTree;
};

class BinTree
{
private:
	BinNode *root;
	int pos;
	char str[255];
public:
	BinTree()
	{
		root=0;
		pos=0;
		str[0]='\0';
	}

	BinNode *Get_Root()
	{
		return root;
	}

	char *Get_str()
	{
		str[pos]='\0';
		return str;
	}

	void Create_Expression_Tree(BinNode *&r)	//建表达树
	{
		My_stack<char> digit;//暂存数字
		My_stack<char> opetor;//暂存操作符
		My_stack<BinNode *> node;//暂存结点
		
		char str[255];
		cout<<"输入表达式:";
		cin>>str;
		int i=0;
		char a,b;
		BinNode *p1,*p2,*p3;

		while(str[i]!='\0')
		{
			if(isdigit(str[i]))
			{
				digit.push(str[i]);
			}
			else
			{
				switch(str[i])
				{
				case '(': opetor.push(str[i]); break;
				case '*':
				case '/':
					if( !opetor.empty() && ( opetor.top()=='*' || opetor.top()=='/' ) )
					{
						p1=new BinNode;
						if(!opetor.empty())
						{
							p1->data=opetor.top();
							opetor.pop();
						}
						else
							cout<<"operator stack is empty"<<endl;
						if(!digit.empty()) //当数字栈中还有数字时
						{
							a=digit.top();
							digit.pop();
							p2=new BinNode;
							p2->data=a;
							p2->lchild=p2->rchild=0;
							if(!digit.empty())
							{
								b=digit.top();
								digit.pop();
								p3=new BinNode;
								p3->data=b;
								p3->lchild=p3->rchild=0;
								p1->lchild=p3;
								p1->rchild=p2;
							}
							else
							{
								if(!node.empty())
								{
									p3=new BinNode;
									p3=node.top();
									node.pop();
								}
								p1->lchild=p3;
								p1->rchild=p2;
							}
							node.push(p1);
						}
						else//当数字栈为空时,运算符号是作为两个式子运算结果的运算
						{
							p2=node.top();
							node.pop();
							p3=node.top();
							node.pop();
							p1->lchild=p3;
							p1->rchild=p2;
							node.push(p1);
						}
						opetor.push(str[i]);
					}
					else
						opetor.push(str[i]);
					break;
				case '+':
				case '-':
					while( (!opetor.empty()) && (opetor.top()!='(') )//加减的运算优先级最低,在他之前的所以运算符号都要出栈
					{
						p1=new BinNode;
						p1->data=opetor.top();
						opetor.pop();
						if(!digit.empty())
						{
							a=digit.top();
							digit.pop();
							p2=new BinNode;
							p2->data=a;
							p2->lchild=p2->rchild=0;
							if( !digit.empty() )
							{
								b=digit.top();
								digit.pop();
								p3=new BinNode;
								p3->data=b;
								p3->lchild=p3->rchild=0;
								p1->lchild=p3;
								p1->rchild=p2;
							}
							else
							{
								if(!node.empty())
								{
									p3=new BinNode;
									p3=node.top();
									node.pop();
								}
								p1->lchild=p3;
								p1->rchild=p2;
							}
							node.push(p1);
						}
						else
						{
							p2=node.top();
							node.pop();
							p3=node.top();
							node.pop();
							p1->lchild=p3;
							p1->rchild=p2;
							node.push(p1);
						}
					}
					opetor.push(str[i]);
					break;
				case ')':
					while( !opetor.empty() && opetor.top()!='(' )
					{
						p1=new BinNode;
						p1->data=opetor.top();
						opetor.pop();
						if(!digit.empty())
						{
							a=digit.top();
							digit.pop();
							p2=new BinNode;
							p2->data=a;
							p2->lchild=p2->rchild=0;
							if(!digit.empty())
							{
								b=digit.top();
								digit.pop();
								p3=new BinNode;
								p3->data=b;
								p3->lchild=p3->rchild=0;
								p1->lchild=p3;
								p1->rchild=p2;
							}
							else
							{
								if(!node.empty())
								{
									p3=new BinNode;
									p3=node.top();
									node.pop();
								}
								p1->lchild=p3;
								p1->rchild=p2;
							}
							node.push(p1);
						}
					}
					if(!opetor.empty())
						opetor.pop();
				}
			}
			i++;
		}
		while(!opetor.empty()) //表达式扫描完以后,将剩下的运算符号栈的元素,一一取出作为双亲结点进行继续建树
		{
			p1=new BinNode;
			p1->data=opetor.top();
			opetor.pop();
			if(!digit.empty())
			{
				a=digit.top();
				digit.pop();
				p2=new BinNode;
				p2->data=a;
				p2->lchild=p2->rchild=0;
				if(!digit.empty())
				{
					b=digit.top();
					digit.pop();
					p3=new BinNode;
					p3->data=b;
					p3->lchild=p3->rchild=0;
					p1->lchild=p3;
					p1->rchild=p2;
					node.push(p1);
				}
				else
				{
					if(!node.empty())
					{
						p3=new BinNode;
						p3=node.top();
						node.pop();
					}
					p1->lchild=p3;
					p1->rchild=p2;
					node.push(p1);
				}
			}
			else
			{			
				p2=new BinNode;
				p3=new BinNode;
				p2=node.top();
				node.pop();
				p3=node.top();
				node.pop();
				p1->lchild=p3;
				p1->rchild=p2;
				r=p1;
			}	
		}
		if(node.size()==1)//运算符号栈为空后,如果node栈只剩下一个元素,那么它就是根节点
		{
			r=node.top();
			node.pop();
		}
		root=r;
		cout<<"建树完成"<<endl;
	}

	void PostOrder_Traverse(BinNode *p)  //将中缀表达式转为后缀表达式
	{
		if(p)
		{
			PostOrder_Traverse(p->lchild);
			PostOrder_Traverse(p->rchild);
			str[pos]=p->data;
			pos++;
		}
	}
	
	void Count(char *str)
	{
		My_stack<int> s;//暂存中间结果
		cout<<"__计算表达式__"<<endl;
		int i=0,a,b;
		while(str[i]!='\0')
		{
			if(isdigit(str[i]))
			{
				int q=str[i]-'0';
				s.push(q);
			}
			else
			{
				switch(str[i])
				{
				case '+':
					if(!s.empty())
					{
						a=s.top();
						s.pop();
						b=s.top();
						s.pop();
						a=a+b;
						s.push(a);
					}
					break;
				case '-':
					if(!s.empty())
					{
						a=s.top();
						s.pop();
						b=s.top();
						s.pop();
						a=b-a;
						s.push(a);
					}
					break;
				case '*':
					if(!s.empty())
					{
						a=s.top();
						s.pop();
						b=s.top();
						s.pop();
						a=a*b;
						s.push(a);
					}
					break;
				case '/':
					if(!s.empty())
					{
						a=s.top();
						s.pop();
						b=s.top();
						s.pop();
						a=b/a;
						s.push(a);
					}
				}//end_switch
			}//end_else
			i++;
		}//end_while
		a=s.top();
		s.pop();
		cout<<"计算结果为:"<<a<<endl;
	}

};


测试函数"main.cpp"

#include"tree.h"

int main()
{
	BinNode *root;
	BinTree tree;

	root=tree.Get_Root();
	tree.Create_Expression_Tree(root);

	char *str;
	tree.PostOrder_Traverse(root);

	str=tree.Get_str();
	int i=0;
	while(str[i]!='\0')
	{
		cout<<str[i]<<' ';
		i++;
	}
	cout<<endl;
	
	tree.Count(str);

	return 0;
}


输入 6+5*9-7/(3+4)

生成的二叉树如下所示:

输出结果:

输入表达式:6+5*9-7/(3+4)
建树完成
5 9 * 6 + 3 4 + 7 / -
__计算表达式__
计算结果为:50
Press any key to continue

 

最近也领悟到,当你调试一段比较长的代码时,如果你静下心来,你会发现,你为了跟踪某一段代码,可以想出很多很奇怪又很简单的方法,当错误都清理完后,那种成就感也是不言而喻的

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值