JS 深度优先遍历(DFS)和广度优先遍历(BFS)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS 深度优先遍历(DFS)和广度优先遍历(BFS)相关的知识,希望对你有一定的参考价值。
参考技术A 深度优先遍历DFS自定义:深度单线游走,从根走完最后一个节点,在游走兄弟节点,走完兄弟的所有子节点,循环之。
递归算法:
function deepFirstSearch(node, nodeList = [])
if (node)
nodeList.push(node);
var children = node.children;
for (var i = 0; i < children.length; i++)
//每次递归的时候将 需要遍历的节点 和 节点所存储的数组传下去
deepFirstSearch(children[i], nodeList);
return nodeList;
非递归算法:
function deepFirstSearch(node)
var nodes = [];
if (node != null)
var stack = [];
stack.push(node);
while (stack.length != 0)
var item = stack.pop();
nodes.push(item);
var children = item.children;
for (var i = children.length - 1; i >= 0; i--)
stack.push(children[i]);
return nodes;
广度优先遍历(BFS)
自定义:从根开始 层层推进 走完一层 走下一层 (犹如爬楼,走完一层的楼梯,继续下一层的楼梯)
递归算法:(容易栈溢出)
function breadthFirstSearch(node)
var nodes = [];
var i = 0;
if (!(node == null))
nodes.push(node);
breadthFirstSearch(node.nextElementSibling);
node = nodes[i++];
breadthFirstSearch(node.firstElementChild);
return nodes;
非递归算法:(推荐)
function breadthFirstSearch(node)
var nodes = [];
if (node != null)
var queue = [];
queue.unshift(node);
while (queue.length != 0)
var item = queue.shift();
nodes.push(item);
var children = item.children;
for (var i = 0; i < children.length; i++)
queue.push(children[i]);
return nodes;
深度优先遍历 (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
以上是关于JS 深度优先遍历(DFS)和广度优先遍历(BFS)的主要内容,如果未能解决你的问题,请参考以下文章