We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
图是一种复杂的非线性结构,它由边(边Edge)和点(顶点Vertex)组成。一条边连接的两个点称为相邻顶点。
G = (V, E)
图分为:
本文探讨的是无向图
图的表示一般有以下两种:
arr[i][j] = 1
arr[i][j] = 0
下面声明图类,Vertex 用数组结构表示,Edge 用 map结构表示
function Graph() { this.vertices = [] // 顶点集合 this.edges = new Map() // 边集合 } Graph.prototype.addVertex = function(v) { // 添加顶点方法 this.vertices.push(v) this.edges.set(v, []) } Graph.prototype.addEdge = function(v, w) { // 添加边方法 let vEdge = this.edges.get(v) vEdge.push(w) let wEdge = this.edges.get(w) wEdge.push(v) this.edges.set(v, vEdge) this.edges.set(w, wEdge) } Graph.prototype.toString = function() { var s = '' for (var i=0; i<this.vertices.length; i++) { s += this.vertices[i] + ' -> ' var neighors = this.edges.get(this.vertices[i]) for (var j=0; j<neighors.length; j++) { s += neighors[j] + ' ' } s += '\n' } return s }
测试:
var graph = new Graph() var vertices = [1, 2, 3, 4, 5] for (var i=0; i<vertices.length; i++) { graph.addVertex(vertices[i]) } graph.addEdge(1, 4); //增加边 graph.addEdge(1, 3); graph.addEdge(2, 3); graph.addEdge(2, 5); console.log(graph.toString()) // 1 -> 4 3 // 2 -> 3 5 // 3 -> 1 2 // 4 -> 1 // 5 -> 2
测试成功
两种遍历算法:
深度优先遍历(Depth-First-Search),是搜索算法的一种,它沿着树的深度遍历树的节点,尽可能深地搜索树的分支。当节点v的所有边都已被探寻过,将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已探寻源节点到其他所有节点为止,如果还有未被发现的节点,则选择其中一个未被发现的节点为源节点并重复以上操作,直到所有节点都被探寻完成。
简单的说,DFS就是从图中的一个节点开始追溯,直到最后一个节点,然后回溯,继续追溯下一条路径,直到到达所有的节点,如此往复,直到没有路径为止。
DFS 可以产生相应图的拓扑排序表,利用拓扑排序表可以解决很多问题,例如最大路径问题。一般用堆数据结构来辅助实现DFS算法。
注意:深度DFS属于盲目搜索,无法保证搜索到的路径为最短路径,也不是在搜索特定的路径,而是通过搜索来查看图中有哪些路径可以选择。
步骤:
实现:
Graph.prototype.dfs = function() { var marked = [] for (var i=0; i<this.vertices.length; i++) { if (!marked[this.vertices[i]]) { dfsVisit(this.vertices[i]) } } function dfsVisit(u) { let edges = this.edges marked[u] = true console.log(u) var neighbors = edges.get(u) for (var i=0; i<neighbors.length; i++) { var w = neighbors[i] if (!marked[w]) { dfsVisit(w) } } } }
graph.dfs() // 1 // 4 // 3 // 2 // 5
广度优先遍历(Breadth-First-Search)是从根节点开始,沿着图的宽度遍历节点,如果所有节点均被访问过,则算法终止,BFS 同样属于盲目搜索,一般用队列数据结构来辅助实现BFS
BFS从一个节点开始,尝试访问尽可能靠近它的目标节点。本质上这种遍历在图上是逐层移动的,首先检查最靠近第一个节点的层,再逐渐向下移动到离起始节点最远的层
Graph.prototype.bfs = function(v) { var queue = [], marked = [] marked[v] = true queue.push(v) // 添加到队尾 while(queue.length > 0) { var s = queue.shift() // 从队首移除 if (this.edges.has(s)) { console.log('visited vertex: ', s) } let neighbors = this.edges.get(s) for(let i=0;i<neighbors.length;i++) { var w = neighbors[i] if (!marked[w]) { marked[w] = true queue.push(w) } } } }
graph.bfs(1) // visited vertex: 1 // visited vertex: 4 // visited vertex: 3 // visited vertex: 2 // visited vertex: 5
本文始发于我的博客:深度优先遍历与广度优先遍历
Originally posted by @sisterAn in #9 (comment)
为什么手动添加节点,不懂为什么这么做,按照你说的 相邻节点和边的概念理解,边的对应的另一个就是相邻节点,故直接在 addEdge 方法是直接更新顶点集合就好了。 以下是我根据你代码改编的:
function Graph() { this.vertices = [] // 顶点集合 ---- 在默认二叉树的数据结构下,应该类似于各个节点 this.edges = new Map() // 边集合 ---- 各个节点与其他节点直接关联的集合 } Graph.prototype.addVertex = function(v) { // 添加顶点方法 this.vertices.push(v) this.edges.set(v, []) // 初始化新增顶点相关的邻接表 } Graph.prototype.addEdge = function(v, w) { // 添加边方法 let Vquery = this.edges.get(v) // 获取 v顶点 对应的邻接表 Vquery.push(w) // 同时,往w的领接表中添加v,这两者相互关联,链接。于此同时,w作为顶点,需要添加到 顶点集合中,当然要注意去重 // 更新顶点集合 this.vertices.includes(w) || this.addVertex(w) let Wquery = this.edges.get(w) Wquery.push(v) // 更新二者的邻接表 this.edges.set(v, Vquery) this.edges.set(w, Wquery) } Graph.prototype.toString = function() { // 根据顶点集合打印出其对应的边集合 let str = '' this.vertices.forEach(vertice => { str += vertice + ' --> ' this.edges.get(vertice).forEach(edge => { str += edge + ' ' }) str += '\n' }) return str } let data = new Graph() data.addVertex('root') data.addEdge('root', 'a') data.addEdge('root', 'b') data.addEdge('a', 'a11') data.addEdge('a', 'a12') data.addEdge('b', 'b11') console.log(data.toString()) // root --> a b // a --> root a11 a12 // b --> root b11 // a11 --> a // a12 --> a // b11 --> b
The text was updated successfully, but these errors were encountered:
No branches or pull requests
图
图是一种复杂的非线性结构,它由边(边Edge)和点(顶点Vertex)组成。一条边连接的两个点称为相邻顶点。
图分为:
本文探讨的是无向图
图的表示
图的表示一般有以下两种:
arr[i][j] = 1
表示节点 i 与节点 j 之间有边,arr[i][j] = 0
表示节点 i 与节点 j 之间没有边创建图
下面声明图类,Vertex 用数组结构表示,Edge 用 map结构表示
测试:
测试成功
图的遍历
两种遍历算法:
深度优先遍历(DFS)
深度优先遍历(Depth-First-Search),是搜索算法的一种,它沿着树的深度遍历树的节点,尽可能深地搜索树的分支。当节点v的所有边都已被探寻过,将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已探寻源节点到其他所有节点为止,如果还有未被发现的节点,则选择其中一个未被发现的节点为源节点并重复以上操作,直到所有节点都被探寻完成。
简单的说,DFS就是从图中的一个节点开始追溯,直到最后一个节点,然后回溯,继续追溯下一条路径,直到到达所有的节点,如此往复,直到没有路径为止。
DFS 可以产生相应图的拓扑排序表,利用拓扑排序表可以解决很多问题,例如最大路径问题。一般用堆数据结构来辅助实现DFS算法。
注意:深度DFS属于盲目搜索,无法保证搜索到的路径为最短路径,也不是在搜索特定的路径,而是通过搜索来查看图中有哪些路径可以选择。
步骤:
实现:
测试:
测试成功
广度优先遍历(BFS)
广度优先遍历(Breadth-First-Search)是从根节点开始,沿着图的宽度遍历节点,如果所有节点均被访问过,则算法终止,BFS 同样属于盲目搜索,一般用队列数据结构来辅助实现BFS
BFS从一个节点开始,尝试访问尽可能靠近它的目标节点。本质上这种遍历在图上是逐层移动的,首先检查最靠近第一个节点的层,再逐渐向下移动到离起始节点最远的层
步骤:
实现:
测试:
测试成功
本文始发于我的博客:深度优先遍历与广度优先遍历
Originally posted by @sisterAn in #9 (comment)
为什么手动添加节点,不懂为什么这么做,按照你说的 相邻节点和边的概念理解,边的对应的另一个就是相邻节点,故直接在 addEdge 方法是直接更新顶点集合就好了。
以下是我根据你代码改编的:
The text was updated successfully, but these errors were encountered: