照例,我们声明类的骨架:
function Graph { var vertices = ; //{1} var adjList = new Dictionary; //{2}}
我们使用一个数组来存储图中所有顶点的名字(行{1}
),以及一个字典(在第7章中已经实现)来存储邻接表(行{2}
)。字典将会使用顶点的名字作为键,邻接顶点列表作为值。vertices
数组和adjList
字典两者都是我们Graph
类的私有属性。
接着,我们将实现两个方法:一个用来向图中添加一个新的顶点(因为图实例化后是空的),另外一个方法用来添加顶点之间的边。我们先实现addVertex
方法:
this.addVertex = function(v){ vertices.push(v); //{3} adjList.set(v, ); //{4}};
这个方法接受顶点v
作为参数。我们将该顶点添加到顶点列表中(行{3}
),并且在邻接表中,设置顶点v
作为键对应的字典值为一个空数组(行{4}
)。
现在,我们来实现addEdge
方法:
this.addEdge = function(v, w){ adjList.get(v).push(w); //{5} adjList.get(w).push(v); //{6}};
这个方法接受两个顶点作为参数。首先,通过将w
加入到v
的邻接表中,我们添加了一条自顶点v
到顶点w
的边。如果你想实现一个有向图,则行{5}
就足够了。由于本章中大多数的例子都是基于无向图的,我们需要添加一条自w
向v
的边(行{6}
)。
请注意我们只是往数组里新增元素,因为数组已经在行
{4}
被初始化了。
让我们测试这段代码:
var graph = new Graph;var myVertices = ['A','B','C','D','E','F','G','H','I']; //{7}for (var i=0; i<myVertices.length; i++){ //{8} graph.addVertex(myVertices[i]);}graph.addEdge('A', 'B'); //{9}graph.addEdge('A', 'C');graph.addEdge('A', 'D');graph.addEdge('C', 'D');graph.addEdge('C', 'G');graph.addEdge('D', 'G');graph.addEdge('D', 'H');graph.addEdge('B', 'E');graph.addEdge('B', 'F');graph.addEdge('E', 'I');
为方便起见,我们创建了一个数组,包含所有我们想添加到图中的顶点(行{7}
)。接下来,我们只要遍历vertices
数组并将其中的值逐一添加到我们的图中(行{8}
)。最后,我们添加想要的边(行{9}
)。这段代码将会创建一个图,也就是到目前为止本章的示意图所使用的。
为了更方便一些,让我们来实现一下Graph
类的toString
方法,以便于在控制台输出图。
this.toString = function{ var s = ''; for (var i=0; i<vertices.length; i++){ //{10} s += vertices[i] + ' -> '; var neighbors = adjList.get(vertices[i]); //{11} for (var j=0; j<neighbors.length; j++){ //{12} s += neighbors[j] + ' '; } s += '/n'; //{13} } return s;};
我们为邻接表表示法构建了一个字符串。首先,迭代vertices
数组列表(行{10}
),将顶点的名字加入字符串中。接着,取得该顶点的邻接表(行{11}
),同样也迭代该邻接表(行{12}
),将相邻顶点加入我们的字符串。邻接表迭代完成后,给我们的字符串添加一个换行符(行{13}
),这样就可以在控制台看到一个漂亮的输出了。运行如下代码:
console.log(graph.toString);
输出如下:
A -> B C DB -> A E FC -> A D GD -> A C G HE -> B IF -> BG -> C DH -> DI -> E
一个漂亮的邻接表!从该输出中,我们知道顶点A
有这几个相邻顶点:B
、C
和D
。