表达式树:

       叶子是操作数,其余结点为操作符,是二叉树的其中一种应用

====================我是分割线======================

一棵表达式树如下图: 

  

  若是对它做中序遍历,则可以得到中缀表达式

      做后序遍历,则可以得到后缀表达式

已知树的结点可以表示成

 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++】朝花夕拾——表达式树的更多相关文章

  1. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  2. [C#] C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  3. 轻量级表达式树解析框架Faller

    有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架" ...

  4. 用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树

    这些对老一代的程序员都是老生常谈的东西,没什么新意,对新生代的程序员却充满着魅力.曾经新生代,好多都经过漫长的学习,理解,实践才能掌握委托,表达式树这些应用.今天我尝试用简单的方法叙述一下,让大家在五 ...

  5. LinqToDB 源码分析——处理表达式树

    处理表达式树可以说是所有要实现Linq To SQL的重点,同时他也是难点.笔者看完作者在LinqToDB框架里面对于这一部分的设计之后,心里有一点不知所然.由于很多代码没有文字注解.所以笔者只能接合 ...

  6. LinqToDB 源码分析——生成表达式树

    当我们知道了Linq查询要用到的数据库信息之后.接下就是生成对应的表达式树.在前面的章节里面笔者就已经介绍过.生成表达式树是事实离不开IQueryable<T>接口.而处理表达式树离不开I ...

  7. 干货!表达式树解析"框架"(1)

    最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 关于我和表达式树 其实我也没有深入了解表达式树一些内在实现的原理 ...

  8. 干货!表达式树解析"框架"(2)

    最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 为了过个好年,我还是赶快把这篇完成了吧 声明 本文内容需要有一定 ...

  9. 干货!表达式树解析"框架"(3)

    最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 这应该是年前最后一篇了,接下来的时间就要陪陪老婆孩子了 关于表达 ...

随机推荐

  1. accept()函数用来告诉Qt,事件处理函数“接收”了这个事件,不要再传递;ignore()函数则告诉Qt,事件处理函数“忽略”了这个事件,需要继续传递(看一下QWidget::mousePressEvent的实现,最为典型。如果希望忽略事件,只要调用父类的响应函数即可)

    QEvent的accept()和ignore()一般不会用到,因为不如直接调用QWidget类的事件处理函数直接,而且作用是一样的,见下面的例子. 推荐直接调用QWidget的事件处理函数.而不是调用 ...

  2. XMU 1613 刘备闯三国之三顾茅庐(一) 【并查集】

    1613: 刘备闯三国之三顾茅庐(一) Time Limit: 1000 MS  Memory Limit: 128 MBSubmit: 99  Solved: 29[Submit][Status][ ...

  3. YTU 2597: 编程题B-选拔飞行员

    2597: 编程题B-选拔飞行员 时间限制: 1 Sec  内存限制: 128 MB 提交: 131  解决: 35 题目描述 2100年空军选拔高中生飞行学员基本条件要求如下,年龄范围:16-19周 ...

  4. bootstrap3.0学习笔记记录1

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. 解决多次异步请求紊乱问题 - JavaScript

    加入目前的需求这样的:       左边的菜单链接,点击后通过异步请求返回其HTML代码,然后innerHTML到右面的DIV中,加入切换菜单的速度非常快,最终会导致请求紊乱. 可以加入消息管理机制, ...

  6. I.MX6 wpa_cli 使用

    /*********************************************************************** * I.MX6 wpa_cli 使用 * 说明: * ...

  7. Python 函数定义以及参数传递

    Python 函数定义以及参数传递1.函数定义#形如def func(args...): doSomething123以关键字def 开头,后面是函数名和参数下面是函数处理过程. 举例: def ad ...

  8. CodeForces 723C Polycarp at the Radio (题意题+暴力)

    题意:给定 n 个数,让把某一些变成 1-m之间的数,要改变最少,使得1-m中每个数中出现次数最少的尽量大. 析:这个题差不多读了一个小时吧,实在看不懂什么意思,其实并不难,直接暴力就好,n m不大. ...

  9. bzoj 3979: [WF2012]infiltration【瞎搞+随机化】

    参考:https://www.cnblogs.com/ccz181078/p/5622200.html 非常服气.jpg 就是random_shuffle几次然后顺着找,ans取min... #inc ...

  10. 洛谷 P2762 太空飞行计划问题 【最大权闭合子图+最小割】

    --一道难在读入的题. 最后解决方案直接getline一行然后是把读优拆掉放进函数,虽然很丑但是过了. 然后就是裸的最大权闭合子图了,把仪器当成负权点向t连流量为其价格的边,s向实验连流量为实验报酬的 ...