【C++】朝花夕拾——表达式树
表达式树:
叶子是操作数,其余结点为操作符,是二叉树的其中一种应用
====================我是分割线======================
一棵表达式树如下图:

若是对它做中序遍历,则可以得到中缀表达式
做后序遍历,则可以得到后缀表达式
已知树的结点可以表示成:
struct TreeNode {
object element;
TreeNode* leftChild;
TreeNode* rightChild;
};
用后缀表达式构建一棵表达式树:
思路:(与后缀表达式计算四则运算结构相似)
1. 一一读入输入字符串
2. 若是操作数,则初始化为结点后入栈
3. 若是操作符,则从栈中弹出两个结点(新结点的左右子树),与刚读入的操作符结合起来构建新结点,然后入栈
重复1~3,最后栈内有一棵表达式树的root结点
code实现:
#include<iostream>
#include <string>
#include<stack> using namespace std; struct TreeNode{
char element;
TreeNode* leftChild;
TreeNode* rightChild;
TreeNode(char ch, TreeNode* l, TreeNode* r) {
element = ch;
leftChild = l;
rightChild = r;
}
TreeNode() {
element = '';
leftChild = ;
rightChild = ;
}
}; //测试函数——输出树
void drawTree(TreeNode* root, bool infix) {
if (infix) {
if (root) {
//中序遍历
drawTree(root->leftChild, infix);
cout << root->element;
drawTree(root->rightChild, infix);
}
else return;
}
else {
if (root) {
//后序遍历
drawTree(root->leftChild, infix);
drawTree(root->rightChild, infix);
cout << root->element;
}
else return;
}
} int main() {
string input;
stack<TreeNode> expressionTree;
while (cin >> input) {
if (input == "") break;
for (int i = ; i < input.size();) {
char ch = input[i++];
if (ch >= '' && ch <= '') {
TreeNode leaves;
leaves.element = ch;
expressionTree.push(leaves);
}
else {
//出栈,成为新结点右子树
TreeNode* right = new TreeNode(expressionTree.top().element, expressionTree.top().leftChild, expressionTree.top().rightChild);
expressionTree.pop(); ////出栈,成为新结点左子树
TreeNode* left = new TreeNode(expressionTree.top().element, expressionTree.top().leftChild, expressionTree.top().rightChild);
expressionTree.pop(); //新结点入栈
TreeNode leave(ch, left, right);
expressionTree.push(leave);
}
}
TreeNode* root = &expressionTree.top();
expressionTree.pop();
drawTree(root, true);
}
return ;
} //NULL 与 0 的概念
局限性:
1. 假设所有输入合法,无空格等非法符号输入
2. 测试输出函数不能还原优先级,12+3* 的表达式树测试输出将是 1+2*3,而并非(1+2)*3,如果需要,可以在结构体中再加上一个优先级判断,若子结点的操作符优先级小于父结点,则输出时子树的表达式需要最后要整体放到一个括号内。
一些bugs:
关于NULL、0 和 nullptr的学习:
1. NULL是宏
2. C中对于NULL的定义为 #define NULL ((void *)0)
3. C++中对于NULL的定义为0
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
4. C++11中对于nullptr的定义
const
class nullptr_t
{
public:
template<class T>
inline operator T*() const
{ return ; } template<class C, class T>
inline operator T C::*() const
{ return ; } private:
void operator&() const;
} nullptr = {};
5. 由于C++中的定义,在重载函数时容易出错
//NULL 0 nullptr
#include <iostream>
#include <stdio.h> using namespace std; int f(void* ptr) {
return ;
} int f(int num) {
return ;
} int main() {
int result1 = f();
//int result2 = f(NULL);
int result3 = f(nullptr);
cout << "result1 = " << result1 << endl;
//cout << "result2 = " << result2 << endl;
cout << "result3 = " << result3 << endl;
return ;
}
当我把17行的注释符去掉时:编译错误

最后运行的结果如下:

