深度优先遍历 (DFS) 与广度优先遍历 (BFS)
Posted 我是开发者FTD
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度优先遍历 (DFS) 与广度优先遍历 (BFS)相关的知识,希望对你有一定的参考价值。
背景
-
一种是以深度,不断去查找是否有下级节点,如果有就继续递归向下查找,否则回到上级,再由未遍历的下级节点进入。 -
另一种是以广度,从一个节点,查找出它的所有子节点,再依次从所有子节点中向下查找所有子节点。
深度优先遍历 (DFS)
-
指定一点为顶点,进行标记,并查找该节点的任意一个相邻节点。 -
若该相邻节点未被访问,则对其进行标记,并进入递归,查找它的未被标记访问的邻接节点;若该节点已被访问标记,则回退到上级节点,查找它未被标记访问的邻接节点,再进入递归,直到与起点相通的全部顶点都被标记访问为止。 -
若所有节点都被标记访问,就结束;反之,如果还有节点未被访问,则需要以该节点为顶点进行下一步的递归查找,直到所有点都被标记访问。
广度优先遍历 (BFS)
-
创建一个队列,并将开始节点放入队列中 -
若队列非空,则从队列中取出第一个节点,检测它是否为目标节点 -
若是目标节点,则结束搜寻,并返回结果 -
若不是,则将它所有没有被检测过的子节点都加入队列中 -
若队列为空,表示图中并没有目标节点,则结束遍历
const vertices = []; // 图的顶点集合
const edges = new Map(); // 图的边集合
/**
* 添加节点
**/
addVertex = (v: string) => {
this.vertices.push(v);
this.edges.set(v, []);
};
/**
* 添加边
**/
addEdge = (v: string, w: string) => {
const vEdge = edges.get(v);
vEdge.push(w);
const wEdge = edges.get(w);
wEdge.push(v);
edges.set(v, vEdge);
edges.set(w, wEdge);
};
formatToString = () => {
let s = "";
vertices.forEach( v => {
s += `${v} -> `;
const neighors = edges.get(v);
neighors.forEach( n => (s += `${n} `));
s += " ";
});
return s;
};
graphDFS = () => {
const marked = [];
vertices.forEach( v => {
if (!marked[v]) {
dfsVisit(v);
}
});
const dfsVisit = (u: string) => {
marked[u] = true;
const neighbors = edges.get(u);
neighors.forEach( n => {
if (!marked[n]) {
dfsVisit(n);
}
});
};
};
graphBFS = (v: string, t?: string) => {
const queue = [],
marked = [];
marked[v] = true;
queue.push(v); // 添加到队尾
while ( queue.length > 0) {
const s = queue.shift(); // 从队首移除
if (t && s === t) {
console. log( "target vertex: ", t);
return;
} else if (edges.has(s)) {
console. log( "visited vertex: ", s);
}
const neighbors = edges.get(s);
neighors.forEach(n => {
if (!marked[n]) {
marked[n] = true;
queue.push(n);
}
});
}
};
总结
站在巨人的肩膀
链接:https://juejin.im/post/5d35204ff265da1bca521807
以上是关于深度优先遍历 (DFS) 与广度优先遍历 (BFS)的主要内容,如果未能解决你的问题,请参考以下文章