一、添加頂點:用數組存儲圖中全部頂點的名字算法
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