今天晚上无心翻到一个图的文章,查了一下感受网上实现和其余都好复杂,因此本身按理解搞了一下,不知道是我实现是否是错了...感受还好~进入正题,先仍是来点理论知识,不过大可能是本身的想法,不必定都对,能够纠正。内容来源来自《JavaScript 数据结构和算法》。javascript
图是一种数学模型,和数学挂勾通常都会比较复杂,因此形象的理解成最简单的模型,点-线 模型。其实最简单的是 1 个点的模型,涉及 2 个点还好,3 个点事后模型就会做出相应的改变。java
这里用简单的语言来讲图中的二元关系,不过仍是先假设一点数学符号:node
G => 表示全部的顶点集合算法
V => 表示顶点数据库
E => 表示边,抽象意义上是无向边数据结构
那么用数学来表示就是:G=<V, E>数据结构和算法
其实根本不用理解数学的模型,我这里理解是只须要知道这是一个点-线模型就能够了。函数
这里有两种表示方法:表和矩阵,其间都是邻接关系工具
这里我有一个测试图,在网上弄的,虽然是无向图,其实在咱们代码中,确定是有向的,是入口的问题:测试
图的结构肯定事后,就能够作出表的结构了,这里我没有用方向,由于我理解的图是一个不能简单表示的,理解成坐标系更好理解一点。分为:x, y 轴的方式。其中,x0 表示开始,后面表示相邻的点,按顺时针排列(不必定按这个顺序)。
在代码中表示,没有图形那么直观,因此须要映射成代码模型,这里简单实现一下,可是不具有不少功能。
假设:
class G => 一个图的类,包括图的定义和经常使用遍历方法
this.V => 表示点集合的个数,可是这里我舍弃了 0 的位置
this.T => 我按数据库表的方式理解命名的,关系的集合
this.E => 边的个数
this.visited => 访问过的 bool 集合,其实就是标记
this.defined => 工具小函数,是否认义过,与图无关
因此最后有关的符号有:
G、V、T、E
是否是感受一会儿变简单了,不过程序的抽象有一个上层,那就是类。
而后我这里按计算机的方式,定义了输入、输出函数:input、output
class G { constructor(V) { this.V = V; this.T = []; this.E = 0; this.visited = []; for (let v = 0; v < this.V; ++v) { this.T[v] = []; this.T[v].push(-1); } this.defined = s => s !== void 0; } input(v, w) { this.T[v].push(w); this.T[w].push(v); this.E++; return this; } output() { console.table(this.T); } }
而后可以看出,其实边是由点的链接组成的,恰好符合数学的定义,而且与相邻有相关性。
那么,实现告终构,还应该有其余做用,那么接下来看一下遍历算法:深度遍历(DFS) 和 广度遍历(BFS)。准确来讲应该是优先采用什么策略的遍历方式。其实我这里的实现感受...很差,和树关系大了点,不过树的大集合就可以上升到图。
dfs(v) { this.visited[v] = true; if (this.defined( this.T[v] )) { console.log('老孙到此一游:' + v); } this.T[v].forEach(t => { if (t !== -1 && !this.visited[t]) { this.dfs(t); } }); }
对于深度遍历,是将图按一个固定方向,纵向的结果,因此是一个递归的结构。
bfs(node) { this.visited[node] = true; var queue = []; queue.push(node); while(queue.length > 0) { var v = queue.shift(); if(this.defined( this.T[v] )) { console.log('老孙到此一游:' + v); } this.T[v].forEach(t => { if(t !== -1 && !this.visited[t]) { this.visited[t] = true; queue.push(t); } }); } }
对于广度遍历,是将图按一个固定方向,横向的结果,因此是一个链式进出的关系,这里是用队列,在 JS 中作队列这种先进先出比较简单。
// 测试代码 var v = [1, 2, 3, 4, 5]; let g = new G( v.length + 1 ); g.input(1, 2).input(1, 5) .input(2, 4).input(2, 5).input(2, 3) .input(3, 4) .input(4, 5) .output(); g.dfs(1); console.log('------------'); // 让它失忆一下 g.visited = []; g.bfs(1);
……-_-# 简单玩一下,睡觉了 zZZ