C++ — 后缀表达式转表达式树
2018-07-21 16:57:26 update
建立表达式树的基本思路:方法类似由下而上建立堆的思想,所以时间复杂度为O(n),这样算法就会变得很简单,只用考虑处理需要入栈的节点和栈中的节点即可。。。
code:
#include "stdafx.h"
#include <iostream>
#include <stack>
#include <string> class expr_tree
{
struct base_node
{
char c;
base_node * lc, *rc;
base_node() {}
base_node(char c)
: c(c)
, lc(nullptr)
, rc(nullptr)
{
}
} * root;
protected:
void parse_expr(std::string str);
void proorder_print(base_node * n);
void inorder_print(base_node * n);
void postorder_print(base_node * n);
void destory(base_node * & n);
double eval(base_node * n); public:
void show(); expr_tree(std::string str)
{
parse_expr(str);
}
~expr_tree()
{
destory(this->root);
}
}; void expr_tree::parse_expr(std::string str)
{
std::stack<base_node *> stack_node;
for (auto c : str)
{
base_node * node = new base_node(c);
if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z')
stack_node.push(node);
else if (c == '+' || c == '-' || c == '*' || c == '/')
{
if (!stack_node.empty())
{
node->rc = stack_node.top();
stack_node.pop();
}
if (!stack_node.empty())
{
node->lc = stack_node.top();
stack_node.pop();
}
stack_node.push(node);
}
else
{
std::cout << "表达式有误!" << std::endl;
exit(1);
}
}
root = stack_node.top();
while (!stack_node.empty())
stack_node.pop();
} void expr_tree::proorder_print(base_node * n)
{
if (n)
{
std::cout << n->c;
proorder_print(n->lc);
proorder_print(n->rc);
}
} void expr_tree::inorder_print(base_node * n)
{
if (n)
{
if (n->c >= '0' && n->c <= '9')
std::cout << n->c;
else
{
std::cout << '(';
inorder_print(n->lc);
std::cout << ' ' << n->c << ' ';
inorder_print(n->rc);
std::cout << ')';
}
}
} void expr_tree::postorder_print(base_node * n)
{
if (n)
{
postorder_print(n->lc);
postorder_print(n->rc);
std::cout << n->c;
}
} void expr_tree::show()
{
std::cout << "前缀表达式:" << std::endl;
proorder_print(this->root);
std::cout << std::endl;
std::cout << "中缀表达式:" << std::endl;
inorder_print(this->root);
std::cout << " = " << eval(this->root) << std::endl;
std::cout << "后缀表达式:" << std::endl;
postorder_print(this->root);
std::cout << std::endl;
} double expr_tree::eval(base_node * n)
{
switch (n->c)
{
case '+': return eval(n->lc) + eval(n->rc);
case '-': return eval(n->lc) - eval(n->rc);
case '*': return eval(n->lc) * eval(n->rc);
case '/': return eval(n->lc) / eval(n->rc);
default: return n->c - '0';
}
} void expr_tree::destory(base_node * & root)
{
if (root != nullptr)
{
destory(root->lc);
destory(root->rc);
delete root;
}
} int main()
{
std::string str = "23+456+**"; expr_tree res(str);
res.show();
return 0;
}
C++ — 后缀表达式转表达式树的更多相关文章
- [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门
[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...
- [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用
[.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是 ...
- C#中的Lambda表达式和表达式树
在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...
- 16.C#初见Lambda表达式及表达式树(九章9.1-9.3)
在说明Lambda相关知识前,我们需要了解Lambda表达式常用于LINQ,那么我们来聊下LINQ. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑: ...
- Lambda表达式和表达式树
在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...
- C#3.0 Lamdba表达式与表达式树
Lamdba表达式与表达式树 Lamdba表达式 C#2.0中的匿名方法使得创建委托变得简单起来,甚至想不到还有什么方式可以更加的简化,而C#3.0中的lamdba则给了我们答案. lamdba的行为 ...
- C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)
Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string ...
- 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types
匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...
- 无法将具有语句体的lambda表达式转换为表达式树
很早就碰到了这个问题,当时也没有深入的研究,趁着空闲,遂把这个问题研究清楚. (一)普通案例 下面从一个普通的案例入手,下面准备两个List集合,都是放在内存里面的(需要模拟到远端执行的时候,我们是通 ...
- 【BZOJ4556】字符串(后缀数组,主席树)
[BZOJ4556]字符串(后缀数组,主席树) 题面 BZOJ 题解 注意看题: 要求的是\([a,b]\)的子串和[c,d]的\(lcp\)的最大值 先来一下暴力吧 求出\(SA\)之后 暴力枚举\ ...
随机推荐
- docker删除mysql镜像失败Error response from daemon: conflict: unable to delete 8809d5286227 (must be forced) - image is being used by stopped container 1a2a427273b3
错误解析:这是由于要删除的目标镜像中有容器存在,故无法删除镜像 解决办法:先删除镜像中的容器,再删除该镜像.
- laravel框架学习笔记
一.laravel的安装 1.composer 作用:主要管理php中的依赖关系(类似于yum源) 可以安装的软件: curl //主要用到微信开发中 upload //文本操作 excel / ...
- vscode git连接github
上一篇文章中介绍了vscode中git的简单使用方法vscode git的简单使用 上次只讲到了本地库的创建,这次说明下怎么push到github上 首先需要有一个github的账号 github官 ...
- ListView 基础列表组件、水平 列表组件、图标组件
一.Flutter 列表组件概述 列表布局是我们项目开发中最常用的一种布局方式.Flutter 中我们可以通过 ListView 来定义 列表项,支持垂直和水平方向展示.通过一个属性就可以控制列表的显 ...
- Linux下RabbitMQ的安装及使用
过多的描述就不扯了,本文主要记录RabbitMQ的安装以及简单使用.本次安装是为了实现spring cloud的消息总线:SpringCloud全家桶学习之消息总线---SpringCloud Bus ...
- 为什么局部内部类和匿名内部类只能访问 final 的局部变量?
首先,我们看一个局部内部类的例子: class OutClass { private int age = 12; public void outPrint(final int x) { class I ...
- vscode 提示 Running save participants 无法保存文件
今天vscode提示一直在running save participants...中,无法保存文件 control + shift + p打开面板后,输入Reload with extensions ...
- Fluent_Python_Part2数据结构,04-text-byte,文本和字节序列
文本和字节序列 人使用文本,计算机使用字节序列 1. 大纲: 字符.码位和字节表述 bytes.bytearray和memoryview等二进制序列的独特特性 全部Unicode和陈旧字符集的编解码器 ...
- web渗透(转)
某天比较无聊,听一个朋友推荐httpscan这款工具,于是就下载下来试试. 首先对某学校网段开始进行测试. 1 python httpscan.py **.**.**.0/24 测试时发现有个比较 ...
- ROS及Ubuntu学习记录
1.ROS安装时出现 “无法获得锁的解决方法” 参考:https://www.jianshu.com/p/6868ed4b4aec 2.运行rviz时 要先在一个终端窗口运行roscore 3.虚拟机 ...