JavaScript数据结构和算法之图和图算法


Posted in Javascript onFebruary 11, 2015

图的定义

图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。

有向图

JavaScript数据结构和算法之图和图算法

有向边:若从顶点Vi到Vj的边有方向,则称这条边为有向边,也成为弧(Arc),用有序偶<Vi,Vj>来表示,Vi称为弧尾,Vj称为弧头。

无序图

JavaScript数据结构和算法之图和图算法

无向边:若顶点Vi到Vj之间的边没有方向,则称这条边为无向边(Edge),用无序偶(Vi,Vj)来表示。

简单图

简单图:在图结构中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。

图类

表示顶点

创建图类的第一步就是要创建一个Vertex类来保存顶点和边。这个类的作用和链表、二叉搜索树的Node类一样。Vertex类有两个数据成员:一个用于标识顶点,另一个表明是否被访问过的布尔值。分别被命名为label和wasVisited。

function Vertex(label){

    this.label = label;

}

我们将所有顶点保存在数组中,在图类里,可以通过他们在数组中的位置引用他们

表示边

图的实际信息都保存在“边”上面,因为他们描述了图的结构。二叉树的一个父节点只能有两个子节点,而图的结构却要灵活得多,一个顶点既可以有一条边,也可以有多条边和它相连。

我们将表示图的边的方法成为邻接表或者邻接表数组。它将存储由顶点的相邻顶点列表构成的数组

构建图

定义如下一个Graph类:

function Graph(v){

    this.vertices = v;//vertices至高点

    this.edges = 0;

    this.adj = [];

    for(var i =0;I<this.vertices;++i){

        this.adj[i] = [];

        this.adj[i].push('');

    }

    this.addEdge = addEdge;

    this.toString = toString;

}

这个类会记录一个图表示了多少条边,并使用一个长度与图的顶点数来记录顶点的数量。
function addEdge(){

    this.adj[v].push(w);

    this.adj[w].push(v);

    this.edges++;

}

这里我们使用for循环为数组中的每个元素添加一个子数组来存储所有的相邻顶点,并将所有元素初始化为空字符串。

图的遍历

深度优先遍历

深度优先遍历(DepthFirstSearch),也有称为深度优先搜索,简称为DFS。

比如在一个房间内寻找一把钥匙,无论从哪一间房间开始都可以,将房间内的墙角、床头柜、床上、床下、衣柜、电视柜等挨个寻找,做到不放过任何一个死角,当所有的抽屉、储藏柜中全部都找遍后,接着再寻找下一个房间。

深度优先搜索:

JavaScript数据结构和算法之图和图算法

深度优先搜索就是访问一个没有访问过的顶点,将他标记为已访问,再递归地去访问在初始顶点的邻接表中其他没有访问过的顶点

为Graph类添加一个数组:

this.marked = [];//保存已访问过的顶点

for(var i=0;i<this.vertices;++i){

    this.marked[i] = false;//初始化为false

}

深度优先搜索函数:

function dfs(v){

    this.marked[v] = true;

    //if语句在这里不是必须的

    if(this.adj[v] != undefined){

        print("Visited vertex: " + v );

        for each(var w in this.adj[v]){

            if(!this.marked[w]){

                this.dfs(w);

            }

        }

    }

}

广度优先搜索

广度优先搜索(BFS)属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

广度优先搜索从第一个顶点开始,尝试访问尽可能靠近它的顶点,如下图所示:

JavaScript数据结构和算法之图和图算法

其工作原理为:

 1. 首先查找与当前顶点相邻的未访问的顶点,将其添加到已访问顶点列表及队列中;
 2. 然后从图中取出下一个顶点v,添加到已访问的顶点列表
 3. 最后将所有与v相邻的未访问顶点添加到队列中
下面是广度优先搜索函数的定义:

function bfs(s){

    var queue = [];

    this.marked = true;

    queue.push(s);//添加到队尾

    while(queue.length>0){

        var v = queue.shift();//从队首移除

        if(v == undefined){

            print("Visited vertex: " + v);

        }

        for each(var w in this.adj[v]){

            if(!this.marked[w]){

                this.edgeTo[w] = v;

                this.marked[w] = true;

                queue.push(w);

            }

        }

    }

}

JavaScript数据结构和算法之图和图算法

最短路径

在执行广度优先搜索时,会自动查找从一个顶点到另一个相连顶点的最短路径

确定路径

要查找最短路径,需要修改广度优先搜索算法来记录从一个顶点到另一个顶点的路径,我们需要一个数组来保存从一个顶点操下一个顶点的所有边,我们将这个数组命名为edgeTo

this.edgeTo = [];//将这行添加到Graph类中
//bfs函数

function bfs(s){

    var queue = [];

    this.marked = true;

    queue.push(s);//添加到队尾

    while(queue.length>0){

        var v = queue.shift();//从队首移除

        if(v == undefined){

            print("Visited vertex: " + v);

        }

        for each(var w in this.adj[v]){

            if(!this.marked[w]){

                this.edgeTo[w] = v;

                this.marked[w] = true;

                queue.push(w);

            }

        }

    }

}

拓扑排序算法

拓扑排序会对有向图的所有顶点进行排序,使有向边从前面的顶点指向后面的顶点。
拓扑排序算法与BFS类似,不同的是,拓扑排序算法不会立即输出已访问的顶点,而是访问当前顶点邻接表中的所有相邻顶点,直到这个列表穷尽时,才会将当前顶点压入栈中。

