今天闲来无事,想到一个自以为绝妙的想法,那就是用后序遍历二叉树Lambda演算的化简
数据结构与算法中,我们想写个计算器就必须遇到一个问题,表达式求值!其实表达式很多就是我们所谓的现实生活中的问题解法的一种抽象------“函数”的写法。
看到邓俊辉老师数据结构说的用栈求解运算表达式的时候,提到一个“push代表左括号,POP代表右括号”的想法,其实也相当于写出了“逆波兰表达式”,然后求值。根据对称性,肯定相对的也有前缀表达式,但是(逆波兰表达式)后缀表达式求值只需要一个栈存操作数和操作码,似乎更加方便,更加体现运算的本质。重点是,联想到前缀表达式的时候,我脑海不由自主地浮现出“f x y”------函数式编程里的柯里化!习惯把函数写成F(x)的那些程序猿把C语言设计成很多括号,甚至有个笑话说破译到美军加密最后一页的代码满满的全是括号。然后,我学Haskell的时候的确被这种表达方式的简洁美观和传参(甚至可以传递含参函数例如f x 2)惊艳到了。
我在想,把函数f看做操作码的一种运算符号类比±*/^的话,这个前缀表达式可不就等价于柯里化后的函数的写法(二元预运算符的话对应二元函数,多元对应多元函数同时也可以看做f (x y) z特殊的二元函数嵌套问题,利用已有结论)?
知道今天我看书的时候突然想到,上述这种利用“进出栈实现去括号”的操作也等价于《图解数据结构使用C++》里面的二叉运算树------通过不同遍历方式转换成前序表达式,中序表达式,后序表达式的化简过程------“加括号,然后把运算符放树根的话,运算数左子树对应左括号,右子树对应右括号,去括号逆波兰表达式一样的操作”。
那么可以得出结论:
从某种观点来看,用后序遍历运算二叉树等价于用栈求解逆波兰表达式;用先序遍历二叉运算树等价于Lambda演算的化简。
那么问题来了,发现他们的相似性有什么用呢?我觉得吧,打通知识轮子之间的关系,两者的结论就能相通互补。同一个问题我们把数学撒三巨头“分析符号Lambda运算”,“几何的二叉树”,“代数的运算表达式”把他们联系到了一起!互相的结论可以相互“翻译转化利用”。

比如:
Lambda演算用的那种类似Ctrl+CV的演算化简操作,遇到复杂的公式的时候会写满一张纸也很难化简明白,也很费内存(这也是为什么当初内存珍贵的时候函数式变成不被欢迎的一部分原因),有了这个等价转换,我们能够把化简一个lambda问题转化为化简一个运算二叉树的问题,然后利用现有二叉树相关的结论进行化简,利用二叉树的数据结构放进去计算机存储,排序,等价转换和计算!

比如:
利用树结构,栈结构来写个“Lambda表达式演算解析器”来化简,来演算Lambda甚至是这个世界。甚至,我们还能通过这个判断Lambda演算的时候利用二叉树的时间,利用二叉树,栈等问题的时间空间复杂度计算方法来判断Lambda演算的复杂度,寻求更好的演算化简求解算法!

比如:Lambda演算里面的相关定理公式就能直接“搬过来”二叉运算树后序遍历运算表达式来用,或者利用Lambda演算化简的结论丰富二叉树演算的结论。

比如: 二元函数看做二叉树,(二叉树可以表示所有树状结构------森)那,树其实也可以看做多分叉的普通的树,乃至森,网络图,现成的图论方面的算法如果适合的也都能用进去。

我还在脑补一件事,图论的不动点,函数变换的特征根,Lambda表达式的不动点会不会能够这样等价转化为同一个问题------对称与不变性? 就像那个“变换中的不变量”。

这是一个新角度看问题,尽管稚嫩甚至不一定全对,但是想到的时候,我觉得很有趣,能走下去。


