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

本文介绍了图的两种基本遍历算法——深度优先遍历(DFS)和广度优先遍历(BFS)。深度优先遍历类似于树的前序遍历,通过递归方式访问每个节点及其邻接点。广度优先遍历类似于树的层次遍历,使用队列结构确保按层次顺序访问节点。文章还提供了具体的JavaScript实现示例。

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

因此,为了避免多次访问某一个定点,需要在遍历过程中把访问过得顶点打上标记。具体办法是设置一个访问数组 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);
            }
        }
    }
}

运行结果:
这里写图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值