递归——CPS(二)
给出一个计算树深度的函数:
function treeDepth(curtree)
{
if(curtree == null)
return 0;
else
{
var leftDepth = treeDepth(curtree.left);
var rightDepth = treeDepth(curtree.right);
return 1 + Math.max(leftDepth, rightDepth);
}
}
现在要用CPS风格重写这个函数。
避免函数的返回值,而是将返回值传入continuation。记住,continuation就是这个函数完成后需要做的事情。于是写出如下代码
function treeDepth(curtree, afterDepth)
{
if(curtree == null)
afterDepth(0);
else
{
// undone: var leftDepth = treeDepth(curtree.left);
// undone: var rightDepth = treeDepth(curtree.right);
afterDepth(1 + Math.max(leftDepth, rightDepth));
}
}
这里假定加法和求最大值不写成CPS风格,以降低难度。
现在需要组合递归调用。考虑第二个递归调用,嗯,它的continuation是什么?也就是,当右子树的深度确定好了之后需要做哪些事情?两件事,第一,左右子树的深度的最大值需要被计算出来然后加1;第二,需要保证,做完后将会调用continuation。于是,写一个闭包来完成这两件事情。
function treeDepth(curtree, afterDepth)
{
if(curtree == null)
afterDepth(0);
else
{
function afterRight(rightDepth)
{
afterDepth(1+Math.max(leftDepth, rightDepth));
}
// undone: var leftDepth = treeDepth(curtree.left);
treeDepth(curtree.right, afterRight);
}
}
嗯,有进步了。那么,当左子树的深度确定后需要做什么?将左深度传给continuation,这个continuation在右树上面递归来决定右树深度,然后决定两者最大值,然后调用 afterDepth 这个continuation。
function treeDepth(curtree, afterDepth)
{
if(curtree == null)
afterDepth(0);
else
{
function afterLeft(leftDepth)
{
function afterRight(rightDepth)
{
afterDepth(1+Math.max(leftDepth, rightDepth));
}
treeDepth(curtree.right, afterRight);
}
treeDepth(curtree.left, afterLeft);
}
}
原文:https://blogs.msdn.microsoft.com/ericlippert/2005/08/11/recursion-part-five-more-on-cps/
递归——CPS(二)的更多相关文章
- Python学习笔记 之 递归、二维数组顺时针旋转90°、正则表达式
递归.二维数组顺时针旋转90°.正则表达式 1. 递归算法是一种直接或间接调用自身算法的过程. 特点: 递归就是在过程或函数里调用自身 明确的递归结束条件,即递归出口 简洁,但是不提倡 递归次数多 ...
- 递归——CPS(一)
程序中为什么需要栈stack? 普通的程序中,接触到子程序和函数的概念,很直观地,调用子程序时,会首先停止当前做的事情,转而执行被调用的子程序,等子程序执行完成后,再捡起之前挂起的程序,这有可能会使用 ...
- python基础(9)--递归、二叉算法、多维数组、正则表达式
1.递归 在函数内部,可以调其他函数,如果一个函数在内部调用它本身,这个函数就是递归函数.递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于裂解 递归算法解决问题的特点: 1)递归是 ...
- python 基础篇 16 递归和二分数查找与编码补充回顾
编码回顾补充: 回顾编码问题: 编码相当于密码本,关系到二进制与看懂的文字的的对应关系. 最早期的密码本: ascii码:只包含英文字母,数字,特殊字符. ...
- JS递归及二叉搜索树的移除节点
1递归含义:在某时某刻某个条件下调用包含自己的函数 2:注意点:⑴递归过程中一定要加限制条件,要不然会陷入死循环: 死循环eg: function f(someP){ f(somP); } f(4); ...
- 递归——CPS(三)
JScript不是天然支持CPS,但是可以写一个分发引擎使得能工作在CPS风格下.一般只有一个活动的continuation,所以可以定义规则:JScript CPS 函数允许有返回,但是它们做的最后 ...
- PHP递归获取二维数组中指定key的值
$data = [ "resulterrorCode" => 0, "resultraw" => [ "result" => ...
- 数据结构&算法(二)_算法基础之前传(递归、时间复杂度、空间复杂度、二分查找)
什么是算法: 间而言之算法(Algorithm):一个计算过程,解决问题的方法 递归的两个特点: 调用自身 结束条件 递归示例: def func(x): : print("我的小鲤鱼&qu ...
- 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历
二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历 二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则 ...
随机推荐
- DevExpress 学习使用之 ComboBoxEdit
往 StatusBar 上添加各种部件,似乎都被包装成了 barEditItem 的方式,其 Edit 属性就是具体的部件.以 ComboBoxEdit 为例,关于 ComboBoxEdit 的一些设 ...
- Devexpress XtraReports 交叉报表
[原创]Devexpress XtraReports 系列 5 创建交叉报表 昨天我们已经介绍了如何创建多栏报表,详见:[原创]Devexpress XtraReports 系列 4 创建多栏报表 ...
- asp.net mvc4设置area里面使用相同的 Controller 名称并设置area里的页面为起始页
asp.net mvc4设置area里面使用相同的 Controller 名称并设置area里的页面为起始页 1.使用重名controller 在asp.net mvc2以后的版本里面,有了area( ...
- 大数据应用之Windows平台Hbase客户端Eclipse开发环境搭建
大数据应用之Windows平台Hbase客户端Eclipse开发环境搭建 大数据应用之Windows平台Hbase客户端Eclipse环境搭建-Java版 作者:张子良 版权所有,转载请注明出处 引子 ...
- Class.forName不能加载abstract原因
今天看到单例模式时,突然想起,单例模式的情况是不让其他类来构造这个类本身,也就是不让new构造器,所以我们一般都会私有化这个构造器.我们知道abstract类是不能实例化的,我想利用abstract这 ...
- hdu 1217
判断通过货币的兑换能否获利,,最短路,这里是乘法,, #include<stdio.h> #include<string.h> double map[31][31],ans[3 ...
- Java入门第二季第一章类和对象知识点
Java 中的 static 使用之静态方法 1. 静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员.如: 如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问 ...
- vue组件,撸第一个
实现此例您可以学到: vue-cli的基本应用 父组件如何向子组件传递值 单文件组件如何引入scss v-on和v-for的基础应用 源码下载 一.搭建vue开发环境 更换镜像到cnpmnpm ins ...
- 700多个PHP版本随时切换,PHPWAMP共生模式与多档位综合教程。
最近有学生向我咨询如何同时建立多个不同PHP版本站点,并自定义任意版本,软件是否可以多开,PHPWAMP如何设置才能与其他的环境同时使用等问题,本文将一一解决. 简单介绍一下PHPWAMP 你们应该会 ...
- rabbitMQ 安装 could not set correct interactive mode
安装rabbit mq 提示下面错误 其他信息: 执行错误:C:\Program Files\erl6.0\erts-6.0\bin\erlsrv: Warning, could not set co ...