学Haskell的时候的确被这种表达方式的简洁和美妙惊艳到。

关于上面这句话我还想说点什么

现在很多祖传代码之所以被称为屎山,我觉得除了垃圾宏或者奇怪的参数莫名其妙的注释,还有很大部分原因是因为循环For和While背锅,因为他们本来就跟人类的想法相悖。人写字计算难道不是线性的吗?为什么不把嵌套函数柯里化后地写在旧函数的后面?
还是那个笑话,某国家破译到美军加密最后一页的代码,满满的全是右括号。大部分编程语言把数学嵌套函数写成(g(x,y)),而函数式编程里的柯里化之后可以写成这样“f g x y”。除了f g x 2 传入一个实参之后传给f的是含参函数g(x,2)而不是Error的好处之外,我觉得这样线性接在后面顺序地添加操作数给操作码的做法“更符合人类的线性的思考方式”。(逆波兰表达式告诉我们这种方法也更适合计算机来计算)还有一个好处是模块独立性好,方便解耦,常说的“范式编程”。新需求来了,直接加在后面。
在写多层嵌套的时候一个个参数去想循环到哪儿简直就是反人类,然而我们先入为主司空见惯,习以为常。滑稽的是,for,while循环的本质代码就是goto,if不是迭代出口条件,执行迭代基进行循环;else 迭代出口初值条件。早期的程序语言Lisp也是用递归写的,更本质。当然,循环也有它适合的地方。顺序,判断,循环,有了他们就能跟鬼子谈条件,解决所有图灵机可解问题。我觉得这句话不如改成,顺序,判断,递归,有了它就能解决所有可解问题。有趣的是,蕴含三大数学常数(指数增长,黄金数复杂度,pi比例)的Fibonacci数列也是递归讲解的最常用的例子!大概是因为世界运作的规律就是包含递归,然后数学物理计算机就是描述世界的工具的原因吧。
而正如邓老师说的:动态规划,把递归编程迭代(DAC)才是好办法。

我对代码的看法是:所有代码都是加诸于计算机RAM机的命令,翻译成机器语言都是让CPU算术逻辑单元运算的一条大型算术表达式*,人为输入部分还可以包装在monad里面保持表达式的数学纯洁性。
那么上述的解决现实世界问题,Simulink模拟现实的代码世界,也可以看做是计算表达式。根据上述的问题,我们得到了一个很好的解决问题的抽象。
这样有什么好处呢?就像用Coq数学定力机器证明,如果我们能把代码和表达式等价转换,然后把表达式化简变成Lambda演算的化简问题,或者转化成上述二叉树化简,图论等问题,那么我们就能实现“机器代码自动重构”------解决祖传代码屎山问题?有没有可能规范化简化成为方便解耦的统一Lambda表达式简化格式?
好吧,这个最简表达式本来也没严格定义出来。Lambda表达式里甚至早早已经证明过Belta简化不具有唯一性,让我想起来“堆排序”利用二叉树排序后的形式也不具有唯一性。但是无所谓,既然有很多等价表述,能不能规定某个分岔路按照约好的“选择”,实现不同表述方式自动转化成为相同的表述方式?实现相同的规范化的预定好的自动化简结构?
好吧,扯远了,相信这样子下去会遇到的问题必然会是像那句话所说的一样,“我们得到的不是机器证明数学定理,而是一本看不懂的01电话本!”------估计又会归结到机器语言和人类语言符号的翻译问题。

