图结构
什么是图?
图结构是一种与树结构有些相似的数据结构,图论是数学的一个分支,并且在数学的概念上,树是图的一种,它以图为研究对象,研究顶点和边组成的图形的数学理论和方法,主要研究的目的是事物之间的关系,顶点代表事物,边代表两个事物间的关系。
图的特点:
一组顶点:通常用V(Vertex)表示顶点的集合
一组边:通常用E(Edge)表示边的集合
边是顶点和顶点之间的连线
边可以是有向的,也可以是无向的,A----B表示无向的,A--->表示有向的
图的表示
邻接矩阵:让每个节点和一个整数相关联,该整数作为数组的下标值,用一个二维数组来表示顶点之间的连接
邻接表:邻接表由图中每个顶点以及顶点相邻的顶点列表组成,这个列表有很多中方式来存储:数组/链表/字典(哈希表)都可以
封装图结构
添加方法
<!--引入字典--> <script src="字典.js"></script> function Graph() { this.vertexes = [] //顶点 this.edges = new Dictionary() //边 //添加顶点的方法 Graph.prototype.addVertex = function (v) { this.vertexes.push(v) this.edges.set(v, []) } // 添加边的方法 Graph.prototype.addEdge = function (v1, v2) { this.edges.get(v1).push(v2) this.edges.get(v2).push(v1) } Graph.prototype.toString = function () { var result = '' for (var i = 0; i < this.vertexes.length; i++) { result += this.vertexes[i] + '->' var vedges = this.edges.get(this.vertexes[i]) for(var j=0;j < vedges.length; j++) { result += vedges[j]+ ' ' } result += "\n" } return result } }
测试:
var g = new Graph() //添加顶点 var vert = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for (var i = 0; i < vert.length; i++) { g.addVertex(vert[i]) } //添加边 g.addEdge('a', 'b') g.addEdge('a', 'c') g.addEdge('a', 'd') g.addEdge('c', 'd') g.addEdge('c', 'g') g.addEdge('d', 'g') g.addEdge('d', 'h') g.addEdge('b', 'e') g.addEdge('b', 'f') g.addEdge('e', 'i') alert(g.toString())
图的遍历
广度优先搜索(Breadth-First Search,BFS),基于队列,入队列的顶点先被探索
深度优先搜索(Deapth-First Search,DFS),基于栈或使用递归,通过将顶点存入栈中,顶点是沿着路径被探索的,存在新的相邻顶点就去访问
两种遍历算法,都需要明确指明第一个被访问的顶点
广度优先搜索的实现
<!--引入字典--> <script src="字典.js"></script> <!--引入队列--> <script src="queue.js"></script> <script> function Graph() { this.vertexes = [] //顶点 this.edges = new Dictionary() //边 //添加顶点的方法 Graph.prototype.addVertex = function (v) { this.vertexes.push(v) this.edges.set(v, []) } // 添加边的方法 Graph.prototype.addEdge = function (v1, v2) { this.edges.get(v1).push(v2) this.edges.get(v2).push(v1) } Graph.prototype.toString = function () { var result = '' for (var i = 0; i < this.vertexes.length; i++) { result += this.vertexes[i] + '->' var vedges = this.edges.get(this.vertexes[i]) for (var j = 0; j < vedges.length; j++) { result += vedges[j] + ' ' } result += "\n" } return result } Graph.prototype.initColor = function () { var color = [] for (var i = 0; i < this.vertexes.length; i++) { color[this.vertexes[i]] = 'white' } return color } //实现广度优先搜索 Graph.prototype.bfs = function (initV, handler) { //初始化颜色 var color = this.initColor() //创建队列 var queue = new Queue() //将顶点加入队列中 queue.enqueue(initV) //循环从队列中取出元素 while (!queue.isEmpty()) { //从队列中取出顶点 var v = queue.dequeue() //获取和顶点相连的其他顶点 var vList = this.edges.get(v) //将v的颜色变为灰色 color[v] = 'gray' //遍历所有顶点,加入队列中 for (var i = 0; i < vList.length; i++) { var e = vList[i] if (color[e] == 'white') { color[e] = 'gray' queue.enqueue(e) } } //已经被探测,并且访问 handler(v) //将顶点设置为黑色 color[v] = 'black' } } } var g = new Graph() //添加顶点 var vert = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for (var i = 0; i < vert.length; i++) { g.addVertex(vert[i]) } //添加边 g.addEdge('a', 'b') g.addEdge('a', 'c') g.addEdge('a', 'd') g.addEdge('c', 'd') g.addEdge('c', 'g') g.addEdge('d', 'g') g.addEdge('d', 'h') g.addEdge('b', 'e') g.addEdge('b', 'f') g.addEdge('e', 'i') // alert(g.toString()) var result= '' g.bfs(g.vertexes[0],function (v) { result += v+' ' }) alert(result)
深度优先搜索的实现
<!--引入字典--> <script src="字典.js"></script> <!--引入队列--> <script src="queue.js"></script> <script> function Graph() { this.vertexes = [] //顶点 this.edges = new Dictionary() //边 //添加顶点的方法 Graph.prototype.addVertex = function (v) { this.vertexes.push(v) this.edges.set(v, []) } // 添加边的方法 Graph.prototype.addEdge = function (v1, v2) { this.edges.get(v1).push(v2) this.edges.get(v2).push(v1) } Graph.prototype.toString = function () { var result = '' for (var i = 0; i < this.vertexes.length; i++) { result += this.vertexes[i] + '->' var vedges = this.edges.get(this.vertexes[i]) for (var j = 0; j < vedges.length; j++) { result += vedges[j] + ' ' } result += "\n" } return result } Graph.prototype.initColor = function () { var color = [] for (var i = 0; i < this.vertexes.length; i++) { color[this.vertexes[i]] = 'white' } return color }//深度优先搜索 Graph.prototype.dfs = function (initV,handler) { //初始化颜色 var colors = this.initColor() //从某个顶点开始递归访问 this.dfsVisit(initV,colors,handler) } Graph.prototype.dfsVisit = function (v,colors,handler) { //将颜色设置为灰色 colors[v] = 'gray' //处理顶点 handler(v) //访问v相连的其他顶点 var vList = this.edges.get(v) for(var i=0;i<vList.length;i++){ var e = vList[i] if(colors[e] == 'white') { this.dfsVisit(e,colors,handler) } } //将v设置为黑色 colors[v] = 'black' } } var g = new Graph() //添加顶点 var vert = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for (var i = 0; i < vert.length; i++) { g.addVertex(vert[i]) } //添加边 g.addEdge('a', 'b') g.addEdge('a', 'c') g.addEdge('a', 'd') g.addEdge('c', 'd') g.addEdge('c', 'g') g.addEdge('d', 'g') g.addEdge('d', 'h') g.addEdge('b', 'e') g.addEdge('b', 'f') g.addEdge('e', 'i') // alert(g.toString()) var result= '' g.dfs(g.vertexes[0],function (v) { result += v+' ' }) alert(result) </script>