欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【图】深度优先遍历&广度优先遍历

程序员文章站 2022-06-12 10:18:01
...

图的遍历:从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次。

因此,为了避免多次访问某一个定点,需要在遍历过程中把访问过得顶点打上标记。具体办法是设置一个访问数组 visited[n],初值为 0,访问过后设置为 1。

深度优先遍历(Depth_First_Search)

类似树的前序遍历。
步骤:

  1. 从图中某个顶点 v 出发,访问此顶点;
  2. 然后从 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)

定义

类似树的层次遍历。
步骤:

  1. 从图中某个顶点 v 出发,访问此顶点(将其访问标志置为已被访问,即 visited[i]=1);
  2. 依次访问顶点 v 的各个未被访问过的邻接点,将 v 的全部邻接点都访问到;
  3. 分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,并使“先被访问的顶 点的邻接点”先于“后被访问的顶点的邻接点”被访问,直到图中所有已被访问过的顶点的邻接点都被访问到。
  4. 依此类推,直到图中所有顶点都被访问完为止。

广度优先搜索在搜索访问一层时,需要记住已被访问的顶点,以便在访问下层顶点时,从已被访问的顶点出发搜索访问其邻接点。
所以在广度优先搜索中需要设置一个队列 Queue,使已被访问的顶点顺序由队尾进入队列。在搜索访问下层顶点时,先从队首取出一个已被访问的上层顶点,再从该顶点出发搜索访问它的各个邻接点。

【图】深度优先遍历&广度优先遍历

实现

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);
            }
        }
    }
}

运行结果:
【图】深度优先遍历&广度优先遍历

相关标签: 遍历