拓扑排序算法被拆分为两个函数,第一个函数是topSort(),用来设置排序进程并调用一个辅助函数topSortHelper(),然后显示排序好的顶点列表

拓扑排序算法主要工作是在递归函数topSortHelper()中完成的,这个函数会将当前顶点标记为已访问,然后递归访问当前顶点邻接表中的每个顶点,标记这些顶点为已访问。最后,将当前顶点压入栈中。

//topSort()函数

function topSort(){

    var stack = [];

    var visited = [];

    for(var i =0;i<this.vertices;i++){

        visited[i] = false;

    }

    for(var i = 0;i<this.vertices;i++){

        if(visited[i] == false){

            this.topSortHelper(i,visited,stack);

        }

    }

    for(var i = 0;i<stack.length;i++){

        if(stack[i] !=undefined && stack[i] != false){

            print(this.vertexList[stack[i]]);

        }

    }

}
//topSortHelper()函数

function topSortHelper(v,visited,stack){

    visited[v] = true;

    for each(var w in this.adj[v]){

        if(!visited[w]){

            this.topSortHelper(visited[w],visited,stack);

        }

    }

    stack.push(v);

}
Javascript 相关文章推荐
【消息提示组件】,兼容IE6/7&amp;&amp;FF2
Sep 04 Javascript
JavaScript中的Window窗口对象
Jan 16 Javascript
Javascript 日期对象Date扩展方法
May 30 Javascript
js 鼠标点击事件及其它捕获
Jun 04 Javascript
asp知识整理笔记3(问答模式)
Sep 27 Javascript
JavaScript几种数组去掉重复值的方法推荐
Apr 12 Javascript
JS Attribute属性操作详解
May 19 Javascript
JavaScript基础教程——入门必看篇
May 20 Javascript
总结Javascript中数组各种去重的方法
Oct 04 Javascript
基于vue cli 通过命令行传参实现多环境配置
Jul 12 Javascript
javascript浅层克隆、深度克隆对比及实例解析
Feb 09 Javascript
微信小程序对图片进行canvas压缩的方法示例详解
Nov 12 Javascript
Javascript核心读书有感之类型、值和变量
Feb 11 #Javascript
JavaScript中的继承方式详解
Feb 11 #Javascript
JavaScript中原型和原型链详解
Feb 11 #Javascript
Node.js中的缓冲与流模块详细介绍
Feb 11 #Javascript
javascript中var的重要性分析
Feb 11 #Javascript
JavaScript设计模式之工厂模式和构造器模式
Feb 11 #Javascript
js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
Feb 11 #Javascript
You might like
PHP教程之PHP中shell脚本的使用方法分享
2012/02/23 PHP
IIS安装Apache伪静态插件的具体操作图文
2013/07/01 PHP
thinkphp 一个页面使用2次分页的实现方法
2013/07/15 PHP
php calender(日历)二个版本代码示例(解决2038问题)
2013/12/24 PHP
js+php实现静态页面实时调用用户登陆状态的方法
2015/01/04 PHP
Laravel 5框架学习之表单
2015/04/08 PHP
PHP实现根据银行卡号判断银行
2015/04/29 PHP
php函数重载的替代方法--伪重载详解
2015/05/08 PHP
PHP简单读取PDF页数的实现方法
2016/07/21 PHP
通过修改Laravel Auth使用salt和password进行认证用户详解
2017/08/17 PHP
PHP中十六进制颜色与RGB颜色值互转的方法
2019/03/18 PHP
jquery表单验证使用插件formValidator
2012/11/10 Javascript
jQuery实现点击标题输入详细信息
2013/04/16 Javascript
js调试系列 源码定位与调试[基础篇]
2014/06/18 Javascript
js使用html()或text()方法获取设置p标签的显示的值
2014/08/01 Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
2016/07/06 Javascript
bootstrap datetimepicker控件位置异常的解决方法
2017/11/23 Javascript
Vue自定义指令实现checkbox全选功能的方法
2018/02/28 Javascript
让你5分钟掌握9个JavaScript小技巧
2018/06/09 Javascript
详解vue-router传参的两种方式
2018/09/10 Javascript
vue打包通过image-webpack-loader插件对图片压缩优化操作
2020/11/12 Javascript
[01:05:40]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第三场
2014/05/24 DOTA
跟老齐学Python之坑爹的字符编码
2014/09/28 Python
详解Django+Uwsgi+Nginx 实现生产环境部署
2018/11/06 Python
Python使用Selenium爬取淘宝异步加载的数据方法
2018/12/17 Python
django settings.py 配置文件及介绍
2019/07/15 Python
基于多进程中APScheduler重复运行的解决方法
2019/07/22 Python
利用Python的sympy包求解一元三次方程示例
2019/11/22 Python
皇家阿尔伯特瓷器美国官网:Royal Albert美国
2020/02/16 全球购物
库房主管岗位职责
2013/12/31 职场文书
工程技术员岗位职责
2014/03/02 职场文书
我们的节日元宵活动方案
2014/08/23 职场文书
2014物价局民主生活会对照检查材料思想汇报
2014/09/24 职场文书
党员个人党性分析材料
2014/12/18 职场文书
学校通报表扬范文
2015/05/04 职场文书
MySQL千万级数据表的优化实战记录
2021/08/04 MySQL