1. 程式人生 > 其它 >JS生成隨機雙向圖,利用生成器進行深度遍歷

JS生成隨機雙向圖,利用生成器進行深度遍歷

技術標籤: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

結果:
在這裡插入圖片描述