JS实现图的深度优先搜索和广度优先搜索
这是我参与更文挑战的第21天,活动详情查看: 更文挑战
前面我们讲了二叉树的搜索,二叉树的搜索可以有很多扩展,可以扩展成树的搜索,图的搜索,图的搜索可以扩展成爬虫的逻辑。今天我们就了解一下图的搜索。
搜索分为两种,一种是深度优先搜索,一种是广度优先搜索。
深度优先搜索是沿着节点的一条边,一路走到黑,然后返回到出发节点,再继续下一条边,如果找到目标节点,则返回,如果找不到,就会遍历完全部节点。
而广度优先搜索则是一层一层去寻找。如上图,用广度优先搜索是先从A开始,如果没找到就继续从第二层CB找,如果找到目标节点,则返回,如果找不到,就会一层一层遍历全部节点。
深度优先搜索更适合探索未知,因为它是先往远的地方走,能走多远走多远。
广度优先搜索更适合探索局域,例如我知道这里附近有要找的东西,那么我就从这附近一层一层的找。
树的搜索和图的搜索对比,树有一个好处,就是树不会形成环。图会形成环,所以图的搜索比较复杂,我们如果用之前的方法的话可能会出现死循环,所以我们要让它搜索的时候,找过的点不再找了。下面我们就用代码实现一下图的深度优先搜索和广度优先搜索。
代码实现图的深度优先搜索
function Node(value) {
this.value = value;
this.neighbor = [];
}
var a = new Node("a");
var b = new Node("b");
var c = new Node("c");
var d = new Node("d");
var e = new Node("e");
a.neighbor.push(b);
a.neighbor.push(c);
b.neighbor.push(a);
b.neighbor.push(c);
b.neighbor.push(d);
c.neighbor.push(a);
c.neighbor.push(b);
c.neighbor.push(d);
d.neighbor.push(b);
d.neighbor.push(c);
d.neighbor.push(e);
e.neighbor.push(d);
function deepSearch(node, target, path) {
if (node == null) return false;
if (path.indexOf(node) > -1) return false;//已经找过了就返回false
if (node.value == target) return true;
path.push(node);
var result = false;
for (var i = 0 ; i < node.neighbor.length ; i ++) {
result |= deepSearch(node.neighbor[i], target, path);
}
return result ? true : false;
}
console.log(deepSearch(b, "e", []));
代码实现图的广度优先搜索
function Node(value) {
this.value = value;
this.neighbor = [];
}
var a = new Node("a");
var b = new Node("b");
var c = new Node("c");
var d = new Node("d");
var e = new Node("e");
a.neighbor.push(b);
a.neighbor.push(c);
b.neighbor.push(a);
b.neighbor.push(c);
b.neighbor.push(d);
c.neighbor.push(a);
c.neighbor.push(b);
c.neighbor.push(d);
d.neighbor.push(b);
d.neighbor.push(c);
d.neighbor.push(e);
e.neighbor.push(d);
function bfs(nodes, target, path) {
if (nodes == null || nodes.length == 0) return false;
var nextNodes = [];
for (var i = 0 ; i < nodes.length ; i ++) {
if (path.indexOf(nodes[i]) > -1) continue;//如果已经找过了就跳过这个数
path.push(nodes[i]);
if (nodes[i].value == target) return true;
else nextNodes = nextNodes.concat(nodes[i].neighbor);
}
return bfs(nextNodes, target, path);
}
console.log(bfs([c], "b", []));