更多例子

第二个递归的例子是求两个自然数的最大公约数(有没有回到令人怀念的中学时代)。下面的程序用的是经典的辗转相除法。

//greatest common divisor
//假定a、b都是正整数
function gcd(a, b){
if (a < b) return gcd(b, a);//ensure a >= b
var c = a % b;
if (c === 0)
return b;
else
return gcd(b, c);
}

除了上面这些条件或者解法可以转化为数学的递归定义的计算,递归方法还适用于其所涉及的数据结构即是以递归形式定义的问题,比如链表、图、树等等。

现在我们来看一个迷宫的例子。迷宫可以抽象成一副数学上的图,每个岔路口是一个点,其间的路是边。两个特殊的点,分别被定义成入口和出口。

下面是用Javascript定义的点和图。每个点包含一个id作为编号和标志,相邻的点被保存在一个数组中。图有一个添加点的方法,和一个更方便使用的直接添加点的id的方法;还有一个添加边的方法。

//define a vertex
function Vertex(id){
var stem={};
stem.id=id;
stem.adjacent=[];
return stem;
}
//define a graph
function Graph(){
var stem={}, vertices={};
//add vertices to the graph
function add(vertex){
if (vertex instanceof Array){
for (var i=0, v=vertex; i<v.length; i++){
vertices[v[i].id]=v[i];
}
}
vertices[vertex.id]=vertex;
}
//create vertices from ids and add them to the graph
function addIds(ids){
var id;
for (var i=0; i<ids.length; i++){
id=ids[i];
vertices[id]=Vertex(id);
}
}
//create an edge between two vertices
function connect(i1, i2){
var v1=vertices[i1], v2=vertices[i2];
if (v1 && v2){
v1.adjacent.push(v2);
v2.adjacent.push(v1);
}
}
stem.vertices=vertices;
stem.add=add;
stem.addIds=addIds;
stem.connect=connect;
return stem;
}

我们走出迷宫的思路是从入口开始,遍历每个点所有相邻的点,直到找到出口。因为图可能会包含环,也就是在迷宫中会出现兜圈子的情况,所以程序中记录每个到过的点,如果再次遇上,则返回上一个点。如果遇到出口,则退出整个遍历,返回到入口,途中记录经过的每个点,并最终写出从入口到出口的路线。这不是一个最优的办法,得到的结果未必是最短的路线,但是只要入口和出口之间是连通的,就一定可以找到一条路线。

//try to walk out of the maze and print the result
function walkOut(entry, exit){
var visited = [], path = []; function walk(vertex){
if (vertex === exit) {//find the exit
path.push(vertex);
return true;
}
if (visited.indexOf(vertex) > -1) {//the vertex was visited
return false;
}
visited.push(vertex);//remember each vertex
var connected = vertex.adjacent;
var length = connected.length;
if (length === 0) {//the vertex is isolated
return false;
}
for (var i = 0; i < length; i++) {
if (walk(connected[i])) {//try each adjacent vertex
path.push(vertex);
return true;
}
}
} function printPath(){
var footprint = '';
var length = path.length;
for (var i = length - 1; i > -1; i--) {
footprint += path[i].id;
footprint += i === 0 ? '' : ' > ';
}
print(footprint);
} if (walk(entry)) {
printPath();
}
else {
print('出不去!');
}
}

我们可以试验一下这段代码走迷宫的能力。

function testMaze(){
var g=Graph();
g.addIds([1, 2, 3, 4, 5, 6]);
g.connect(1, 2);
g.connect(1, 3);
g.connect(1, 4);
g.connect(2, 3);
g.connect(3, 5); //你可以画出这个图
walkOut(g.vertices[1], g.vertices[5]);//1 > 2 > 3 > 5
walkOut(g.vertices[1], g.vertices[6]);//出不去!
walkOut(g.vertices[2], g.vertices[5]);//2 > 1 > 3 > 5
}

在现实生活中,我们当然也可以用这种笨办法走出任何一个可能走出的迷宫,只要你用笔和便签纸在每一个岔路口记下你选择的路线。

