表达式二叉树

原创 2012年03月23日 10:19:47

总结了一下常见的表达式求值问题,写了一个模板,输入为中缀式时,用中缀式建立表达式二叉树,可以打印前缀式和后缀式,可以用前缀式计算,也可以用后缀式计算。


代码如下:

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<vector>
#include<climits>
#include<ctime>
#include<stack>
#include<algorithm>
using namespace std;

#define MAX 1005
#define CLR(arr, what) memset(arr, what, sizeof(arr))

struct Node
{
	char ope[10];
	Node *lchild, *rchild;
	Node()
	{
		CLR(ope, '\0');
		lchild = rchild = NULL;
	}
};

class Exp
{
private:
	Node *root;
	int prelen, postlen; //前缀式长度、后缀式长度
	int pos; //前缀式计算指针
	char str[MAX], pre[MAX], post[MAX]; //中缀式、前缀式、后缀式
	stack<double> num; //后缀式计算->数字栈
	double answer;

public:
	Exp(char[]); //构造函数
	Node* Build_Exp(int start, int end); //建表达式树

	void Pre_Order(Node*); //前缀式遍历
	void Post_Order(Node*); //后缀式遍历

	void PreOut(){cout<<pre<<"="<<endl;} //输出前缀式
	void PostOut(){cout<<post<<"="<<endl;} //输出后缀式

	double Pre_Calucate(); //前缀式计算
	double Post_Calucate(); //后缀式计算

	double result(); //输出结果

	void clear(Node*);
	~Exp(){	clear(root);}; //销毁二叉树
};

Exp::Exp(char s[])
{
	root = new Node;
	pos = -1;
	prelen = 0, postlen = 0;
	CLR(str, '\0'); CLR(pre, '\0'), CLR(post, '\0');
	while(!num.empty())
		num.pop();
	strcpy(str, s);
	root = Build_Exp(0, strlen(str) - 2); //中缀式长度可按题目改变~
}

Node* Exp::Build_Exp(int src, int des)
{
	if(src > des)
		return 0;
	if(str[src] >= '0' && str[src] <= '9' || str[src] == '.')
	{
		double temp;
		int length;
		sscanf(&str[src], "%lf%n", &temp, &length);
		if(src + length -1 == des)
		{
			Node* cur = new Node;
			sprintf(cur->ope, "%lf", temp);
			cur->ope[length] = '\0';
			cur->lchild = NULL, cur->rchild = NULL;
			return cur;
		}
	}
	int optr1 = -1, optr2 = -1, pos = 0; // +- || ×/
	for(int i = src; i <= des; ++i) //寻找树根
	{
		switch(str[i])
		{
		case '(': pos++; break;
		case ')': pos--; break;
		case '+': 
		case '-': if(pos == 0) optr1 = i; break;
		case '*':
		case '/': if(pos == 0) optr2 = i; break;
		}
	}
	if(optr1 < 0)
		optr1 = optr2;
	if(optr1 < 0)
		return Build_Exp(src + 1, des - 1); //被括号包围
	Node* upper = new Node;
	upper->ope[0] = str[optr1];
	upper->ope[1] = '\0';
	upper->lchild = Build_Exp(src, optr1 - 1); //递归建左子树
	upper->rchild = Build_Exp(optr1 + 1, des); //递归建右子树
	return upper;
}

void Exp::Pre_Order(Node* rot)
{
	if(rot != NULL)
	{
		sprintf(&pre[prelen], "%s", rot->ope);
		prelen += strlen(rot->ope);
		pre[prelen++] = ' ';
		Pre_Order(rot->lchild);
		Pre_Order(rot->rchild);
	}
}

void Exp::Post_Order(Node* rot)
{
	if(rot != NULL)
	{
		Post_Order(rot->lchild);
		Post_Order(rot->rchild);
		sprintf(&post[postlen], "%s", rot->ope);
		postlen += strlen(rot->ope);
		post[postlen++] = ' ';
	}
}

double Exp::Pre_Calucate()
{
	pos++;
	if(pre[pos] == ' ') pos++;
	if(pre[pos] >= '0' && pre[pos] <= '9')
	{
		double temp;
		int length;
		sscanf(&pre[pos], "%lf%n", &temp, &length);
		pos += length - 1;
		return temp;
	}
	if(pre[pos] == '+')
		return Pre_Calucate() + Pre_Calucate();
	if(pre[pos] == '-')
		return Pre_Calucate() - Pre_Calucate();
	if(pre[pos] == '*')
		return Pre_Calucate() * Pre_Calucate();
	if(pre[pos] == '/')
		return Pre_Calucate() / Pre_Calucate();
}

double Exp::Post_Calucate()
{
	postlen = strlen(post) - 1; //最后一个是空格
	for(int i = 0; i < postlen; ++i)
	{
		if(post[i] >= '0' && post[i] <= '9') //操作数
		{
			double temp;
			int length;
			sscanf(&post[i], "%lf%n", &temp, &length);
			i += length - 1;
			num.push(temp);
		}
		else if(post[i] == ' ')
			continue;
		else//操作符
		{
			double a, b;
			b = num.top(); num.pop();
			a = num.top(); num.pop();
			switch(post[i])
			{
			case '+': num.push(a + b); break;
			case '-': num.push(a - b); break;
			case '*': num.push(a * b); break;
			case '/': num.push(a / b); break;
			}
		}
	}
	return num.top();
}

double Exp::result()
{
	Pre_Order(root);
	PreOut();
	Post_Order(root);
	PostOut();
	return Pre_Calucate();
	//return Post_Calucate();
}

void Exp::clear(Node* rot)
{
	if(rot->lchild != NULL)
		clear(rot->lchild);
	if(rot->rchild != NULL)
		clear(rot->rchild);
	delete(rot);
}

int main()
{
	int ncase;
	scanf("%d", &ncase);
	while(ncase--)
	{
		char s[MAX];
		cin>>s;
		Exp e(s);
		printf("%.2lf\n", e.result());
	}
	return 0;
}


【算法题集锦之四】--算术表达式转二叉树并还原

算术表达式,即由数字和运算符号组成的式
  • mhxy199288
  • mhxy199288
  • 2014年07月21日 23:44
  • 2769

二叉树与表达式(前缀,中缀,后缀表达式)

表达式简介
  • wcj920946195
  • wcj920946195
  • 2016年12月05日 09:51
  • 2669

[算法学习]后缀表达式转二叉树

问题描述: 输入后缀表达式,输出后缀表达式的二叉树。 解法与分析: 1. 根据后缀表达式的特点,我们可以知道,只要是运算符的就都是根结点。 2. 我们这里需要使用一个栈来保存字...
  • KesarChen
  • KesarChen
  • 2016年02月18日 13:33
  • 7910

表达式求值,用二叉树

  • 2012年06月22日 11:27
  • 41KB
  • 下载

二叉树(C语言)以及构建表达式树

  • 2016年06月03日 18:50
  • 4KB
  • 下载

二叉树算法计算表达式

  • 2010年09月21日 01:06
  • 4KB
  • 下载

c语言 实现二叉树操作 用栈实现算术表达式求值

  • 2014年11月09日 21:04
  • 115KB
  • 下载

表达式二叉树

  • 2012年12月01日 16:44
  • 3KB
  • 下载

北邮计算机数据结构 二叉树存储表达式求值

  • 2015年12月13日 19:29
  • 8KB
  • 下载

用C创建表达式二叉树

  • 2013年11月13日 21:45
  • 11KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:表达式二叉树
举报原因:
原因补充:

(最多只允许输入30个字)