中缀表达式——表达式树

还记得之前讲过的波兰表达式和逆波兰表达式么?我再最后提了一句可以将中缀表达式像以下的方法解析成一个树:


波兰和逆波兰表达式分别是对上面得树进行前序和后序遍历。我们这里的表达式树,就是这个树。我们现在需要学习如何将中缀表达式转化为上面这个树。


代码实现

事实上我们可以简单的总结几个小结论:

1.叶节点一定是数字
2.没有括号的情况下,相对运算优先级低的运算符放在树的上层位置

根据上面的两个结论,我们对建树就有一个粗略的概念了,用l和r分别表示两个端点[l,r),如果r-l=1,代表表达式由一个结点组成,如果表达式合法,那么剩下的一定是一个数字,于是构造成叶节点。

对于一长段的表达式,我们需要遍历一遍找到合适的运算符作为根节点。但现在的问题如何处理括号改变运算优先级的情况。

事实上我们再深入观察一下可以发现,如果一个表达式括号外有运算符,那么括号外的运算符的优先级一定可以视为低于括号内的运算符。也就是说作为根节点的运算符,一定要在括号之外。

如果不存在这样的结点呢?说明整个表达式都在括号之内,脱去外层的括号即可。代码如下:

const int maxn=1000;//nc表示当前树里面的结点总数,lch[i]和rch[i]表示编号为i的结点左右子节点的编号
int lch[maxn],rch[maxn],nc=0; char op[maxn];//op[i]表示编号为i的结点存储的字符
int build_tree(char* s,int l,int r){//l和r分别表示遍历表达式某段区间的左右端点:[x,y) int i,c1=-1,c2=-1,p=0;//p用于记录当前表达式出现的括号数,左括号+1,右括号-1//p=0代表在括号外,p不等于0代表在括号内//当我们寻找根节点时,我们优先需要寻找的是括号外的运算符作为根节点//c1表示括号外最后出现的"+-"运算符,c2表示括号外最后出现的"*/"运算符//因为对于一个表达式,没有括号下两种运算符的优先级是不同的//加减后运算所以应当放在较为上层的位置if (r-l==1){nc++; lch[u]=rch[u]=0; op[u]=s[l]; return nc;} //当区间内仅一个字符,那么它显然为一个叶节点,当前的结点个数作为它的编号//由于是叶结点,叶节点没有左右子节点,lch和rch的值设置为0  for (int i=l;i<r;i++){//将表达式的字符遍历一编,寻找括号外的运算符 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(s,x+1,y-1);//整个表达式被一对括号括起来了 //以c1作为根节点递归遍历左子树和右子树 nc++; lch[nc]=build_tree(s,l,c1); rch[nc]=build_tree(s,c1+1,r);op[nc]=s[c1]; return nc;
}

事实上我怀疑会不会转化成前缀表达式,之后做起来思路上更加清晰。

