JavaScript 中圖的實現
圖是一種非線性資料結構,表示一組頂點(也稱為節點)以及它們之間的關係(或邊)。頂點表示實體或對象,而邊表示頂點之間的關係或連結。圖可用於對許多不同類型的關係進行建模,例如社交網路、交通系統或資訊流。
圖有兩種主要類型:有向圖(也稱為有向圖)和無向圖。在有向圖中,邊有一個方向,並且只能在一個方向上遍歷,即從起始頂點到結束頂點。在無向圖中,邊沒有方向,可以在兩個方向遍歷。
JavaScript 中圖的實作
圖可以使用鄰接矩陣或鄰接列表來實現。在這裡,我們將使用鄰接列表在 JavaScript 中實作圖形。
建立圖表類別
這裡我們創建了圖形類別的藍圖。
class Graph { constructor() { this.adjacencyList = {}; } }
新增頂點
該函數透過在 adjacencyList 物件中建立一個新鍵並將空數組作為其值來為圖中新增一個頂點(或節點)。新頂點將作為鍵,空數組將用於儲存其鄰居。
addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; }
新增邊緣
此函數在兩個頂點之間新增一條新邊。它接受兩個參數:vertex1 和 vertex2,並將 vertex2 加到 vertex1 的鄰居陣列中,反之亦然。這會在兩個頂點之間建立連接。
addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); }
列印圖表
此函數將圖表記錄到控制台。它迭代 adjacencyList 物件中的每個頂點並記錄該頂點及其鄰居。
print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } }
範例
在下面的範例中,我們定義一個圖表並向該圖添加頂點和邊。最後列印圖表。
class Graph { constructor() { this.adjacencyList = {}; } addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; } addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); } print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } } } const graph = new Graph(); graph.addVertex("A"); graph.addVertex("B"); graph.addVertex("C"); graph.addVertex("D"); graph.addEdge("A", "B"); graph.addEdge("A", "C"); graph.addEdge("B", "D"); graph.addEdge("C", "D"); console.log("Graph:"); graph.print();
輸出
Graph: A -> B, C B -> A, D C -> A, D D -> B, C
刪除邊
此函數刪除兩個頂點之間的邊。它接受兩個參數:vertex1 和 vertex2,並從 vertex1 的鄰居陣列中過濾掉 vertex2,反之亦然。
removeEdge(vertex1, vertex2) { this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter( (v) => v !== vertex2 ); this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter( (v) => v !== vertex1 ); }
刪除頂點
此函數從圖中刪除一個頂點。它接受一個頂點參數,並首先刪除連接到該頂點的所有邊。然後,它從 adjacencyList 物件中刪除該鍵。
removeVertex(vertex) { while (this.adjacencyList[vertex].length) { const adjacentVertex = this.adjacencyList[vertex].pop(); this.removeEdge(vertex, adjacentVertex); } delete this.adjacencyList[vertex]; }
範例
在下面的範例中,我們定義一個圖並新增頂點和邊,然後列印該圖。我們從圖中刪除一邊 AC,最後列印結果圖。
class Graph { constructor() { this.adjacencyList = {}; } addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; } addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); } removeEdge(vertex1, vertex2) { this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter( (v) => v !== vertex2 ); this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter( (v) => v !== vertex1 ); } removeVertex(vertex) { while (this.adjacencyList[vertex].length) { const adjacentVertex = this.adjacencyList[vertex].pop(); this.removeEdge(vertex, adjacentVertex); } delete this.adjacencyList[vertex]; } print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } } } const graph = new Graph(); graph.addVertex("A"); graph.addVertex("B"); graph.addVertex("C"); graph.addVertex("D"); graph.addEdge("A", "B"); graph.addEdge("A", "C"); graph.addEdge("B", "D"); graph.addEdge("C", "D"); console.log("Initial Graph:"); graph.print(); console.log("Graph after removal of edge AC:") graph.removeEdge("A","C"); graph.print();
輸出
Initial Graph: A -> B, C B -> A, D C -> A, D D -> B, C Graph after removal of edge AC: A -> B B -> A, D C -> D D -> B, C
圖的遍歷方法
圖遍歷是指訪問圖的所有頂點(或節點)並處理與其關聯的資訊的過程。圖遍歷是圖演算法中的重要操作,用於尋找兩個節點之間的最短路徑、偵測迴路、尋找連通分量等任務。
圖遍歷主要有兩種方法:廣度優先搜尋(BFS)和深度優先搜尋(DFS)
A.廣度優先搜尋(BFS)
它是使用breadthFirstSearch()函數實現的。此函數實作廣度優先搜尋演算法並採用 start 參數,即起始頂點。它使用佇列來追蹤要存取的頂點,使用結果陣列來儲存存取過的頂點,並使用存取物件來追蹤已經存取過的頂點。此函數首先將起始頂點新增至佇列並將其標記為已存取。然後,當佇列不為空時,它會從佇列中取出第一個頂點,將其新增至結果陣列中,並將其標記為已存取。然後它將所有未訪問的鄰居添加到隊列中。這個過程一直持續到所有頂點都被訪問過,並且結果數組作為 BFS 的結果返回。
breadthFirstSearch(start) { const queue = [start]; const result = []; const visited = {}; let currentVertex; visited[start] = true; while (queue.length) { currentVertex = queue.shift(); result.push(currentVertex); this.adjacencyList[currentVertex].forEach((neighbor) => { if (!visited[neighbor]) { visited[neighbor] = true; queue.push(neighbor); } }); } return result; } }
B。深度優先搜尋
深度優先搜尋方法透過使用以頂點作為參數的遞歸內部函數 dfs 來實作 DFS 演算法。此函數使用存取的物件來追蹤存取的頂點,並將每個存取的頂點新增至結果陣列。該函數首先將當前頂點標記為已存取並將其新增至結果陣列。然後,它迭代當前頂點的所有鄰居,並為每個未訪問的鄰居遞歸呼叫 dfs 函數。這個過程一直持續到所有頂點都被存取過並且結果數組作為 DFS 的結果傳回。
depthFirstSearch(start) { const result = []; const visited = {}; const adjacencyList = this.adjacencyList; (function dfs(vertex) { if (!vertex) return null; visited[vertex] = true; result.push(vertex); adjacencyList[vertex].forEach(neighbor => { if (!visited[neighbor]) { return dfs(neighbor); } }); })(start); return result; }
範例
在下面的範例中,我們示範了廣度優先搜尋(BFS)和深度優先搜尋(DFS)。
class Graph { constructor() { this.adjacencyList = {}; } addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; } addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); } print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } } breadthFirstSearch(start) { const queue = [start]; const result = []; const visited = {}; let currentVertex; visited[start] = true; while (queue.length) { currentVertex = queue.shift(); result.push(currentVertex); this.adjacencyList[currentVertex].forEach((neighbor) => { if (!visited[neighbor]) { visited[neighbor] = true; queue.push(neighbor); } }); } return result; } depthFirstSearch(start) { const result = []; const visited = {}; const adjacencyList = this.adjacencyList; (function dfs(vertex) { if (!vertex) return null; visited[vertex] = true; result.push(vertex); adjacencyList[vertex].forEach(neighbor => { if (!visited[neighbor]) { return dfs(neighbor); } }); })(start); return result; } } const graph = new Graph(); graph.addVertex("A"); graph.addVertex("B"); graph.addVertex("C"); graph.addVertex("D"); graph.addEdge("A", "B"); graph.addEdge("A", "C"); graph.addEdge("B", "D"); graph.addEdge("C", "D"); console.log("Initial Graph:"); graph.print(); console.log("BFS: "+graph.breadthFirstSearch('A')); console.log("DFS: "+graph.depthFirstSearch('A'));
輸出
Initial Graph: A -> B, C B -> A, D C -> A, D D -> B, C BFS: A,B,C,D DFS: A,B,D,C
結論
圖是一種有用的資料結構,可用來表示物件之間的關係和連結。在 JavaScript 中實作圖可以使用多種技術來完成,包括使用鄰接列表或鄰接矩陣。本答案中演示的 Graph 類別使用鄰接列表表示形式,其中每個頂點都作為鍵存儲在物件中,其對應的邊作為該鍵的值儲存在數組中。
Graph 類別實作了為圖形新增頂點和邊、列印圖形以及執行深度優先搜尋和廣度優先搜尋遍歷的方法。
以上是JavaScript 中圖的實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...
