RubyLouvre / algorithmbook

没有经过整理的知识才是徒然浪费时间,伤透脑筋!
109 stars 67 forks source link

链式前向星 #11

Open RubyLouvre opened 5 years ago

RubyLouvre commented 5 years ago
class GraphByComet {
      constructor(vertices, isDirected = false) {
        var n = vertices.length;
        var map = {}, head = [];
        for (var i = 0; i < n; i++) {
          map[vertices[i]] = i;
          head[i] = -1;
        }
        this.isDirected = isDirected
        this.vertices = vertices; //保存所有顶点信息
        this.head = head;
        this.map = map;
        this.ends = []
      }
      insertEdge(from, to, weight) {
        var len = this.ends.length
        this.ends.push({
          to,
          next: this.head[from],
          weight,
        })
        this.head[from] = len
      }
      addEdge(a, b, weight = 1) {
        var from = this.map[a];
        var to = this.map[b];
        this.insertEdge(from, to, weight);
        if (!this.isDirected) {
          this.insertEdge(to, from, weight);
        }
      }
      dfs(cb) {
        var visited = [];
        for (var i = 0; i < this.vertices.length; i++) {
          if (visited[i] === COLOR.WHITE) {
            dfs(this, i, visited, cb);
          }
        }
      }
      bfs(cb) {
        var visited = []
        var ends = this.ends;
        var queue = [0]
        visited[0] = COLOR.GRAY;
        while (queue.length) {
          var index = queue.shift()
          cb(this.vertices[index], index)
          for (var i = this.head[index]; ~i; i = ends[i].next) {
            var j = ends[i].to;//取是某一终点
            if (visited[j] === COLOR.WHITE) {
              visited[j] = COLOR.GRAY
              queue.push(j)
            }
          }
        }
      }
      toString() {
        var ends = this.ends
        var str = '['
        console.log(this)
        for (var u = 0; u < this.head.length; u++) {
          for (var i = this.head[u]; i != -1; i = ends[i].next) {
            str += `{${u}, ${ends[i].to}, ${ends[i].weight}}\n`;
          }
        }
        return str += ']'
      }
    }
    var COLOR = {
      WHITE: void 0,
      GRAY: 1,
      BLACK: -1
    }
    function dfs(graph, index, visited, cb) {
      visited[index] = COLOR.GRAY; //已被访问
      var ends = graph.ends;
      cb(graph.vertices[index], index) //访问顶点
      //循环以index为起点的所有边
      for (var i = graph.head[index]; ~i; i = ends[i].next) {// ~i相当于 i !==-1
        var j = ends[i].to;//取是某一终点
        if (visited[j] === COLOR.WHITE) {
          dfs(graph, j, visited, cb)
        }
      }
      visited[index] = COLOR.BLACK;//它及其所有子树都被访问
    }

    var g = new GraphByComet(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'], true);

     g.addEdge('A', 'B')
     g.addEdge('A', 'F')
     g.addEdge('B', 'G')
     g.addEdge('F', 'G')
     g.addEdge('B', 'C')
     g.addEdge('B', 'I')
     g.addEdge('C', 'I')
     g.addEdge('G', 'H')
     g.addEdge('F', 'E')
     g.addEdge('H', 'D')
     g.addEdge('H', 'E')
     g.addEdge('D', 'E')
     g.addEdge('D', 'G')
     g.addEdge('I', 'D')
     g.addEdge('C', 'D')
     g.addEdge('C', 'D')

    g.bfs(function (el, pos) {
      console.log("访问bfs", el, pos)
    });
    console.log('====')
    g.dfs(function (el, pos) {
      console.log("访问dfs", el, pos)
    });