lulusir / my-blog

my-blog
https://github.com/lulusir/my-blog/issues
13 stars 1 forks source link

数据结构--笔记-图 #8

Open lulusir opened 7 years ago

lulusir commented 7 years ago

typescript实现版本

图是网络结构的抽象,图是一组由边连接的节点。

G = (V, E)

相关术语

class Graph {
  constructor () {
    this._veritices = [] // 用一个数组来储存所有顶点的名字
    this._adjList = new Map() // 用字典来储存邻接表,字典使用顶点的名字为键,邻接顶点列表为值
  }
  addVertex (v) {
    this._veritices.push(v) // 存入顶点
    this._adjList.set(v, []) // 初始化顶点对应的列表
  }
  addEdge (v, w) {
    this._adjList.get(v).push(w) // 将w顶点添加到v的邻接表中
    this._adjList.get(w).push(v) // 如果是无向图,则把v顶点也添加到w的邻接表中
  }
  toString () {
    let s = ''
    this._veritices.forEach(ver => {
      s += `${ver} ==> `
      this._adjList.get(ver).forEach(neibor => {
        s += neibor + ' '
      })
      s += '\n'
    })
    return s
  }
}
var graph = new Graph()
var myVeritices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
myVeritices.forEach(v => {
  graph.addVertex(v)
})
graph.addEdge('A', 'B')
graph.addEdge('A', 'C')
graph.addEdge('A', 'D')
graph.addEdge('C', 'D')
graph.addEdge('C', 'G')
graph.addEdge('D', 'G')
graph.addEdge('D', 'H')
graph.addEdge('B', 'E')
graph.addEdge('B', 'F')
graph.addEdge('E', 'I')

// 输出结果
A ==> B C D 
B ==> A E F 
C ==> A D G 
D ==> A C G H 
E ==> B I 
F ==> B 
G ==> C D 
H ==> D 
I ==> E

图的遍历

广度优先搜索(BFS)

class Graph {
  ...
  bfs (v, cb) {
    const color = this.initializeColor()
    const queue = new Queue()
    queue.enqueue(v)

    while (!queue.isEmpty()) {
      const u = queue.dequeue()
      const neighbors = this._adjList.get(u)
      color[u] = 'grey'
      neighbors.forEach(v => {
        if (color[v] === 'white') {
          color[v] = 'grey'
          queue.enqueue(v)
        }
      })
      color[u] = 'back'

      if (cb) {
        cb(u)
      }
    }
  }
}
// 返回路径和追溯点
  bfs2 (v, cb) {
    const color = this.initializeColor()
    const queue = new Queue()
    const d = [] // v到u的距离
    const pred = [] // 钱说点
    queue.enqueue(v)
    // 初始化
    this._veritices.forEach(v => {
      d[v] = 0
      pred[v] = null
    })

    while (!queue.isEmpty()) {
      const u = queue.dequeue()
      const neighbors = this._adjList.get(u)
      color[u] = 'grey'
      neighbors.forEach(v => {
        if (color[v] === 'white') {
          color[v] = 'grey'
          d[v] = d[u] + 1
          pred[v] = u
          queue.enqueue(v)
        }
      })
      color[u] = 'back'

      if (cb) {
        cb(u)
      }
    }

    return {
      distances: d,
      predecessors: pred
    }
  }

寻找最短路径

// 路径追溯
var fromVertex = myVeritices[0]
myVeritices.forEach(toVertex => {
  var path = new Stack()
  for (var v = toVertex; v !== fromVertex; v = shortestPathA.predecessors[v]) {
    path.push(v)
  }
  path.push(fromVertex)
  var s = path.pop()
  while (!path.isEmpty()) {
    s += ' - ' + path.pop()
  }
  console.log(s)
})
// 输出结果
A
A - B
A - C
A - D
A - B - E
A - B - F
A - C - G
A - D - H
A - B - E - I

深度优先搜索

  dfs (cb) {
    const color = this.initializeColor()
    this._veritices.forEach(v => {
      if (color[v] === 'white') {
        this._dfsVisit(v, color, cb)
      }
    })
  }

  _dfsVisit (u, color, cb) {
    color[u] = 'grey'
    if (cb) {
      cb(u)
    }
    const neighbors = this._adjList.get(u)
    neighbors.forEach(v => {
      if (color[v] === 'white') {
        this._dfsVisit(v, color, cb)
      }
    })
    color[u] = 'black'
  }
// 探索深度优先算法
  DFS () {
    const color = this.initializeColor(),
      d = {},
      f = {},
      p = {}
    let time = 0
    this._veritices.forEach(v => {
      f[v] = 0
      d[v] = 0
      p[v] = null
    })

    this._veritices.forEach(v => {
      if (color[v] === 'white') {
        _DFSVisit.call(this, v, color, d, f, p)
      }
    })
    function _DFSVisit (v, color, d, f, p) {
      console.log('discovered ' + v)
      color[v] = 'grey'
      d[v] = ++time
      const neighbors = this._adjList.get(v)
      neighbors.forEach(w => {
        if (color[w] === 'white') {
          p[w] = v
          _DFSVisit.call(this, w, color, d, f, p)
        }
      })
      color[v] = 'black'
      f[v] = ++time
      console.log('explored ' + v)
    }
    return {
      discovery: d,
      finished: f,
      predecessors: p
    }
  }