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 相关文章推荐
javascript编程起步(第六课)
Feb 27 Javascript
JQUERY操作JSON实例代码
Feb 09 Javascript
实例讲解JS中数组Array的操作方法
May 09 Javascript
javascript:void(0)点击登录没反应怎么解决
Nov 13 Javascript
基于jQuery实现左右图片轮播(原理通用)
Dec 24 Javascript
jQuery 如何给Carousel插件添加新的功能
Apr 18 Javascript
jQuery基础知识点总结(DOM操作)
Jun 01 Javascript
基于JS+Canves实现点击按钮水波纹效果
Sep 15 Javascript
Vue.js 2.0窥探之Virtual DOM到底是什么?
Feb 10 Javascript
React中常见的动画实现的几种方式
Jan 10 Javascript
Node Puppeteer图像识别实现百度指数爬虫的示例
Feb 22 Javascript
微信小程序实现一张或多张图片上传(云开发)
Sep 25 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的Yii框架中扩展的安装与使用
2016/04/01 PHP
PHP获取IP地址所在地信息的实例(使用纯真IP数据库qqwry.dat)
2016/11/15 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
2017/07/20 PHP
PhpStorm本地断点调试的方法步骤
2018/05/21 PHP
JS应用之禁止抓屏、复制、打印
2008/02/21 Javascript
Js,alert出现乱码问题的解决方法
2013/06/19 Javascript
JavaScript将数据转换成整数的方法
2014/01/04 Javascript
jquery使用append(content)方法注意事项分享
2014/01/06 Javascript
JS对文本框值的判断示例
2014/03/10 Javascript
JavaScript中最简洁的编码html字符串的方法
2014/10/11 Javascript
快速学习AngularJs HTTP响应拦截器
2015/12/31 Javascript
javascript中replace使用方法总结
2017/03/01 Javascript
JS+canvas绘制的动态机械表动画效果
2017/09/12 Javascript
Vue+ElementUI实现表单动态渲染、可视化配置的方法
2018/03/07 Javascript
微信小程序 swiper 组件遇到的问题及解决方法
2019/05/26 Javascript
使用Vue 实现滑动验证码功能
2019/06/27 Javascript
小程序Scroll-view上拉滚动刷新数据
2020/06/21 Javascript
vue如何在项目中调用腾讯云的滑动验证码
2020/07/15 Javascript
[01:08:00]Fnatic vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python正则表达式判断字符串是否是全部小写示例
2013/12/25 Python
python中偏函数partial用法实例分析
2015/07/08 Python
Python中字符串的格式化方法小结
2016/05/03 Python
python利用MethodType绑定方法到类示例代码
2017/08/27 Python
Python数据分析之双色球统计两个红和蓝球哪组合比例高的方法
2018/02/03 Python
解决python爬虫中有中文的url问题
2018/05/11 Python
详解Python3的TFTP文件传输
2018/06/26 Python
python 将对象设置为可迭代的两种实现方法
2019/01/21 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
2019/08/07 Python
python中open函数的基本用法示例
2019/09/07 Python
python调用c++返回带成员指针的类指针实例
2019/12/12 Python
Jupyter notebook设置背景主题,字体大小及自动补全代码的操作
2020/04/13 Python
关于python的缩进规则的知识点详解
2020/06/22 Python
Pycharm Git 设置方法
2020/09/15 Python
公文写作:新员工转正申请书范本3篇!
2019/08/07 职场文书
redis客户端实现高可用读写分离的方式详解
2021/07/04 Redis
三种方式清除vue路由跳转router-link的历史记录
2022/04/10 Vue.js