图是网络结构抽象模型。图是一组由边连接的节点(或顶点)。

一个图G = (V,E)由以下元素组成。

  • V:一组顶点
  • E:一组边,连接V中的顶点 

由一条边连接在一起的顶点称为相邻顶点。一个顶底的度是其相邻顶点的数量。

简单路径要求不包含重复的顶点。

如果图中每两个定点间在双向上都存在路径,则该图是强连通。

图可以是未加权的或是加权的。加权图的边被赋予了权值。

从数据结构的角度来说,有多种方式来表示图。在所有的表示法中,不存在绝对正确的方式。图的正确表示法取决于待解决的问题和图的类型。

  • 邻接矩阵
  • 邻接表
  • 关联矩阵
//邻接表方式实现
class Graph{
    constructor(){
        this.vertices = []
        this.adjList = new Dictionary()//见实现字典类
    }
}
Graph.prototype.addVertex = function(v){
    this.vertices.push(v)
    this.adjList.set(v,[])
}
Graph.prototype.addEdge = function(v,w){
    this.adjList.get(v).push(w)
    this.adjList.get(w).push(v)
}
Graph.prototype.toString = function(){
    let str = ''
    for(let i = 0;i < this.vertices.length;i++){
        str += vertices[i] + '->'
        var neighbors = this.adjList.get(vertices[i])
        for(let j = 0;j < neighbors.length;j++){
            str += neighbors[j] + ' '
        }
        str += '\n'
    }
    return str
}
// 运行代码
let graph = new Graph()
let myVertices = ['A','B','C','D','E','F','G','H']
for(let i = 0;i < myVertices.length;i++){
    graph.addVertex(myVertices[i])
}
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')
console.log(graph.toString())
// A -> B C D
// B -> A E F
// C -> A D G
// D -> A C G H
// E -> B 
// F -> B 
// G -> C D
// H -> D

有两种算法可以对图进行遍历:广度优先搜索(Breadth-First Search,BFS)和深度优先搜索(Depth-First Search,DFS)。

广度优先搜索算法和深度优先搜索算法基本上是相同的,只有一点不同,就是待访问顶点列表的数据结构。

算法 数据结构 描述
深度优先搜索 通过将顶点存入栈中,顶点是沿着路径被探索的,存在新的相邻顶点就去访问。
广度优先搜索 队列 通过将顶点存入队列中,最先入队列的顶点先被探索。

当要标注已经访问过的顶点时,用三种颜色来反映它们的状态。

  • 白色:表示该顶点还没有被访问。
  • 灰色:表示该顶点被访问过,但并未被探索过。
  • 黑色:表示该顶点被访问过且被完全探索过。
Graph.prototype.initColor = function(){
    let color = []
    for(let i = 0;i < this.vertices.length;i++){
        color[this.vertices[i]] = 'white'
    }
    return color
}
Graph.prototype.bfs = function(v,cb){
    let color = this.initColor()
    let queue = new Queue(v)
    while(!queue.isEmpty()){
        let u = queue.dequeue()
        let neighbors = this.adjList.get(u)
        color[u] = 'gray'
        for(let i = 0;i < neighbors.length;i++){
            let item = neighbors[i]
            if(color[item] == 'white'){
                color[item] = 'gray'
                queue.enqueue(item)
            }
        }
        color[u] = 'black'
        if(cb){
            cb(u)
        }
    }
}

  

Graph.prototype.dfs = function(cb){
    let color = this.initColor()
    for(let i = 0;i < this.vertices.length;i++){
        if(color[this.vertices[i]] == 'white'){
            dfsVisit(vertices[i],color,cb)
        }
    }
    function dfsVisit(u,color,cb){
        color[u] = 'grey'
        let neighbors = thia.adjList.get(u)
        for(let i = 0;i < neighbors.length;i++){
            let item = neighbors[i]
            if(color[item] == 'white'){
                dfsVisit(item,color,cb)
            }
        }
        color[u] = 'black'
        if(cb){
            cb(u)
        }
    }
}

最短路径问题   

 

 

未完待续...

posted @ 2020-08-19 17:51  671_MrSix  阅读(166)  评论(0编辑  收藏  举报