图的广度优先遍历与树的广度优先遍历类似,用队列来实现。
节点出队,节点的所有邻接点入队。如此循环,直到队列为空。
还是以邻接矩阵表示图,咱们用下面这个图。
用邻接矩阵去表示这个图,邻接表的广度优先遍历思路是一致的,只是去找邻接点的时候邻接表会更快。
图的定义:
function Graph(vexs = [], arcs = []) {
this.vexs = vexs
this.arcs = arcs
}
vexs 存储了4个顶点:
const vexs= [ 'A', 'B', 'C', 'D', 'E', 'F', 'G']
arcs是一个二维数组,长这样:
const arcs=
[
[0, 1, 0, 0, 1, 1, 0],
[1, 0, 1, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 1, 0],
[1, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
]
初始化这个图:
var graph = new Graph(vexs, arcs);
function bfs(graph) {
// // 从节点A开始
let queue = []
queue.push(0)
while (queue.length !==0) {
let len = queue.length;
for (let i = 0; i < len; i++) {
// 当前顶点
let index = queue.shift()
console.log(`当前访问的是第${index}个节点: `, graph.vexs[index])
visited[index] = true
// 找到当前顶点的所有邻接点
for(let j =0; j < graph.vexs.length; j++) {
if(graph.arcs[index][j] !==0 && visited[j]!==true) {
queue.push(j)
// 这里也必须加上 visited[j] = true 不然会重复入队
visited[j] = true
}
}
}
}
}
广度优先遍历的时间复杂度分析:
邻接矩阵来说需要遍历矩阵里面的每一个元素,时间复杂度为O(n^2)
邻接表来说时间复杂度为O(n+e)
bfs(广度优先遍历)与dfs(深度优先遍历)比较:
时间复杂度只与存储结构相关,如果是矩阵那么时间复杂度为O(n^2)
空间复杂度都为O(n) ,dfs的递归用到了栈,bfs是用到了队列。