说明C++11标准中,nullptr的调用在重载时不会又歧义,而0则会在重载时调用int形参的函数
在C++中,可以的话,尽量用nullptr为空指针赋值
文章推荐:
http://www.cppblog.com/airtrack/archive/2012/09/16/190828.html
【C++】朝花夕拾——表达式树的更多相关文章
- 再讲IQueryable<T>,揭开表达式树的神秘面纱
接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...
- [C#] C# 知识回顾 - 表达式树 Expression Trees
C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...
- 轻量级表达式树解析框架Faller
有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架" ...
- 用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树
这些对老一代的程序员都是老生常谈的东西,没什么新意,对新生代的程序员却充满着魅力.曾经新生代,好多都经过漫长的学习,理解,实践才能掌握委托,表达式树这些应用.今天我尝试用简单的方法叙述一下,让大家在五 ...
- LinqToDB 源码分析——处理表达式树
处理表达式树可以说是所有要实现Linq To SQL的重点,同时他也是难点.笔者看完作者在LinqToDB框架里面对于这一部分的设计之后,心里有一点不知所然.由于很多代码没有文字注解.所以笔者只能接合 ...
- LinqToDB 源码分析——生成表达式树
当我们知道了Linq查询要用到的数据库信息之后.接下就是生成对应的表达式树.在前面的章节里面笔者就已经介绍过.生成表达式树是事实离不开IQueryable<T>接口.而处理表达式树离不开I ...
- 干货!表达式树解析"框架"(1)
最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 关于我和表达式树 其实我也没有深入了解表达式树一些内在实现的原理 ...
- 干货!表达式树解析"框架"(2)
最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 为了过个好年,我还是赶快把这篇完成了吧 声明 本文内容需要有一定 ...
- 干货!表达式树解析"框架"(3)
最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 这应该是年前最后一篇了,接下来的时间就要陪陪老婆孩子了 关于表达 ...
随机推荐
- YTU 2905: The Sum of 1...N
2905: The Sum of 1...N 时间限制: 1 Sec 内存限制: 128 MB 提交: 281 解决: 51 题目描述 Given an integer n,your task i ...
- MyEclipse8.5优化
MyEclipse8.5优化 第一步: 取消自动validation validation有一堆,什么xml.jsp.jsf.js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下 ...
- HTTP网络请求原理 (三) 简单模拟HTTP服务器
HTTP实际上是基于TCP的应用层协议,它在更高的层次封装了TCP的使用细节,是网络请求操作更为易用. TCP连接是因特网上基于流的可靠连接,它为HTTP提供了一条可靠的比特传输管道. 从TCP连接一 ...
- 如何将Eclipse中的项目迁移到Android Studio中
如果你之前有用Eclipse做过安卓开发,现在想要把Eclipse中的项目导入到Android Studio的环境中,那么首先要做的是生成Build Gradle的文件.因为Android Studi ...
- Python之Split函数
python中的split()函数用来拆分一个字符串,通过指定的分隔符对字符串进行切割,返回切割后的字符串列表list. split()函数用法: str.split(str=' ',num = st ...
- 并不对劲的manacher算法
有些时候,后缀自动机并不能解决某些问题,或者解决很麻烦.这时就有各种神奇的字符串算法了. manacher算法用来O(|S|)地求出字符串S的最长的回文子串的长度.这是怎么做到的呢? 并不对劲的暴力选 ...
- bzoj4289 PA2012 Tax——点边转化
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4289 好巧妙的转化!感觉自己难以想出来... 参考了博客:https://blog.csdn ...
- UVa 1363 Joseph's Problem (数论)
题意:给定 n,k,求 while(i <=n) k % i的和. 析:很明显是一个数论题,写几个样例你会发现规律,假设 p = k / i.那么k mod i = k - p*i,如果 k ...
- E20180202
attribute n. 属性; (人或物的) 特征; 价值; [语法学] 定语; attribute ... to ... vt.认为…是; 把…归于; 把…品质归于某人; 认为某事[物]属于某人 ...
- mysql 时间向减写法
select * from ( select c.OrderNumber , c.Name as equipmentName, a.*, d.Starttime, d.E ...