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\)之后 暴力枚举\ ...
随机推荐
- CI 框架多表关联查询
public function getCollectData($limit, $page, $search_user, $search_phone, $orderfield, $ordertype) ...
- STM32F103之GPIO学习记录
9 GPIO:通用I/O口 AFIO:可供选择的I/O口 9.1 GPIO功能描述 每一个通用的I/O口都有: 两个32位的配置寄存器(配置寄存器低和配置寄存器高): 两个32位的数据寄存器(输入数据 ...
- u盘乱码了,如何备份
文/亡命之徒 2013年7月的最后一天,今天在公司下了些嵌入式的教程存在u盘里,准备拿回家到自己的本子上学习,不知怎的查到电脑上,显示一些文件夹,名字都是乱码,顿时心情扫地,无奈只能到互联网上寻找re ...
- Could not set property of class with value There is no setter for property named
检查entity中类的属性与MAPPER中的resultMap属性是否一致
- Java进阶学习(3)之对象容器.小练习
查找里程(10分) 题目内容: 下图为国内主要城市之间的公路里程: 你的程序要读入这样的一张表,然后,根据输入的两个城市的名称,给出这两个城市之间的里程. 注意:任何两个城市之间的里程都已经给出,不需 ...
- VMware 14 激活密钥
VMware 14 激活密钥 FF31K-AHZD1-H8ETZ-8WWEZ-WUUVA CV7T2-6WY5Q-48EWP-ZXY7X-QGUWD
- django模块导入/函数/中间件/MVC和MTV/CSRF
目录 一:模块导入 二:函数 三:中间件 四:MVC和MTV 五:csrf 一:模块导入 第一种:继承 这里的母版更像是一个架子,子板都是定义的内容(如果多个页面中 ,存在相同的页面:这样我们可以抽到 ...
- selenium Python实现附件上传
对于web页面的上传功能一般有两类实现方式:一类是将本地文件的路径作为一个值放在input标签中,通过form表单将这个值提交给服务器:另一个类是插件上传,一般基于flash/javascript或者 ...
- Educational Codeforces Round 76 (Rated for Div. 2)E(最长上升子序列)
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;int a[200007],b[200007] ...
- idea 快捷使用(二)回退断点的使用
在调试的时候,想要重新走一下流程而不用再次发起一个请求? 1.所谓的断点回退,其实就是回退到上一个方法调用的开始处,在IDEA里测试无法一行一行地回退或回到到上一个断点处,而是回到上一个方法.回退的方 ...