图的表示方式
- 主要以无向图学习
如何用JS表示邻接图?
- 为什么不用类定义?因为结构过于复杂
let Graph = function(){
//存储顶点
let vertices = []
//存储边
let adjList = {}
//1.添加顶点
this.addVertex = function(v){
vertices.push(v)
adjList[v] = []
}
// 2.添加边
this.addEdge = function(a,b){
adjList[a].push(b)
adjList[b].push(a)
}
}
let g = new Graph()
g.addVertex('A')
g.addVertex('B')
g.addEdge('A','B')
图遍历:广度优先和深度优先
广度优先遍历
- 采用队列的方法
- 使用数组的
push()
和shif()
方法模拟队列
function initColor(){
let color = {}
for(let i = 0;i<vertices.length;i++){
color[vertices[i]] = 'white'
}
return color
}
this.bfs = function(v,callback){
let color = initColor()
let queue = []
// 入队
queue.push(v)
while(!queue.length){
let now = queue.shift()
let bian = adjList[now]
for(let i = 0;i < bian.length;i++){
let w = bian[i]
if (color[i] == 'white'){
//未发现的全部入列 并且标识为已发现
color[i] = 'grey'
queue.push(w)
}
}
color[now] = 'black'
if(callback){
callback(now)
}
}
}
最短路径问题
- 设置两个对象记录起点到任意点的距离和任意一个点的回溯点
let d = {}
let pred = {}
- 初始化
for(let i = 0;i < vertices.length;i++){
d[vertices[i]] = 0
pred[vertices[i]] = null
}
- 设置回溯点
if (color[i] == 'white'){
color[i] = 'grey'
// 设置回溯点
pred[w] = now
d[w] =d[now] + 1
queue.push(w)
}
- 广度优先算法能保证每个回溯点是最近的
let s = g.bfs()
let stack = []
var best_short = function(from,to){
let v = to
while(v !== from){
stack.push(v)
v = s.pred[to]
}
while(stack.length){
console.log(stack.pop());
}
}
深度优先遍历DFS
- 主要使用递归
let dfsVisit = function(u,color,callback){
color[u] = 'gery'
let n = adjList[u]
for(let i = 0;i < n.length;i++){
let w = n[i]
if(color[w] == 'white'){
dfsVisit(w,color,callback)
}
}
color[u] = 'black'
}
this.dfs = function (v, color, callback){
color = initColor()
dfsVisit(v,color,callback)
}