递归——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 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则 ...
随机推荐
- 运用Unity结合PolicyInjection实现拦截器
运用Unity结合PolicyInjection实现拦截器[结合操作日志实例] 上一篇文章我们通过Unity自身Unity.InterceptionExtension.IInterceptionBeh ...
- GitHub删除文件
删除单个文件 一般情况下,通常可直接在文件管理器中直接把文件删了,或者用rm命令删了 $ rm README.txt 这个时候,工作区是删除了,可版本库还没有.git status命令会立刻告诉你哪些 ...
- IceMx.Mvc 我的js MVC 框架 开篇
开篇 这篇文章是后补的,前端时间想写一些对于js开发的一些理解,就直接写了,后来发现很唐突,所以今天在这里补一个开篇. 我的js Mvc 框架 基于实用设计,过分设计等于没设计.本着简单的原则,它只实 ...
- Ping其他电脑ping不通的解决方法
要想Ping通其他电脑,首先要看被PING的电脑,是否允许PING. 一.在被PING电脑操作系统为XP下分为:1.被PING 电脑关闭了防火墙,就完全可以PING通:2.被PING 电脑开了防火墙, ...
- 分享.net常见的内存泄露及解决方法
分享.net常见的内存泄露及解决方法 关于内存泄漏的问题,之前也为大家介绍过,比如:<C++中内存泄漏的检测方法介绍>,是关于C++内存泄漏的.今天为大家介绍的是关于.NET内存泄漏的问题 ...
- 【Cocos2d-X开发学习笔记】第05期:渲染框架之布景层类(CCLayer)的使用
本系列学习教程使用的是cocos2d-x-2.1.4版本(截至目前为止最新稳定版) ,PC开发环境Windows7,C++开发环境VS2010 图层也是渲染框架中很重要的内容.场景类用来划分游戏的状态 ...
- Android应用中使用AsyncHttpClient来异步网络数据
首先下载AsyncHttpClient的库文件,可以自行搜索,可以到下面地址下载 http://download.csdn.net/detail/xujinyang1234/5767419 测试的Ac ...
- Haskell 笔记(三)类型系统
类型 (Type) Haskell的类型系统式静态类型系统,在编译的时候就知道数据类型,所以不同类型的值运算在编译的时候就会报错,比如用布尔值和整数运算,在C语言中这种运算就不会报错. Haskell ...
- Servle中的会话管理
最近整理了下会话管理的相关笔记,以下做个总结: 一.会话管理(HttpSession) 1.Web服务器跟踪客户状态的四种方法: 1).使用Servlet API的Session机制(常用) 2).使 ...
- js广告轮询效果
var intervalTime = 5000; var showIndex = 0; var imageLength=0; $(window).load(function () { var heig ...