中缀表达式——表达式树相关推荐

  1. delegate、Lambda表达式、Func委托和Expression(TDelegate)表达式目录树

    1.delegate MSDN:一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似.与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的.委托的类型由委托的名称定义 class ...

  2. 第十九节: 结合【表达式目录树】来封装EF的BaseDal层的方法

    一. 简介 该章节,可以说是一个简单轻松的章节,只要你对Expression表达式树.EF的基本使用.泛型有所了解,那么本章节实质上就是一个非常简单的封装章节,便于我们快捷开发. PS:在该章节对于E ...

  3. 第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)

    一. 基本介绍 回忆: 最早接触到表达式目录树(Expression)可能要追溯到几年前使用EF早期的时候,发现where方法里的参数是Expression<Func<T,bool> ...

  4. 前缀中缀后缀表达式的计算求值

    原文在这里 表达式 前缀表达式(波兰表达式) 前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前 举例说明: (3+4)×5-6 对应的前缀表达式就是 - × + 3 4 5 6 前缀表达式求值 ...

  5. 表达式目录树(Expression)

    表达式目录树 什么是表达式目录树呢?用于表示Lambda表达式逻辑的一种数据结构,表达式树也可以称作表达式目录树,它 将代码表示成一个对象树,而不是可执行的代码.这个跟汇编原理一样,我们找到关键字,把 ...

  6. Java解析SQL生成语法树_Atitit.sql ast 表达式 语法树 语法 解析原理与实现 java php c#.net js python...

    Atitit.sql ast 表达式 语法树 语法 解析原理与实现java php c#.net js python 1.1.Sql语法树ast如下图锁死 2.SQL语句解析的思路和过程 2.1.le ...

  7. C#表达式目录树系列之5 –动态创建查询表达式

    概要 在项目开发中,根据用户的需求,一般来是,我们的查询表达式是固定的,新的查询需求都要通过代码的修改来实现.而对于不确定的查询条件,固定查询表达式的方式显然是行不通的. 针对固定查询表达式存在的问题 ...

  8. Lambda表达式表达式树

    在C#3.0中,继匿名方法之后出现了Lambda 表达式,使表达更为简洁.快捷.Lambda 表达式使用Lambda 运算符 "=>"来定义,语法如下: (参数列表) =&g ...

  9. (中缀)表达式转换成前缀表达式、后缀表达式

    认识前缀.中缀.后缀表达式: 一般我们平时用的计算式都是中缀表达式,因为符号都是在操作数的中间的.相对应的符号在操作数后面的就叫后缀表达式(也称逆波兰式),符号在操作数前面的就叫前缀表达式(也称波兰式 ...

  10. 数据结构与算法——24. 树的应用:表达式解析树

    文章目录 一.解析树 二.解析树实例:表达式解析 1. 建立表达式解析树 (1)建立表达式解析树的规则 (2)建立表达式解析树的思路 (3)python代码实现 2. 表达式解析树的求值 (1)增加程 ...

最新文章

  1. B - Frogger POJ - 2253
  2. Thymeleaf 标准表达式语法详解
  3. Python subprocess模块
  4. 突出告警信息(DBA_OUTSTANDING_ALERTS)
  5. libevent简介和使用【转】
  6. HTML+CSS+JavaScript复习笔记持更(二)——列表篇
  7. ZOJ-1610-Count the Colors
  8. 字体样式 font-family 0911
  9. androidStudio导入库文件
  10. 声明了包的类Java命令找不到或无法加载主类
  11. English course (6)
  12. 肿瘤免疫浸润资源汇总
  13. Fedora Linux 14百度云下载,Fedora Linux 14下载
  14. 1stopt拟合步骤_1stopt快速公式拟合
  15. 爱看小说程序源码+4W条数据全站打包
  16. PIC16F887 单片机 信号发生器 波形发生器 PCF8591
  17. 18获得触发事件元素节点的方法
  18. qcom 音频相关的dsp driver笔记(基于msm8996平台)
  19. mysql和oracle面试题_【SQL 面试题2】Mysql 和Oracle数据库
  20. 编程参考- 重名符号的链接问题

热门文章

  1. 如何减小数据库日志文件.ldf
  2. DelphiX中的DXSprite单元中涉及到修改
  3. linux重新初始化mysql 并修改大小写铭感_在Linux(Centos 7)环境下安装Mysql的完整过程...
  4. yaws mysql_MySQL入门之C语言操作MySQL
  5. pip 安装指定版本的库
  6. WinUsbNet: A managed interface to WinUSB.sys
  7. 浅谈SpringMVC源码的SpringServletContainerInitializer的完整加载流程
  8. Echarts实现成都市地图下钻
  9. 四年级信息技术上册课本上类似于logo的绘图编程语言-GoC之不为人知的技巧
  10. vim保存文件”:wq与“:x的区别以及小写:x与大写“:X”的区别