答案:图的两种主要表示方法是邻接矩阵和邻接表。邻接矩阵使用二维数组存储边,适合稠密图,检查边存在性快(O(1)),但空间占用大(O(V²)),遍历邻居慢(O(V));邻接表使用Map或链表存储每个顶点的邻居,空间效率高(O(V+E)),遍历邻居高效(O(degree(V))),适合稀疏图和图遍历算法,但查边存在性较慢(除非用Set优化)。在JavaScript中实现邻接表时,推荐使用Map+Set组合,以支持任意类型顶点、避免重复边,并提升增删查效率。需注意区分有向与无向图的边处理、防止顶点缺失导致错误、合理选择数据结构以应对自环与多重边,同时关注内存使用与性能优化。

在JavaScript中实现图的邻接表,核心思路是利用哈希映射(通常是
Map
Set
要实现一个图的邻接表,我通常会创建一个
Graph
Map
class Graph {
constructor() {
// 使用Map来存储邻接表,键是顶点,值是该顶点的邻居列表(Set或Array)
this.adjacencyList = new Map();
}
// 添加一个顶点
addVertex(vertex) {
if (!this.adjacencyList.has(vertex)) {
this.adjacencyList.set(vertex, new Set()); // 使用Set自动处理重复邻居
}
}
// 添加一条边(无向图)
addEdge(vertex1, vertex2) {
if (!this.adjacencyList.has(vertex1)) {
this.addVertex(vertex1);
}
if (!this.adjacencyList.has(vertex2)) {
this.addVertex(vertex2);
}
this.adjacencyList.get(vertex1).add(vertex2);
this.adjacencyList.get(vertex2).add(vertex1); // 对于无向图,两边都要加
}
// 添加一条边(有向图)
addDirectedEdge(source, destination) {
if (!this.adjacencyList.has(source)) {
this.addVertex(source);
}
if (!this.adjacencyList.has(destination)) {
this.addVertex(destination);
}
this.adjacencyList.get(source).add(destination);
}
// 获取某个顶点的所有邻居
getNeighbors(vertex) {
return this.adjacencyList.get(vertex) || new Set();
}
// 打印图的邻接表
printGraph() {
for (let [vertex, neighbors] of this.adjacencyList) {
console.log(`${vertex} -> ${[...neighbors].join(', ')}`);
}
}
// 检查两个顶点之间是否存在边
hasEdge(vertex1, vertex2) {
return this.adjacencyList.has(vertex1) && this.adjacencyList.get(vertex1).has(vertex2);
}
// 移除一个顶点及其所有关联的边
removeVertex(vertexToRemove) {
if (!this.adjacencyList.has(vertexToRemove)) {
return;
}
// 移除其他顶点到此顶点的边
for (let [vertex, neighbors] of this.adjacencyList) {
if (neighbors.has(vertexToRemove)) {
neighbors.delete(vertexToRemove);
}
}
// 移除此顶点本身
this.adjacencyList.delete(vertexToRemove);
}
// 移除一条边
removeEdge(vertex1, vertex2) {
if (!this.adjacencyList.has(vertex1) || !this.adjacencyList.has(vertex2)) {
return;
}
this.adjacencyList.get(vertex1).delete(vertex2);
this.adjacencyList.get(vertex2).delete(vertex1); // 无向图
}
}
// 示例用法:
const graph = new Graph();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addVertex('D');
graph.addVertex('E');
graph.addEdge('A', 'B');
graph.addEdge('A', 'C');
graph.addEdge('B', 'D');
graph.addEdge('C', 'E');
graph.addEdge('D', 'E');
console.log("图的邻接表表示:");
graph.printGraph();
// 输出可能类似:
// A -> B, C
// B -> A, D
// C -> A, E
// D -> B, E
// E -> C, D
console.log(`A和B之间有边吗? ${graph.hasEdge('A', 'B')}`); // true
console.log(`A和D之间有边吗? ${graph.hasEdge('A', 'D')}`); // false
graph.removeEdge('A', 'B');
console.log("\n移除A-B边后:");
graph.printGraph();
graph.removeVertex('C');
console.log("\n移除顶点C后:");
graph.printGraph();选择
Map
Map
Map
Set
在图论中,表示图的方法主要有两种:邻接矩阵(Adjacency Matrix)和邻接表(Adjacency List)。每种方法都有其适用场景和固有的优缺点,了解它们能帮助我们更好地选择适合特定问题的表示方式。
1. 邻接矩阵(Adjacency Matrix) 邻接矩阵是一个二维数组(或矩阵),通常记作
A[V][V]
V
i
j
A[i][j]
A[i][j] == A[j][i]
优点:
A[i][j]
V^2
缺点:
O(V^2)
V
V
V x V
2. 邻接表(Adjacency List) 邻接表是前面我们重点讨论的表示方法。它为图中的每个顶点维护一个列表(通常是链表、数组或哈希集合),该列表存储了所有与该顶点直接相连的顶点。
优点:
V^2
O(V + E)
E
O(V^2)
degree(V)
缺点:
Set
Map
Set
总结来说,如果图是稠密的,并且需要频繁检查边是否存在,邻接矩阵可能是更好的选择。而如果图是稀疏的,并且需要频繁遍历顶点的邻居(例如进行图遍历算法),那么邻接表无疑是更优的方案。在实际应用中,绝大多数真实世界的图(如社交网络、互联网拓扑)都是稀疏图,因此邻接表的使用更为广泛。
邻接表在图算法中的效率提升,主要体现在它对稀疏图的优化处理上。当图中的边相对较少时,邻接表能够显著减少不必要的计算和内存占用。我个人觉得,它就像一个“按需分配”的系统,只存储必要的信息,而不是像邻接矩阵那样预留一大片可能用不上的空间。
图遍历算法(BFS/DFS)的加速:
degree(V)
V
O(V + E)
O(V^2)
E
V^2
查找最短路径算法(Dijkstra, Bellman-Ford):
O(E log V)
O(E + V log V)
O(V^2)
最小生成树算法(Prim, Kruskal):
连通性检查与拓扑排序:
空间效率:
说白了,当你的算法需要“沿着边走”时,邻接表就是那个为你铺设好高速公路的工具。它避免了你在一个巨大的、大部分是空的表格中瞎转悠,而是直接告诉你“这里有条路,通向哪里哪里”。这种聚焦于实际存在连接的特性,是它在多数图算法中成为首选表示方法的核心原因。
在JavaScript中实现和使用邻接表,虽然概念上不复杂,但实际操作中还是有些地方需要留心,或者可以进行一些优化,让代码更健壮、更高效。
选择正确的邻居存储结构:Array
Set
Array
Set
Set
Set
add()
delete()
has()
Set
Array
addEdge
处理自环和多重边:
Set
Set
Array
push
无向图与有向图的边处理:
(u, v)
u
V
V
u
addEdge(u, v)
u
V
V
u
(u, v)
u
V
V
u
u
V
addEdge
addDirectedEdge
顶点不存在时的健壮性处理:
addEdge
getNeighbors
adjacencyList
内存管理与垃圾回收:
性能优化:
Map
Map
Map
new Set()
new Map()
调试和可视化:
console.log
这些“坑”或者说“细节”,很多时候都是在实际开发中踩过才有的体会。一开始可能觉得一个
Map
Set
以上就是JS如何实现图的邻接表?图的表示方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号