好久没js
1.顶点
//定义顶点 var Vertex = function (label) { this._label = label; this._wasVisited = false; }
2.图
//定义图 var Graph = function () { var max_vertx = 20; this.vertexList = new Array(max_vertx); this.adjMat = []; this.length = 0; for (var i = 0; i < max_vertx; i++) { this.adjMat.push([]); for (var j = 0; j < max_vertx; j++) { this.adjMat[i][j] = 0; } } };
3.添加顶点和边
//添加顶点 Graph.prototype.AddVertex = function (label) { var vertex = new Vertex(label); this.vertexList.push(vertex); this.length++; }; //添加边 Graph.prototype.AddEdge = function (start, end) { adjMat[start][end] = 1; adjMat[end][start] = 1; }
4.深度优先遍历
规则:
1.访问一个领接点未访问的顶点并标记为访问,然后放入栈中
2.如果1无法执行且栈不为空,则弹出一个顶点然后继续执行1
3.无法1,2均无法执行则结束遍历
so先定义一个栈
Stack
var Stack = function () { this._array = new Array(10); this.top = -1; } Stack.prototype.Push = function (obj) { this._array[++this.top] = obj; }; Stack.prototype.Peek = function () { return this._array[this.top]; }; Stack.prototype.Pop = function () { return this._array[this.top--]; }; Stack.prototype.IsEmpty = function () { return this.top == -1; };
(1)把第一个放入栈
if (this.length == 0) return; this.vertexList[0].wasVisited = true; this.vertexList[0].Display(); this.vertStack.Push(0);
var length = this.length; var adjMat = this.adjMat; var vertexList = this.vertexList; var unvisitedVertex = function (v) { for (var i = 0; i < length; i++) { if (adjMat[v][i] == 1 && !vertexList[i].wasVisited) return i; } return -1; }
while (!this.vertStack.IsEmpty()) { var v = unvisitedVertex(this.vertStack.Peek()); if (v == -1) this.vertStack.Pop(); else { this.vertexList[v].wasVisited = true; this.vertexList[v].Display(); this.vertStack.Push(v); } }
Test
var entity = new Graph(); //添加顶点 entity.AddVertex("A"); entity.AddVertex("B"); entity.AddVertex("C"); entity.AddVertex("D"); entity.AddVertex("E"); //添加边 entity.AddEdge(0, 1);//AB entity.AddEdge(1, 2); //BC entity.AddEdge(0, 3); //AD entity.AddEdge(3, 4); //DE entity.dfs();
5.广度优先遍历
规则:
1.访问当前点的所有邻接点,标记它,并放入队列中
2.如果邻接点访问完毕后,则从队列中取一个邻接点重复1步骤
3.当1和2完毕后则完成
先定义一个Queue
var Queue = function () { this.Max_Size = 10; this._array = new Array(this.Max_Size); this.head = 0; this.rear = -1; } Queue.prototype.Enqueue = function (obj) { this._array[++this.rear] = obj; }; Queue.prototype.Dequeue = function () { return this._array[this.head++]; }; Queue.prototype.IsEmpty = function () { return (this.rear + 1 == this.head || (this.head + this.Max_Size - 1 == this.rear)); };
bfs
1.标记第一个点
this.vertexList[0].wasVisited = true; this.vertexList[0].Display(); this.vertQueue.Enqueue(0);
2.当有邻接点则显示,否则则从队列中取
while (!this.vertQueue.IsEmpty()) { var v1 = this.vertQueue.Dequeue(); var v2; while ((v2=unvisitedVertex(v1))!=-1) { this.vertexList[v2].wasVisited = true; this.vertexList[v2].Display(); this.vertQueue.Enqueue(v2); } }
Graph.prototype.bfs = function () { if (this.length == 0) return; this.vertexList[0].wasVisited = true; this.vertexList[0].Display(); this.vertQueue.Enqueue(0); var length = this.length; var adjMat = this.adjMat; var vertexList = this.vertexList; var unvisitedVertex = function (v) { for (var i = 0; i < length; i++) { if (adjMat[v][i] == 1 && !vertexList[i].wasVisited) return i; } return -1; } while (!this.vertQueue.IsEmpty()) { var v1 = this.vertQueue.Dequeue(); var v2; while ((v2=unvisitedVertex(v1))!=-1) { this.vertexList[v2].wasVisited = true; this.vertexList[v2].Display(); this.vertQueue.Enqueue(v2); } } }
6.最小生成树
一个图的最小生成树可能有很多种,采用深度遍历.不同之处在于将当前值给记录下来,
与4比较
Graph.prototype.mst = function () { if (this.length == 0) return; this.vertexList[0].wasVisited = true; this.vertStack.Push(0); var length = this.length; var adjMat = this.adjMat; var vertexList = this.vertexList; var unvisitedVertex = function (v) { for (var i = 0; i < length; i++) { if (adjMat[v][i] == 1 && !vertexList[i].wasVisited) return i; } return -1; } while (!this.vertStack.IsEmpty()) { var currentVertex = this.vertStack.Peek(); var v = unvisitedVertex(currentVertex); if (v == -1) this.vertStack.Pop(); else { this.vertexList[v].wasVisited = true; this.vertexList[currentVertex].Display(); this.vertexList[v].Display(); this.vertStack.Push(v); } } }
7.拓扑排序
在有向图的情况下,如课程选择,有先后顺序原则.
规则:
1.找到一个没有后继的顶点,删除这个顶点并做标记,并重复,直到删除完为止
(1)有向图只需要添加一边
Graph.prototype.AddSingleEdge = function (start, end) { this.adjMat[start][end] = 1; };
(2)delete
Graph.prototype.DeleteVertex = function (index) { var nVerts = this.length; if (index != this.length - 1) { //move for (var i = index; i < nVerts - 1; i++) { this.vertexList[i] = this.vertexList[i + 1]; } //delete arrry from table //move up for (var i = index; i < nVerts - 1; i++) { this.moveRowUp(i, nVerts); } //move left for (var i = index; i < nVerts - 1; i++) { this.moveColLeft(i, nVerts-1); } } this.length--; }; Graph.prototype.moveRowUp=function(row, length) { for(var col=0; col<length; col++) this.adjMat[row][col] = this.adjMat[row+1][col]; } Graph.prototype.moveColLeft = function (col, length) { for (var row = 0; row < length; row++) this.adjMat[row][col] = this.adjMat[row][col + 1]; }
(3)topo
Graph.prototype.Topo = function () { while (this.length > 0) { var currentVertex = this.noSuccessors(); if (currentVertex == -1) return; this.sortArray[this.length-1]=this.vertexList[currentVertex]._label; this.DeleteVertex(currentVertex); } }; Graph.prototype.noSuccessors = function () { var isEdge = false; for (var i = 0; i < this.length; i++) { isEdge = false; for (var j = 0; j < this.length; j++) { if (this.adjMat[i][j] > 0) { isEdge = true; break; } } if (!isEdge) return i; } return -1; };
8.Warshall算法