// 使用字典来存储邻接表
var Dictionary = require('../map/dictionary');
// 引入队列,辅助广度搜索
var Queue = require('../queue/queue');
function Graph() {
var vertices = [];
var adjList = new Dictionary();
/**
* 添加顶点
* @param {*} v
*/
this.addVertex = function(v) {
vertices.push(v);
adjList.set(v,[]);
}
/**
* 连接顶点(无向图)
* @param {顶点} v
* @param {顶点} u
*/
this.addEdge = function (v,u) {
adjList.get(v).push(u);
adjList.get(u).push(v);
}
/**
* 广度优先遍历
* @param {遍历的起始顶点} v
* @param {回调函数} callback
*/
this.bfs = function (v, callback) {
var color = iniitialColor();
var queue = new Queue();
queue.enqueue(v);
while(!queue.isEmpty()) {
var u = queue.dequeue(), neighbors = adjList.get(u);
color[u] = 'grey';
neighbors.forEach(function (ele) {
if(color[ele] === 'white') {
color[ele] = 'grey';
queue.enqueue(ele);
}
});
color[u] = 'black';
if(callback) {
callback(u);
}
}
}
/**
* 深度优先遍历
* @param {回调函数} callback
*/
this.dfs = function (callback) {
var color = iniitialColor();
vertices.forEach(function (node) {
if(color[node] === 'white') {
dfsVisit(node, color, callback);
}
})
}
/**
* 访问顶点,每次迭代中选择一个未被访问的顶点进行深度优先遍历
* @param {前驱结点} node
* @param {当前全部顶点的状态} color
* @param {回调函数} callback
*/
var dfsVisit = function (node, color,callback) {
var neighbors = adjList.get(node);
color[node] ='grey';
if(callback) {
callback(node);
}
neighbors.forEach(function (u) {
if(color[u] === 'white') {
dfsVisit(u, color, callback);
}
});
color[node] = 'black';
}
/**
* 搜索的辅助函数
* 对顶点初始化,染上白色
* 当顶点第一次被发现时,染上灰色,防止重复添加
* 当顶点被访问过,染上黑色
*/
var iniitialColor = function() {
var color = [];
vertices.forEach(ele => {
color[ele] = 'white';
});
return color;
}
/**
* 利用BFS计算顶点间的最短距离
* @param {源顶点} v
*/
this.BFS = function (v) {
var queue = new Queue(),
color = iniitialColor(),
d = [],
pred = [];
queue.enqueue(v);
// 初始化
vertices.forEach(function (node) {
d[node] = 0;
pred[node] = null;
});
while(!queue.isEmpty()) {
var u = queue.dequeue(),
neighbors = adjList.get(u);
color[u] = 'grey';
neighbors.forEach(function (node) {
if(color[node] === 'white') {
color[node] = 'grey';
d[node] = d[u] + 1; // 累积距离
pred[node] = u; // 记录前驱顶点
queue.enqueue(node);
}
});
color[u] = 'black';
}
// 通过前驱结点,可以构建出最短路径
return {
distances: d,
predecessors:pred
}
}
this.toString = function () {
var s = '';
vertices.forEach(ele => {
s += ele + ' -> ';
var neighbors = adjList.get(ele);
neighbors.forEach(ele2 => {
s += ele2 + ' ';
});
s += '\n';
})
return s;
}
}
module.exports = Graph;
JavaScript数据结构与算法(八):图、图的遍历和搜索
最新推荐文章于 2022-07-26 19:12:15 发布