什么是图
图用来表示顶点与顶点间的关系
术语
- 顶点:表示图中的一个结点。
- 边:顶点与顶点间的连线。
- 相邻顶点:一条边连接的顶点。
- 度:一个顶点连接的边的条数。
- 路径:路径是顶点
v1
,v2
…,vn
的一个连续序列。 - 根据边的有无方向分为:无向图 和 有向图。
图的表示
顶点表示
顶点的表示抽象成数字或者字母表示。
边的表示
-
邻接矩阵:两个顶点间的边用1表示,无边连接的两个顶点间用0表示。当为带权图时,可以为权重。
-
当图为稀疏图时(顶点很多,边较少)。要用大量的0 表示两个顶点之间无边连接,已造成空间浪费。
图的封装
创建图类
- 用一个
数组
存储所有的顶点 - 用
字典结构
来存储边的信息,key:顶点
,value是一个数组
,存储的是与该顶点连接的顶点。字典结构的封装 - 方法:
addVertex(val)
添加一个节点addEdge(val1, val2)
添加一条边toString()
输出一个顶点与其相邻的节点
function Graph() {
this.vertexes = [];// 存储顶点
this.dictonary = new Dictonary();//存储边信息
this.dfsResult = '';// 深度优先的结果
this.bfsResult = '';// 广度优先的结果
}
// 添加一个节点
Graph.prototype.addVertex = function(val) {
this.vertexes.push(val);
this.dictonary.set(val, []);
};
//添加一条边
Graph.prototype.addEdge = function(val1, val2) {
this.dictonary.get(val1).push(val2);
this.dictonary.get(val2).push(val1);
};
// 颜色初始化
Graph.prototype.initializeColor = function() {
const color = [];
this.vertexes.forEach(value => {
color[value] = 'white';
});
return color;
};
//toString()
Graph.prototype.toString = function() {
let result = '';
this.vertexes.forEach(key => {
result += key + ' -> '
this.dictonary.get(key).forEach(value => {
result += value + ' ';
});
result += '\n';
});
return result;
};
代码测试
const graph = new Graph();
graph.addVertex('A');graph.addVertex('B');
graph.addVertex('C');graph.addVertex('D');
graph.addVertex('E');graph.addVertex('F');
graph.addVertex('G');graph.addVertex('H');
graph.addVertex('I');graph.addEdge('A', 'B');
graph.addEdge('A', 'C');graph.addEdge('A', 'D');
graph.addEdge('B', 'E');graph.addEdge('B', 'F');
graph.addEdge('C', 'D');graph.addEdge('C', 'G');
graph.addEdge('D', 'G');graph.addEdge('D', 'H');
graph.addEdge('E', 'I');
console.log(graph.toString());
图的遍历
深度优先搜索
- 深度优先搜索算法将会从第一个指定的顶点开始遍历图,沿着路径知道这条路径最后被访问了。
- 接着原路回退并探索吓一条路径。
- 图解 DFS
代码实现
利用递归实现
//深度优先
Graph.prototype.dfs = function(startV) {
const color = this.initializeColor();
this.dfsVisit(startV, color);
return this.dfsResult;
}
Graph.prototype.dfsVisit = function(vertex, color) {
const current = this.dictonary.get(vertex);
color[vertex] = 'gray';
this.dfsResult += vertex + ' ';
for (let i = 0; i < current.length; i++) {
if (color[current[i]] === 'white') {
this.dfsVisit(current[i], color);
}
}
color[vertex] = 'black';
};
深度优先搜索代码测试
console.log(graph.dfs('A'));
// A B E I F C D G H
广度优先搜索
- 广度优先算法会从指定的第一个顶点开始遍历图,先访问其所有的相邻点,就像一次访问图的一层。换句话说,就是先宽后深的访问顶点。
- 图解 BFS
代码实现
利用队列实现
// 广度优先
Graph.prototype.bfs = function(startV) {
const color = this.initializeColor();
let queue = new Queue();// 队列结构的定义
queue.enqueue(startV);
color[startV] = 'gary';
while (!queue.isEmpty()) {
const v = queue.dequeue();
this.bfsResult += v + ' ';
let outV = this.dictonary.get(v);
for (let i = 0; i < outV.length; i++) {
if (color[outV[i]] === 'white') {
color[outV[i]] = 'gary';
queue.enqueue(outV[i]);
}
}
color[v] = 'black';
}
return this.bfsResult;
};
广度优先搜索代码测试
console.log(graph.bfs('A'));
// A B C D E F G H I