`
从此醉
  • 浏览: 1046568 次
  • 性别: Icon_minigender_1
  • 来自: US
社区版块
存档分类
最新评论

JavaScript的递归之更多例子

 
阅读更多

更多例子

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

//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-things:JavaScript代码示例

    JavaScript事物 该存储库包含JavaScript代码示例。 剧本 功能编程 筛选,映射,减少,关闭,组成,承诺,蹦床,递归 面向对象编程 类,继承,组成 API调用,JSON,提取,Axios ... 请参阅以获取更多信息。

    《JavaScript语言精粹[修订版]》高清版_2012.09_【蝴蝶书】_172页完整版

     JavaScript 曾是“世界上误解的语言”,因为它担负太多的特性,包括糟糕的交互和失败的设计,但随着Ajax 的到来,JavaScript“从受误解的编程语言演变为非常流行的语言”,这除了幸运之外,也证明了它其实是一门...

    lindenmayer-power:使用Lindenmayer系统的3D植物生成器

    Lindenmayer力量 基于植物/递归结构生成器。 使用 , 和 计划功能: 更多例子 更多文档 更多重构 更多测试 适当的词法分析器

    quick-dp:快速使用动态编程

    在这两种情况下,它都是指通过以递归方式将其分解为更简单的子问题来简化一个复杂的问题。 尽管无法以这种方式解决某些决策问题,但跨越多个时间点的决策通常会递归分解。 同样,在计算机科学中,可以通过将其分解...

    正则表达式30分钟入门教程

    下面来看看更多的例子: \ba\w*\b匹配以字母a开头的单词——先是某个单词开始处(\b),然后是字母a,然后是任意数量的字母或数字(\w*),最后是单词结束处(\b)。 好吧,现在我们说说正则表达式里的单词是什么意思吧:...

    DWR.xml配置文件说明书(含源码)

    这里仅仅是定义了Converter并且简单的放在….&gt;元素之内,任何的….&gt;元素内容都有两个必须定义的属性.一个是对converter定义的引用和converter能够转换的类. 例如最简单的converter是null converter,它作用是把null和...

    PHP3程序设计

    尤其值得注意的是,书中使用了多个“中场”章节,以便在学习过一定知识之后,通过实际例子来对所学的知识进行巩固,这些章节介绍的内容具有很强的实用价值。因此本书不仅对Web编程的入门者,即使对于有一定经验的Web...

    java源码包---java 源码 大量 实例

    JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML浏览器...

    JAVA上百实例源码以及开源项目

    JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML浏览器...

    JAVA上百实例源码以及开源项目源代码

    JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML浏览器...

    java源码包2

    JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML...

    java源码包3

    JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML...

    java源码包4

    JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    递归遍历矩阵 1个目标文件,简单! 多人聊天室 3个目标文件 第一步:运行ServerData.java 启动服务器,然后服务器处于等待状态 第二步:运行LoginData.java 启动(客户端)登陆界面 输入用户名 ip为本机localhost 第...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    递归遍历矩阵 1个目标文件,简单! 多人聊天室 3个目标文件 第一步:运行ServerData.java 启动服务器,然后服务器处于等待状态 第二步:运行LoginData.java 启动(客户端)登陆界面 输入用户名 ip为本机localhost 第...

    PHP和MySQL WEB开发(第4版)

    12.3 获取更多关于数据库的信息 12.3.1 使用SHOW获取信息 12.3.2 使用DESCRIBE获取关于列的信息 12.3.3 用EXPLAIN理解查询操作的工作过程 12.4 数据库的优化 12.4.1 设计优化 12.4.2 权限 12.4.3 表的优化 12.4.4 ...

    PHP和MySQL Web开发第4版pdf以及源码

    12.3 获取更多关于数据库的信息 12.3.1 使用SHOW获取信息 12.3.2 使用DESCRIBE获取关于列的信息 12.3.3 用EXPLAIN理解查询操作的工作过程 12.4 数据库的优化 12.4.1 设计优化 12.4.2 权限 12.4.3 表的优化 ...

    PHP和MySQL Web开发第4版

    12.3 获取更多关于数据库的信息 12.3.1 使用SHOW获取信息 12.3.2 使用DESCRIBE获取关于列的信息 12.3.3 用EXPLAIN理解查询操作的工作过程 12.4 数据库的优化 12.4.1 设计优化 12.4.2 权限 12.4.3 表的优化 ...

Global site tag (gtag.js) - Google Analytics