更多例子

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

//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. Python PIL库之Image注解(API)

    http://blog.csdn.net/xiezhiyong3621/article/details/8499543 class Image Methods defined here: __geta ...

  2. ZOJ 2750 Idiomatic Phrases Game(Dijkstra)

    点我看题目 题意 : 给定一本字典,字典里有很多成语,要求从字典里的第一个成语开始,运用字典里的成语变到最后一个成语,变得过程就是成语接龙,后一个成语的第一个字必须有前一个成语的最后一个字相等,给定的 ...

  3. Spring 配置XML文件头部文件格式

    普通格式: <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns:xsi="ht ...

  4. CAN

    CAN Introduction Features Network Topology(CANbus網路架構) MESSAGE TRANSFER(CAN通訊的資料格式) 1.DATA FRAME(資料通 ...

  5. Django中的Model继承

    Django 中的 model 继承和 Python 中的类继承非常相似,只不过你要选择具体的实现方式:让父 model 拥有独立的数据库:还是让父 model 只包含基本的公共信息,而这些信息只能由 ...

  6. vs2010+ Ankhsvn使用详解

    1.为什么要用VisualSVN Server,而不用Subversion? 回答: 因为如果直接使用Subversion,那么在Windows 系统上,要想让它随系统启动,就要封装SVN Serve ...

  7. simplified build configuration

    http://blogs.msdn.com/b/saraford/archive/2005/08/16/452411.aspx Did you know… That you can hide the ...

  8. Heartbeat+DRBD+NFS 构建高可用的文件系统

    1.实验拓扑图 2.修改主机名 1 2 3 vim /etc/sysconfig/network vim /etc/hosts drbd1.free.com     drbd2.free.com 3. ...

  9. POJ1699Best Sequence(DFS)

    链接 这题其实是由bug的 一个串包含其它两个串的数据没有 所以就这么水了它吧 只处理两个串的关系就行了 回来补点..看了huge的博客 发现其实不是有Bug  题意没读清楚 必须首尾相连 像AGCT ...

  10. BZOJ_1026_[SCOI2009]_windy数_(数位dp)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1026 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为wi ...