Set 是记录图论中节点访问状态的天然选择,因其支持 O(1) 插入、查找与删除,自动去重,且可直接存储任意类型值(包括对象、数字、Symbol),语义清晰、无需字符串化、避免类型混淆,相比数组(includes 为 O(n))和对象(需手动管理 key)更高效可靠。

JavaScript 中的 Set 是记录图论中节点访问状态的天然选择——它提供 O(1) 的插入、查找和删除,且自动去重,非常适合标记“已访问”节点。
为什么用 Set 而不是数组或对象?
Set 比数组(includes() 是 O(n))更高效;相比对象(需手动管理 key,还可能因字符串化导致类型混淆),Set 支持任意类型作为值(包括对象、数字、符号),无需序列化,语义清晰,不易出错。
常见图遍历中的使用方式
以 BFS 和 DFS 为例,访问前检查是否已在 Set 中,访问后立即加入:
- BFS 示例(邻接表表示):
const queue = [startNode];
visited.add(startNode);
while (queue.length > 0) {
const node = queue.shift();
// 处理 node...
for (const neighbor of graph.get(node) || []) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
}
}
}
- DFS 递归写法(避免重复递归):
if (visited.has(node)) return;
visited.add(node);
// 处理当前节点
for (const neighbor of graph.get(node) || []) {
dfs(neighbor, visited, graph);
}
}
注意节点类型的可靠性
如果图节点是普通对象(如 {id: 1}),直接存入 Set 会因引用不同而失效(两个相同结构的对象被视为不同元素)。此时应:
立即学习“Java免费学习笔记(深入)”;
- 用唯一标识符(如
node.id)代替整个对象存入Set - 或确保节点是单例对象(如用 Map 管理全局节点池)
- 避免用 JSON.stringify(node) 作 key —— 效率低且顺序敏感
扩展:配合算法做状态分离
某些算法(如拓扑排序、双色染色)需要区分“未访问”“正在访问”“已访问”。这时可用一个 Map 或多个 Set:
-
unvisited、visiting、visited三个Set - 或用
Map存键值对:status.set(node, 'visiting') -
Set更轻量,适合仅需二元状态(访问/未访问)的场景


















