原文链接:https://note.noxussj.top/?source=helloworld
什么是图?
图是网络结构的抽象模型,是一组由边连接的节点。图可以表示任何二元关系,比如道路、航班等。在 JavaScript 中没有图,但是可以通过 Object 和 Array 来构建图。
常用操作
- 深度优先遍历
- 广度优先遍历
图的表示法
- 邻接矩阵
- 邻接表
- 关联矩阵
- ...

邻接矩阵
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 0 | 1 | 0 | 0 | 0 |
| B | 0 | 0 | 1 | 1 | 0 |
| C | 0 | 0 | 0 | 0 | 1 |
| D | 1 | 0 | 0 | 0 | 0 |
| E | 0 | 0 | 0 | 1 | 0 |
邻接表
并非仅限于通过对象/数组表示,其他形式也可以。
1{ 2 "A": ["B"], 3 "B": ["C", "D"], 4 "C": ["E"], 5 "D": ["A"], 6 "E": ["D"] 7}
图的深度/广度优先遍历
深度优先遍历
尽可能深的搜索图的分支。
口诀:
- 先访问根节点
- 对根节点的没访问过的相邻节点挨个进行深度优先遍历(因为相邻节点可能也会指向当前节点)
1const graph = { 2 A: ['B'], 3 B: ['C', 'D'], 4 C: ['E'], 5 D: ['A'], 6 E: ['D'] 7} 8 9const visited = new Set() 10 11const dfs = (n) => { 12 console.log(n) 13 14 visited.add(n) 15 16 graph[n].forEach((item) => { 17 if (!visited.has(item)) { 18 dfs(item) 19 } 20 }) 21} 22 23dfs('A') // A B C E D
广度优先遍历
先访问离根节点最新的节点。
口诀:
- 新建一个队列,把根节点入队
- 把队头出队并访问
- 把队头的没有访问过的相邻节点入队
- 重复第 2、3 步直到队列为空
1const graph = { 2 A: ['B'], 3 B: ['C', 'D'], 4 C: ['E'], 5 D: ['A'], 6 E: ['D'] 7} 8 9const bfs = (head) => { 10 const visited = new Set() 11 12 visited.add(head) 13 14 const q = [head] 15 16 while (q.length) { 17 const n = q.shift() 18 19 console.log(n) 20 21 graph[n].forEach((item) => { 22 if (!visited.has(item)) { 23 q.push(item) 24 visited.add(item) 25 } 26 }) 27 } 28} 29 30bfs('A') // A B C D E
