图
图是网络结构抽象模型。图是一组由边连接的节点(或顶点)。
一个图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) } } }
最短路径问题
未完待续...
以自己现在的努力程度,还没有资格和别人拼天赋