一、添加顶点:用数组存储图中全部顶点的名字算法
this.addVertex = function(v) { vertices.push(v); adjList[v] = []; }
二、添加边 :用对象的形式存储每一个顶点包含的边数组
this.addEdge = function(a,b) { adjList[a].push(b); adjList[b].push(a); }
一、打印数据结构
this.print= function() { let s = '\n'; for(let i=0; i<vertices.length; i++) { let dingdian = vertices[i]; s += dingdian + '=>'; let bian = adjList[dingdian]; for(let j=0; j<bian.length; j++) { s += bian[j]; } s += '\n'; } console.log(s); }
二、广度优先遍历(采用队列数据结构)函数
let initColor = function() { let color = []; for(let i=1; i<vertices.length; i++) { color[vertices[i]] = 'white'; } return color; }; //广度优先遍历(采用队列数据结构) this.bfs = function(v,callback) { let color = initColor(); let queue = new Queue; queue.enqueue(v); while(!queue.isEmpty()) { let now = queue.dequeue(); let bian = adjList[now]; for(let i=0; i<bian.length; i++) { let w = bian[i]; if(color[w] === 'white') { //未发现的所有入列,而且标识为已发现 color[w] = 'grey'; queue.enqueue(w); } } color[now] = 'black'; if(callback) { callback(now); } } };
三、深度优先遍历测试
this.dfs = function(v,callback) { let color = initColor(); //初始化颜色 dfsVisite(v,color,callback); } let dfsVisite = function(u,color,callback) { color[u] = 'grey'; let n = adjList[u]; for(let i=0; i<n.length; i++) { let w = n[i]; if(color[w] == 'white') { dfsVisite(w,color,callback); } } color[u] = 'black'; if(callback) { callback(u); } };
一、基于广度优先的最短路径生成算法ui
let zuiduan = function(from,to){ let v = to; //设置当前点 let s = g.BFS(from); let path = new Stack(); while(v !== from) { path.push(v); v = s.pred[v]; } path.push(v); let str = ''; while(!path.isEmpty()) { str += path.pop() + '-'; } str = str.slice(0,str.length-1); console.log(str); }
//栈 let Stack = function() { let items = []; //添加元素 this.push = function(element) { items.push(element); }; //删除元素 this.pop = function() { return items.pop(); }; //查看栈顶元素 this.peek = function() { return items[items.lenght -1]; }; //检查栈是否为空 this.isEmpty = function() { return items.length == 0; } //栈的长度 this.size = function() { return items.length; } //清空栈 this.clear = function() { items = []; } //打印栈元素 this.print = function() { console.log(items.toString()); } }; //队列 let Queue= function() { let items = []; //入队 this.enqueue = function(element) { items.push(element); }; //出队 this.dequeue = function() { return items.shift(); }; //查看队列头 this.front = function() { return items[0]; }; //检查队列是否为空 this.isEmpty = function() { return items.length === 0; }; //队列大小 this.size = function() { return items.length; }; }; //图 let Graph = function() { //顶点(用数组存储图中全部顶点的名字) let vertices = []; //边(用对象的形式存储每一个顶点包含的边) let adjList = {}; //一、添加顶点 this.addVertex = function(v) { vertices.push(v); adjList[v] = []; } //二、添加边 this.addEdge = function(a,b) { adjList[a].push(b); adjList[b].push(a); } //打印 this.print= function() { let s = '\n'; for(let i=0; i<vertices.length; i++) { let dingdian = vertices[i]; s += dingdian + '=>'; let bian = adjList[dingdian]; for(let j=0; j<bian.length; j++) { s += bian[j]; } s += '\n'; } console.log(s); } /* 广度优先遍历: white 未发现 grey 已发现未探索 black 已探索 */ //初始化颜色 let initColor = function() { let color = []; for(let i=1; i<vertices.length; i++) { color[vertices[i]] = 'white'; } return color; }; //广度优先遍历(采用队列数据结构) this.bfs = function(v,callback) { let color = initColor(); let queue = new Queue; queue.enqueue(v); while(!queue.isEmpty()) { let now = queue.dequeue(); let bian = adjList[now]; for(let i=0; i<bian.length; i++) { let w = bian[i]; if(color[w] === 'white') { //未发现的所有入列,而且标识为已发现 color[w] = 'grey'; queue.enqueue(w); } } color[now] = 'black'; if(callback) { callback(now); } } }; //广度优先算法(d:距离 prev:回溯点) this.BFS = function(v) { let color = initColor(); let queue = new Queue; queue.enqueue(v); //初始化 let d = {}; let pred = {}; for(let i=0; i<vertices.length; i++) { d[vertices[i]] = 0; pred[vertices[i]] = null; } while(!queue.isEmpty()) { let now = queue.dequeue(); let bian = adjList[now]; for(let i=0; i<bian.length; i++) { let w = bian[i]; if(color[w] === 'white') { color[w] = 'grey';//未发现的所有入列,而且标识为已发现 //设置回溯点 pred[w] = now; d[w] = d[now] + 1; queue.enqueue(w); } } color[now] = 'black'; } return { pred : pred, d : d }; }; //深度优先算法 this.dfs = function(v,callback) { let color = initColor(); //初始化颜色 dfsVisite(v,color,callback); } let dfsVisite = function(u,color,callback) { color[u] = 'grey'; let n = adjList[u]; for(let i=0; i<n.length; i++) { let w = n[i]; if(color[w] == 'white') { dfsVisite(w,color,callback); } } color[u] = 'black'; if(callback) { callback(u); } }; }; //广度优先算法解决最短路径问题 (保证每一个点的回溯点是最短的) let zuiduan = function(from,to){ let v = to; //设置当前点 let s = g.BFS(from); let path = new Stack(); while(v !== from) { path.push(v); v = s.pred[v]; } path.push(v); let str = ''; while(!path.isEmpty()) { str += path.pop() + '-'; } str = str.slice(0,str.length-1); console.log(str); }
结果测试this
let g =new Graph; g.addVertex('A'); g.addVertex('B'); g.addVertex('C'); g.addVertex('D'); g.addVertex('E'); g.addVertex('F'); g.addEdge('A','B'); g.addEdge('A','C'); g.addEdge('A','D'); g.addEdge('C','D'); g.addEdge('B','E'); g.addEdge('F','B'); g.print(); //A=>BCD B=>AEF C=>AD D=>AC E=>B F=>B g.bfs('A', function(e) {console.log(e)}); //A B C D E F g.BFS('A'); //d:{A:0, B:1, C:1, D:1, E:2} pred:{A:null, B:"A", C:"A", D:"A", E:"B"} g.dfs('A',function(e){console.log(e);}); //E F B D C A zuiduan('A','E') //A-B-F