JavaScript的递归之更多例子的更多相关文章

  1. Javascript中递归造成的堆栈溢出及解决方案

    关于堆栈的溢出问题,在Javascript日常开发中很常见,Google了下,相关问题还是比较多的.本文旨在描述如何解决此类问题. 首先看一个实例(当然你可以使用更容易的方式实现,这里我们仅探讨递归) ...

  2. 每天一个JavaScript实例-递归实现反转数组字符串

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. Javascript函数式编程的一些例子[转载]

    函数式编程风格 通常来讲,函数式编程的谓词(关系运算符,如大于,小于,等于的判断等),以及运算(如加减乘数等)都会以函数的形式出现,比如:    a > b通常表示为:    gt(a, b)/ ...

  4. javascript memoization递归优化

    memoize优化递归 function createRec(callback, cache) { cache = cache || []; var rec = function(n) { (n in ...

  5. javascript dom追加内容的例子

    javascript dom追加内容的使用还是比较广泛的,在本文将为大家介绍下具体的使用方法. 例子: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML ...

  6. 前端笔试题目总结——应用JavaScript函数递归打印数组到HTML页面上

    数组如下: var item=[{ name:'Tom', age:70, child:[{ name:'Jerry', age:50, child:[{ name:'William', age:20 ...

  7. [译]Javascript中闭包的各种例子

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  8. 一个javascript继承和使用的例子

    继承可以帮助我们实现代码的重用,把对象的属性写入构造函数,对象的方法写入原型后,以下例子演示继承的使用: 示例的css和js在后 父实例,得到一个间隔1s的轮播: <!DOCTYPE html& ...

  9. JavaScript对象---递归遍历对象

    JavaScript 中的所有事物都是对象:字符串.数值.数组.函数... 此外,JavaScript 允许自定义对象. JavaScript 对象 JavaScript 提供多个内建对象,比如 St ...

随机推荐

  1. win7 不能启动 memcached 总是反回failde to start service

    原地址: http://zhidao.baidu.com/link?url=Ul9hJxFckU9IHWRy0pcxT11f2c0-p2uXkXhLria73mLNxYuV7IiaKYRtIl6vED ...

  2. Python安装模块出错(ImportError: No module named setuptools)解决方法

    原地址:http://www.cnblogs.com/BeginMan/archive/2013/05/28/3104928.html 在window平台下安装第三方模块时,出现这样的错误:

  3. easyui源码翻译1.32--Combo(自定义下拉框)

    前言 扩展自$.fn.validatebox.defaults.使用$.fn.combo.defaults重写默认值对象.下载该插件翻译源码 自定义下拉框显示一个可编辑的文本框和下拉面板在html页面 ...

  4. mysql导出数据库几种方法

    方法一 cmd 到mysql bin目录下用 如下命令 mysqldump --opt -h192.168.0.156 -uusername -ppassword --skip-lock-tables ...

  5. 乐1/MACBOOK/ N1 Type-C接口新体验

    经过在华强北电子市场排队一个小时,笔者顺利买到了期待已久的乐1,结合之前的NOKIA平板电脑N1,苹果全新MACBOOK,终于集齐了手机.平板.笔记本电脑三种TYPE-C接口设备(能兑换极品装备吗?^ ...

  6. velocity-1.7学习笔记

    Velocity是由Apache软件组织提供的一项开放源码项目,它是一个基于Java的模板引擎.通过Velocity模板语言(Velocity Template Language,VTL)定义模板(T ...

  7. 【HDOJ】1241 Oil Deposits

    经典的BFS. #include <stdio.h> #include <string.h> #define MAXNUM 105 #define MAXROW 105 #de ...

  8. 卸载Visual Studio Code后删除右键Open with Code…

    Win+R,输入  regedit  ,点击确认,进入注册表编辑器   Ctrl+F,搜索  Ticino  ,将搜索出来的Ticino都删除就行了

  9. bzoj1976

    终于忙完期末考试了,即将进入愉快的暑假(虽然暑假作业奇多,但好歹终于能有大量时间刷题了) 先把上次新一类最小割留下的一道题目A了复习一下: 题目看起来很复杂,实际上和bzoj2132是同一个类型的 用 ...

  10. PHP 'ext/gd/gd.c'信息泄漏漏洞

    漏洞版本: PHP 5.5.x 漏洞描述: CVE ID:CVE-2014-2020 PHP是一种HTML内嵌式的语言. PHP 'ext/gd/gd.c'没有检查数据类型,允许远程攻击者使用字符串或 ...