“后序遍历二叉运算树进行Lambda演算的化简”带来的联系相关推荐

  1. 线索树找*p的中序后继且中序遍历 二叉线索树

    //线索树找*p的中序后继且中序遍历 二叉线索树 #define thread 1 #define link 0 typedef struct Bt{char data;struct Bt *lc;/ ...

  2. 数据结构—二叉树线索化(线索化的先序、中序、后序遍历)

    1.线索二叉树基本概念 二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历.用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序 ...

  3. 剑指Offer(Java版):二叉搜索树的后序遍历序列

    2019独角兽企业重金招聘Python工程师标准>>> 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组 ...

  4. tree traversal (树的遍历) - postorder traversal (后序遍历)

    tree traversal (树的遍历) - postorder traversal (后序遍历) 1. tree traversal - 树的遍历 二叉树的遍历 (traversing binar ...

  5. 非递归先、中、后序遍历二叉树(C语言)

    文章目录 前言 一.二叉树非递归遍历算法 1.先序遍历 2.中序遍历 3.后序遍历 二.完整程序 三.运行结果实例 前言 本程序采用C语言编写,栈和二叉树的基本操作函数基于严蔚敏老师的<数据结构 ...

  6. 二叉树的四种遍历方法(前序遍历、中序遍历、后序遍历、层序遍历)有图有真相!!!

    文章目录 二叉树的四种遍历方式 前序遍历(Preorder Traversal) 中序遍历(Inorder Traversal) 后序遍历(Postorder Traversal) 层序遍历(Leve ...

  7. 数据结构---二叉线索树

    数据结构-二叉线索树 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> typedef struct bmTree {i ...

  8. 二叉树的前序、中序、后序遍历

    文章目录 前言 一.用递归法实现遍历 1.1 前序遍历 1.2 中序遍历 1.3 后序遍历 二.用迭代法实现遍历 2.1 前序遍历 2.2 中序遍历 2.3 后序遍历 2.3.1 后序解法一 2.3. ...

  9. 《剑指offer》-- 从上往下打印二叉树、二叉搜素树的后序遍历、二叉树中和为某一值的路径、二叉树与双向链表

    一.从上往下打印二叉树: 1.题目: 上往下打印出二叉树的每个节点,同层节点从左至右打印. 2.解题思路: 用arraylist模拟一个队列来存储相应的TreeNode. 3.代码实现: public ...

最新文章

  1. Oracle 11g 新特性 -- Transparent Data Encryption (透明数据加密TDE) 增强 说明
  2. 分享Kali Linux 2016.2第46周虚拟机
  3. Mybatis学习第四天——一对一一对多
  4. 【牛客 - 373A】翻硬币问题(博弈,结论,分析)
  5. php自动验证,ThinkPHP 自动验证及验证规则详解
  6. 2019斯坦福CS224n深度学习自然语言处理笔记(3)反向传播与计算图
  7. Tomas语录-关于String.valueOf()
  8. 详尽Ubuntu18安装搜狗输入法教程
  9. 飘刃 v0.0.10 首次发布,超快执行速度的 Vue 项目构建工具
  10. 教师资格证信息技术主观题
  11. 攒机笔记二十二:台式组装机(2022.9)
  12. 我的JAVA求学之路
  13. 【K最近邻法(KNN)】的Python和R语言简单实现鸢尾花分类
  14. 江西省吉安市谷歌高清卫星地图下载
  15. 网易微专业高级前端开发工程师2022
  16. fastqc检验时不能执行java_安装Fastqc软件遇到的坑
  17. 关于调整互联网、电话订票起售时间的公告
  18. TopLevel和Topmost
  19. 蚂蚁金服面试及笔试(附自己的答案)
  20. SpringMVC +Spring + MyBatis + Mysql + Redis(作为二级缓存) 配置

热门文章

  1. 有关视图状态(ViewState)的一些问题
  2. CSS Repeater - 交错显示行背景色 table行鼠标进入事件特效 禁止文本换行
  3. C#实现用Enter键和Tab键同样功能
  4. 为了车票而奔波着.....
  5. cmake使用教(一)多目录下多个文件的构建
  6. dd linux 尾部添加0_dd使用方法详解
  7. vue 子组件给父组件传值
  8. sql语句ding_SQL语句映射文件增删改查、参数、缓存
  9. mysql 行级锁 where_mysql 行级锁的使用以及死锁的预防
  10. java中字符类型的转换