JS生成隨機雙向圖,利用生成器進行深度遍歷
阿新 • • 發佈:2021-02-17
技術標籤:JS前端javascript前端
目錄:
文章目錄
前言
本文取自《JavaScript高階程式設計》(第4版)第7章
- 內容主體為生成器,因此用生成器遞迴的迭代器對圖進行深度遍歷
- 適合深入瞭解生成器
內容講解
1. 用類模擬結構體
由於JS
中無法像C
定義結構體,如何實現結構體功能就成了一個問題。
在研究JS
面向物件的特性後,發現可以用constructor
的構造器函式進行模擬,並在這個基礎上可以封裝一個連線方法,用來增加結點的連通性
2. 隨機的雙向圖
- 為了體現遞迴生成器的方便,在圖的類宣告時,就自動建立好隨機雙向圖
- 新增2個方法,分別用於列印輸出圖的內容和深度優先遍歷,檢視圖是否連通
程式碼實現
以下為原始碼:
class Node {
constructor(id) {
this.id = id;
this.neighbors = new Set();
}
connect(node) {
if(node !== this){
this.neighbors.add(node);
node.neighbors.add(this);
}
}
}
class RandomGraph {
constructor(size) {
this.nodes = new Set();
// 建立結點
for(let i = 0; i < size; ++ i) this.nodes.add(new Node(i));
// 隨機連線結點
const threshold = 1 / size;
for(const x of this.nodes) {
for(const y of this.nodes){
if(Math.random () < threshold){
x.connect(y);
}
}
}
}
// 這個方法用於除錯
print() {
for(const node of this.nodes){
const ids = [...node.neighbors]
.map(n => n.id)
.join(',');
console.log(`${node.id}: ${ids}`);
}
}
// 深度優先遍歷
isConnected() {
const visitedNodes = new Set();
function* traverse(nodes) {
for(const node of nodes ) {
if(!visitedNodes.has(node)){
yield node;
yield* traverse(node.neighbors);
}
}
}
// 取得集合中的第一個結點
const firstNode = this.nodes[Symbol.iterator]().next().value;
// 使用遞迴生成器迭代每個結點,並放入Set裡
for (const node of traverse([firstNode])) {
visitedNodes.add(node);
}
return visitedNodes.size === this.nodes.size;
}
}
const g = new RandomGraph(6);
// 遍歷列印
g.print();
// 檢查是否連通
console.log(g.isConnected());
// 0: 2,5
// 1: 5,4
// 2: 0
// 3: 5,4
// 4: 1,3,5
// 5: 1,3,0,4
// true
結果: