[Algorithm] Breadth First JavaScript Search Algorithm for Graphs
Breadth first search is a graph search algorithm that starts at one node and visits neighboring nodes as widely as possible before going further down any other path. This algorithm requires the use of a queue to keep track of which nodes to visit, so it might be worth your time to brush up on that data structure before watching this lesson.
const {createQueue} = require('./queue'); function createNode(key) { let children = []; return { key, children, addChild(child) { children.push(child) } } } function createGraph(directed = false) { const nodes = []; const edges = []; return { nodes, edges, directed, addNode(key) { nodes.push(createNode(key)) }, getNode (key) { return nodes.find(n => n.key === key) }, addEdge (node1Key, node2Key) { const node1 = this.getNode(node1Key); const node2 = this.getNode(node2Key); node1.addChild(node2); if (!directed) { node2.addChild(node1); } edges.push(`${node1Key}${node2Key}`) }, print() { return nodes.map(({children, key}) => { let result = `${key}`; if (children.length) { result += ` => ${children.map(n => n.key).join(' ')}` } return result; }).join('\n') }, /** * Breadth First Search */ bfs (startNodeKey = "", visitFn = () => {}) { /** * Keytake away: * 1. Using Queue to get next visit node * 2. Enqueue the node's children for next run * 3. Hashed visited map for keep tracking visited node */ const startNode = this.getNode(startNodeKey); // create a hashed map to check whether one node has been visited const visited = this.nodes.reduce((acc, curr) => { acc[curr.key] = false; return acc; }, {}); // Create a queue to put all the nodes to be visited const queue = createQueue(); queue.enqueue(startNode); // start process while (!queue.isEmpty()) { const current = queue.dequeue(); // check wheather the node exists in hashed map if (!visited[current.key]) { visitFn(current); visited[current.key] = true; // process the node's children current.children.map(n => { if (!visited[n.key]) { queue.enqueue(n); } }); } } } } } const graph = createGraph(true) graph.addNode('Kyle') graph.addNode('Anna') graph.addNode('Krios') graph.addNode('Tali') graph.addEdge('Kyle', 'Anna') graph.addEdge('Anna', 'Kyle') graph.addEdge('Kyle', 'Krios') graph.addEdge('Kyle', 'Tali') graph.addEdge('Anna', 'Krios') graph.addEdge('Anna', 'Tali') graph.addEdge('Krios', 'Anna') graph.addEdge('Tali', 'Kyle') console.log(graph.print()) const nodes = ['a', 'b', 'c', 'd', 'e', 'f'] const edges = [ ['a', 'b'], ['a', 'e'], ['a', 'f'], ['b', 'd'], ['b', 'e'], ['c', 'b'], ['d', 'c'], ['d', 'e'] ] const graph2 = createGraph(true) nodes.forEach(node => { graph2.addNode(node) }) edges.forEach(nodes => { graph2.addEdge(...nodes) }) graph2.bfs('a', node => { console.log(node.key) //a,b,e,f,d,c })
A more general function:
bfs (startNodeKey, predFn = () => {}, cb = () => {}) { const startNode = this.getNode(startNodeKey); const visited = createVistedMap(this.nodes); const queue = createQueue(); startNode.children.forEach((n) => { queue.enqueue(n); }); while (!queue.isEmpty()) { const current = queue.dequeue(); if (!visited[current.key]) { if (predFn(current)) return cb(current); else { visited[current.key] = true; } } } cb(null) },
let graph3 = createGraph(true) const tyler = {key: 'tyler', dog: false}; const henry = {key: 'henry', dog: false}; const john = {key: 'john', dog: false}; const aimee = {key: 'aimee', dog: true}; const peggy = {key: 'peggy', dog: false}; const keli = {key: 'keli', dog: false}; const claire = {key: 'claire', dog: false}; graph3.addNode('tyler', tyler); graph3.addNode('henry', henry); graph3.addNode('john', john); graph3.addNode('claire', claire); graph3.addNode('aimee', aimee); graph3.addNode('peggy', peggy) graph3.addNode('keli', keli); graph3.addEdge('tyler', 'henry') graph3.addEdge('tyler', 'john') graph3.addEdge('tyler', 'aimee') graph3.addEdge('henry', 'keli') graph3.addEdge('henry', 'peggy') graph3.addEdge('john', 'john') graph3.addEdge('keli', 'claire') graph3.bfs2('tyler', (node) => { return node.dog; }, (node) => { if (node) console.log(`${node.key} has a dog`) else console.log('Tyler friends has no dog') })
Time Complexity: O(V+E) where V is number of vertices in the graph and E is number of edges in the graph.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2017-12-15 [Python] Read and plot data from csv file
2017-12-15 [React] Make Controlled React Components with Control Props
2016-12-15 [JS Compose] 6. Semigroup examples
2016-12-15 [JS Compose] 5. Create types with Semigroups
2014-12-15 [AngularJS] $http cache
2014-12-15 [AngularJS+ GSAP] Greensock TimelineLite Animation Sequences