照例,我們聲明類的骨架:
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 D
B -> A E F
C -> A D G
D -> A C G H
E -> B I
F -> B
G -> C D
H -> D
I -> E
一個漂亮的鄰接表!從該輸出中,我們知道頂點A
有這幾個相鄰頂點:B
、C
和D
。