【图】深度优先遍历&广度优先遍历
程序员文章站
2022-06-12 10:18:01
...
图的遍历:从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次。
因此,为了避免多次访问某一个定点,需要在遍历过程中把访问过得顶点打上标记。具体办法是设置一个访问数组
深度优先遍历(Depth_First_Search)
类似树的前序遍历。
步骤:
- 从图中某个顶点
v 出发,访问此顶点; - 然后从
v 的未被访问的邻接点出发深度优先遍历图,直至图中所有和v 有路径相通的顶点都被访问到。
实现
function Graph(v){
this.v = v;
this.e = [];
for (var i = 0; i < this.v.length; i++) {
this.e[i] = [];
}
this.visited = [];
for (var i = 0; i < this.v.length; ++i) {
this.visited[i] = false;
}
}
Graph.prototype.addEdge = function (v1,v2) {
//获取顶点对应的下标(因为这里存储的是大写字母,若存储的是顶点是number则不需要下面两步)
var v1Index = v1.charCodeAt(0)-'A'.charCodeAt(0);
var v2Index = v2.charCodeAt(0)-'A'.charCodeAt(0);
this.e[v1Index].push(v2Index);
this.e[v2Index].push(v1Index);
}
Graph.prototype.DFSTraverse = function (v) {
//获取顶点对应的下标(因为这里存储的是大写字母,若存储的是顶点是number则不需要这一步)
var vIndex = v.charCodeAt(0)-'A'.charCodeAt(0);
this.visited[vIndex] = true;
console.log("Visited vertex: " + v );
for (var i in this.e[vIndex]){
//console.log(this.e[vIndex][i]);
var next_v=this.e[vIndex][i]
if(!this.visited[next_v]){
this.DFSTraverse(this.v[next_v]);
}
}
}
对下图做深度优先遍历:(右图是遍历树)
var v= ['A','B','C','D','E','F','G','H','I'];
var g = new Graph(v);
g.addEdge(0,1);g.addEdge(0,5);
g.addEdge(1,2);g.addEdge(1,6);g.addEdge(1,8);
g.addEdge(2,3);g.addEdge(2,8);
g.addEdge(3,4);g.addEdge(3,6);g.addEdge(3,7);g.addEdge(3,8);
g.addEdge(4,5);g.addEdge(4,7);
g.addEdge(5,6);
g.addEdge(6,7);
console.log(g);
console.log("深度优先遍历过程:");
g.DFSTraverse('A');
得到的结果如下:
广度优先遍历(Breadth_First_Search)
定义
类似树的层次遍历。
步骤:
- 从图中某个顶点
v 出发,访问此顶点(将其访问标志置为已被访问,即visited[i]=1 ); - 依次访问顶点
v 的各个未被访问过的邻接点,将v 的全部邻接点都访问到; - 分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,并使“先被访问的顶 点的邻接点”先于“后被访问的顶点的邻接点”被访问,直到图中所有已被访问过的顶点的邻接点都被访问到。
- 依此类推,直到图中所有顶点都被访问完为止。
广度优先搜索在搜索访问一层时,需要记住已被访问的顶点,以便在访问下层顶点时,从已被访问的顶点出发搜索访问其邻接点。
所以在广度优先搜索中需要设置一个队列
实现
Graph.prototype.BFSTraverse = function (v) {
var queue = [];
var vIndex = v.charCodeAt(0)-'A'.charCodeAt(0);
this.visited[vIndex] = true;
queue.push(vIndex);
while(queue.length>0){
var vOut =queue.shift();
console.log("Visited vertex: " + this.v[vOut] );
for(var i in this.e[vOut]){
var next_v=this.e[vOut][i];
if(!this.visited[next_v]){
this.visited[next_v] = true;
queue.push(next_v);
}
}
}
}
运行结果: