图结构

 

 

一、实现邻接表

 

 

代码实现:

var Graph = function() {
    var vertices = []; // 初始化顶点
    var adjList = {}; // 初始化边

    // 添加顶点
    this.addVertices = function(v){
        vertices.push(v); // 添加顶点
        adjList[v] = []; // 初始化顶点对应的边
    }

    // 添加边
    this.addEdge = function(v1, v2) {
        adjList[v1].push(v2);
        adjList[v2].push(v1);
    }

    // 打印
    this.print = function() {
        console.log(adjList)
        var s = '\n';
        for(var i = 0; i < vertices.length; i++ ){
            var v = vertices[i];
            s += v + '=>';
            for(var j = 0; j < adjList[v].length; j++ ){
                s += adjList[v][j];
            }
            s += '\n'
        }
        console.log(s)
    }
}    
var graph = new Graph();
graph.addVertices('A')
graph.addVertices('B')
graph.addVertices('C')
graph.addVertices('D')
graph.addVertices('E')
graph.addVertices('F')
graph.addEdge('A','B')
graph.addEdge('A','C')
graph.addEdge('A','D')
graph.addEdge('C','D')
graph.addEdge('B','E')
graph.addEdge('B','F')
graph.print()

打印结果:

 

二、图遍历

 

1.广度遍历(BFS:Breadth-First Search)

(1)基本实现

代码实现:
  1.将所有顶点的颜色设为白色;
  2.创建一个队列;
  3.首个顶点入队列;
  4.循环队列是否为空, 若不为空,将第一个元素出栈,遍历其adjList,如果其中的顶点颜色为白色,则改为灰色并入队列;遍历完adjList后颜色设为黑色,并执行回调函数。

// 实现广度遍历
  // 具体实现:
  // 1.将所有顶点的颜色设为白色;
  // 2.创建一个队列;
  // 3.首个顶点入队列;
  // 4.循环队列是否为空,
  // 若不为空,将第一个元素出栈,遍历其adjList,如果其中的顶点颜色为白色,则改为灰色并入队列;遍历完adjList后颜色设为黑色,并执行回调函数
  var initColor = function() {
    var color = {};
    for(var i = 0; i < vertices.length; i++) {
      color[vertices[i]] = 'white';
    }
    return color;
  }
  this.bfs = function(v,callback) {
    // 所有顶点的颜色设为白色
    var color = initColor();
    // 创建队列
    var queue = new Queue();
    // 将第一个顶点放入队列中
    queue.enqueue(v);
    while(!queue.isEmpty()) {
      // 将队列头出栈
      var now = queue.dequeue()
      // 循环其边
      for(var i = 0; i < adjList[now].length; i++) {
        // 查看顶点颜色是否为白色,若是,则改为灰色,并入队
        var edge = adjList[now]
        var vi = adjList[now][i];
        if(color[vi] == 'white') {
          color[vi] = 'grey';
          queue.enqueue(vi);
        }
      }
      color[now] = 'black';
      if(callback) {
        callback(now);
      }
    }
  }

 

(2)广度优先遍历和最短路径问题

代码实现:

// 广度优先遍历:设置了距离和回溯点 ,方便查找顶点到顶点之间的最短距离
    this.BFS1 = function(v, callback) {
        var color = initColor();
        var queue = new Queue();
        // 创建
        var d = {}; // 距离
        var pred = {}; // 回溯点
        for(var i = 0; i < vertices.length; i++) {
            d[vertices[i]] = 0;
            pred[vertices[i]] = null;
        }
        queue.enqueue(v);
        while(!queue.isEmpty()) {
            var now = queue.dequeue();
            for(var i = 0; i < adjList[now].length; i++) {
                var vi = adjList[now][i]
                if(color[vi] == 'white') {
                    color[vi] = 'grey';
                    // 添加距离和回溯点
                    d[vi] = d[now] + 1;
                    pred[vi] = now;
                    // 入列
                    queue.enqueue(vi);
                }
            }
            color[now] = 'black';
            if(callback) {
                callback(now);
            }
        }
        return{
            pred:pred,
            d:d
        }
    }

使用:

// 栈
var Stack = function() {
    var items = [];
    this.push = function(val) {
        items.push(val);
    }
    this.pop = function() {
        return items.pop();
    }
    this.isEmpty = function() {
        return items.length == 0;
    }
}

var graph = new Graph();
graph.addVertices('A')
graph.addVertices('B')
graph.addVertices('C')
graph.addVertices('D')
graph.addVertices('E')
graph.addVertices('F')
graph.addEdge('A','B')
graph.addEdge('A','C')
graph.addEdge('A','D')
graph.addEdge('C','D')
graph.addEdge('B','E')
graph.addEdge('B','F')
graph.print()

var log = function(v) {
    console.log(v);
}
var s = graph.BFS1('A',log)
console.log(s);

// 最短路径:广度优先算法
var zuiduan = function(from, to) {
    var v = to;
    var path = new Stack();
    while(v != from) {
        path.push(v);
        v = s.pred[v];
    }
    path.push(v);
    var str = '';
    while(!path.isEmpty()) {
        str += path.pop() + '->';
    }
    str = str.slice(0,str.length - 2);
    console.log(str)
}
zuiduan('A','F') // A->B->F

 

2.深度遍历(DFS:Depth-First Search)

思路:A中发现有白色顶点,则查看白色顶点中是否还含有白色顶点;A->B->E和F

代码实现:

    // 深度遍历:像遍历树一样 递归
    var dfsVisite = function(v, color, callback) {
        color[v] = 'grey';
        for(var i = 0; i<adjList[v].length;i++) {
            var vi = adjList[v][i];
            while(color[vi] == 'white') {
                dfsVisite(vi,color,callback);
            }
        }
        color[v] = 'black';
        if(callback) {
            callback(v);
        }
    }
    this.DFS = function(v, callback) {
        var color = initColor();
        dfsVisite(v,color,callback);
    }

 

打印结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值