ACM:树的变换,根据表达式建立表达式树

题目:输入一个表达式,建立一个表达式树!

分析:找到最后计算的运算符(它是整棵表达式树的根),然后递归处理!

在代码中,只有当p==0的时候,才考虑这个运算符,因为括号里的运算符一定不是最后计算的,应当忽略!

由于加减跟乘除都是左结合的,最后一个运算符才是最后计算的,所以用两个变量c1跟c2分别记录在括号外面的“最右”出现的加减号和乘除号。

#include <iostream>
#include <string>
using namespace std;

const int MAXN = 1000;
string str;  //表达式
int lch[MAXN], rch[MAXN];   //每个节点的左右儿子节点编号
char op[MAXN];   //每个节点里面的字符
int nc = 0;   //代表节点个数

int build_tree(string s, int x, int y) {
	int p = 0, c1 = -1, c2 = -1;   //c1和c2分别记录最右出现的加减号和乘除号,前提是他们在括号外面,因为如果在括号里面的话,这个运算符肯定不是最后一个计算的!
	int u;
	if(y - x == 1) {   //如果仅有一个字符,那么建立单独节点!
		u = ++nc;
		lch[u] = 0;
		rch[u] = 0;
		op[u] = s[x];
		return u;
	}
	for(int i = x; i < y; ++i) {  //找括号外面的最右边的加减号跟乘除号,位置分别由c1跟c2记录!
		switch(s[i]) {
			case '(' : ++p; break;
			case ')' : --p; break;
			case '+' : case '-' : if(!p) {c1 = i; break;}   //如果这个 “+” 或者这个 “-” 是在括号外面的!
			case '*' : case '/' : if(!p) {c2 = i; break;}   //如果这个 “*” 或者这个 “/” 是在括号外面的!
		}
	}
	if(c1 < 0) c1 = c2;  //如果括号外面没有加减号,那就只能考虑括号外面的乘除号了。
	if(c1 < 0) return build_tree(str, x+1, y-1);   //如果括号外面加减乘除号都没有,那意思就是整个表达式被一个括号包围了。
	u = ++nc;
	lch[u] = build_tree(str, x, c1);   //运算符s[c1]的左子树区间是[x, c1],右子树区间是[c1+1, y]
	rch[u] = build_tree(str, c1+1, y);
	op[u] = s[c1];
	return u;
}

int main() {
	cin >> str;
	build_tree(str, 0, str.size());
	for(int i = 1; i < nc+1; ++i) {
		cout << lch[i] << "  " << rch[i] << "  " << op[i] << endl;
	}
	return 0;
}

ACM:树的变换,根据表达式建立表达式树

时间: 2024-10-14 16:08:54

ACM:树的变换,根据表达式建立表达式树的相关文章

Java实现后缀表达式建立表达式树

概述 表达式树的特点:叶节点是操作数,其他节点为操作符.由于一般的操作符都是二元的,所以表达式树一般都是二叉树. 根据后缀表达式"ab+cde+**"建立一颗树 文字描述: 如同后缀表达式求值一样,逐个读取后缀表达式的每一个符号,如果遇到操作数,建立一个节点把操作数的值加入这个节点,并把节点入栈:如果遇到操作符,弹出栈里的两个节点,并赋值为自己的左子节点.右子节点,最后把这个节点树入栈. 画图描述: 1.读入操作数a,创建节点,压入栈:读入操作数b,创建节点,压入栈 2.遇到操作符&q

Lambda表达式和表达式树

在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等.通常这些操作都是用委托来表示.Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式. Lambda表达式不仅可以用来创

C#中的Lambda表达式和表达式树

在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等.通常这些操作都是用委托来表示.Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式. Lambda表达式不仅可以用来创

[.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用

[.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是时候来引用他解决问题.而本节主要目的就是使用表达式树解决实际问题. 读前必备: 本节学习前,需要掌握以下知识: A.继承 [.net 面向对象编程基础]  (12) 面向对象三大特性——继承 B.多态 [.net 面向对象编程基础]  (13) 面向对象三大特性——多态 C.抽象类 [.net 面向

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习表达式在程序设计中的优点:比如构造动态查询.动态构造表达式树完成未知对象属性访问,比反射的性能高出很多.我们可以说表达式树才是Lambda的精髓,是我们必须要熟练掌握并灵活运用的. 1.关于表达式树(Expression Tree) 表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如

16.C#初见Lambda表达式及表达式树(九章9.1-9.3)

在说明Lambda相关知识前,我们需要了解Lambda表达式常用于LINQ,那么我们来聊下LINQ. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑:如何过滤.如何排序以及如何将不同的数据源连接在一起,等等.执行委托只是LINQ的众多能力之一.为了富有效率地使用数据库和其他查询引擎,我们需要以一种不同的方式来表示管道中的各个操作.这种不同的方式就可以使用Lambda表达式来表现.下面分别使用委托(使用匿名函数)和Lambda表达式来作出同样的事情

前中后缀表达式以及表达式树

中缀表达式就是我们平时喜闻乐见的形式:二元运算符在中间,它的两个操作数在两侧: a + b * c + ( d * e + f ) * g 后缀和前缀表达式,顾名思义就是把运算符分别放在前面或者后面,注意没有括号,手工转换方法是按运算顺序添加括号,然后把相应的运算符置于相应的括号的前或后,如: ((a + ( b * c)) + (((d * e) + f) * g)) 放到前面有: +(+(a*(b c))*(+((*(d e))f)g)) 放到后面有: ((a(b c)*)+(((d e)*

ACM:树的变换,无根树转有根树

题目: 输入一个n个节点的无根树的各条边,并指定一个根节点,要求把该树转化为有根树,输出各个节点的父亲编号. 分析:分析在代码的注释中! #include <iostream> #include <vector> using namespace std; const int MAXN = 1000; int n, p[MAXN]; vector<int> G[MAXN]; void dfs(int u, int fa) { //递归转化为以u为根的子树,u的父亲为fa

c# Lambda表达式和表达式树

using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SRLJCSHAP.委托.Demo { delegate void StringProcessor(string input);//声明委托类型 public class Person {