JavaScript实现数据结构与算法(五)图结构
- (五)图论
- 1. 图的相关概念
- 1.1 什么是图
- 1.2 图的现实案例
- 1.3 图结构的特点
- 1.4 图的术语
- 1.4.1 顶点
- 1.4.2 度
- 1.4.3 路径
- 1.4.4 简单路径
- 1.4.5 回路
- 1.4.6 无向图
- 1.4.7 有向图
- 1.4.8 无权图
- 1.4.9 带权图
- 2. 图的表示
- 2.1 邻接矩阵
- 2.1.1 邻接矩阵的表示方法
- 2.1.2 邻接矩阵的缺点
- 2.2 邻接表
- 2.2.1 表示方法
- 2.2.2 解析
- 2.2.3 问题
- 2.2.4 添加边
- 2.2.5 代码实现
- 2.3 关联矩阵
- 3. 自定义图
- 4. 图的遍历
- 4.1 广度优先搜素(BFS)
- 4.1.1 思路
- 4.1.2 思想与实现方法
- 4.2 深度优先搜素(DFS)
- 4.2.1 思路
- 4.2.2 思想与实现方法
- 4.3 实现代码
(五)图论
1. 图的相关概念
1.1 什么是图
1.2 图的现实案例
1.3 图结构的特点
1.4 图的术语
1.4.1 顶点
1.4.2 度
1.4.3 路径
1.4.4 简单路径
1.4.5 回路
1.4.6 无向图
1.4.7 有向图
1.4.8 无权图
1.4.9 带权图
2. 图的表示
2.1 邻接矩阵
2.1.1 邻接矩阵的表示方法
2.1.2 邻接矩阵的缺点
2.2 邻接表
2.2.1 表示方法
2.2.2 解析
2.2.3 问题
2.2.4 添加边
2.2.5 代码实现
(1)代码部分
// 封装图结构
function Graph() {
// 属性:定点(数组)/边(字典)
this.vertexes = []; // 定点
this.edges = new Dictionary(); // 边
// 方法
// 添加方法
// 1. 添加顶点的方法
Graph.prototype.addVertex = function (v) {
this.vertexes.push(v);
this.edges.set(v,[]);
};
// 2. 添加边的方法
Graph.prototype.addEdge = function (v1,v2) {
this.edges.get(v1).push(v2);
this.edges.get(v2).push(v1);
};
// 3. 实现toString方法
Graph.prototype.toString = function () {
// 1. 定义字符串,保存最终的结果
var resultString = "";
// 2. 遍历所有的顶点,以及顶点对应的边
for (var i = 0 ; i < this.vertexes.length; i++){
resultString += this.vertexes[i] + "->";
var vEdges = this.edges.get(this.vertexes[i]);
for (var j = 0; j < vEdges.length; j++){
resultString += vEdges[j] + " ";
};
resultString += "\n";
};
return resultString;
}
};
(2)测试代码
// 测试代码
// 1. 创建图结构
var g =new Graph();
// 2. 添加顶点
var myVertexes = ['A','B','C','D','E','F','G','H','I'];
for (var i = 0; i < myVertexes.length ; i++){
g.addVertex(myVertexes[i]);
};
// 3.添加边
g.addEdge('A','B');
g.addEdge('A','C');
g.addEdge('A','D');
g.addEdge('C','D');
g.addEdge('C','G');
g.addEdge('D','G');
g.addEdge('D','H');
g.addEdge('B','E');
g.addEdge('B','F');
g.addEdge('E','I');
alert('aaa');
// 4. 测试结果
alert(g);
(3)运行结果
2.3 关联矩阵
3. 自定义图
4. 图的遍历
思想:
4.1 广度优先搜素(BFS)
需要明确指定第一个被访问的顶点
4.1.1 思路
4.1.2 思想与实现方法
4.2 深度优先搜素(DFS)
需要明确指定第一个被访问的顶点
4.2.1 思路
4.2.2 思想与实现方法
4.3 实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图结构</title>
</head>
<body>
<script src="dict.js"></script>
<script src="queue.js"></script>
<script>
// 封装图结构
function Graph() {
// 属性:定点(数组)/边(字典)
this.vertexes = []; // 定点
this.edges = new Dictionary(); // 边
// 方法
// 添加方法
// 1. 添加顶点的方法
Graph.prototype.addVertex = function (v) {
this.vertexes.push(v);
this.edges.set(v,[]);
};
// 2. 添加边的方法
Graph.prototype.addEdge = function (v1,v2) {
this.edges.get(v1).push(v2);
this.edges.get(v2).push(v1);
};
// 3. 实现toString方法
Graph.prototype.toString = function () {
// 1. 定义字符串,保存最终的结果
var resultString = "";
// 2. 遍历所有的顶点,以及顶点对应的边
for (var i = 0 ; i < this.vertexes.length; i++){
resultString += this.vertexes[i] + "->";
var vEdges = this.edges.get(this.vertexes[i]);
for (var j = 0; j < vEdges.length; j++){
resultString += vEdges[j] + " ";
};
resultString += "\n";
};
return resultString;
};
// 初始化状态颜色
Graph.prototype.initializeColor = function () {
var colors = [];
for (var i = 0 ;i < this.vertexes.length; i++){
colors[this.vertexes[i]] = "white";
}
return colors;
};
// 实现广度优先搜索(BFS)
Graph.prototype.bfs = function (initV,handler) {
// 1. 初始化颜色
var colors = this.initializeColor();
// 2. 创建队列
var queue = new Queue();
// 3. 将顶点加入到队列中
queue.enqueue(initV);
// 4. 循环从队列中取出元素
while(!queue.isEmpty()){
// 4.1 从队列中取出一个顶点
var v = queue.dequeue();
// 4.2 获取和顶点相连的其他顶点
var vList = this.edges.get(v);
// 4.3 将v的颜色设置成灰色
colors[v] = 'gray';
// 4.4 遍历所有的顶点,并且加入到队列中
for (var i = 0; i < vList.length; i++){
var e = vList[i];
if(colors[e] == 'white'){
colors[e] = 'gray';
queue.enqueue(e);
}
};
// 4.5 v已经被探测,并且访问顶点
handler(v);
// 4.6 将顶点设置为黑色
colors[v] = 'black';
}
};
// 实现深度优先搜索(DFS)
Graph.prototype.dfs = function (initV,handler) {
// 1. 初始化颜色
var colors = this.initializeColor();
// 2. 创建队列
var queue = new Queue();
// 3. 将顶点加入到队列中
queue.enqueue(initV);
// 4. 循环从队列中取出元素
while(!queue.isEmpty()){
// 4.1 从队列中取出一个顶点
var v = queue.dequeue();
// 4.2 从某个顶点开始依次递归访问
this.dfsVisit(v,colors,handler);
}
};
Graph.prototype.dfsVisit = function (v,colors,handler) {
// 1. 将颜色设置为灰色
colors[v] = "gray";
// 2. 处理v顶点
handler(v);
// 3. 访问v相连的顶点
var vList = this.edges.get(v);
for (var i = 0 ; i < vList.length ; i++){
var e = vList[i];
if (colors[e] == "white"){
this.dfsVisit(e,colors,handler);
}
}
// 4. 将v设置为黑色
colors[v] = "black";
};
};
// 测试代码
// 1. 创建图结构
var g =new Graph();
// 2. 添加顶点
var myVertexes = ['A','B','C','D','E','F','G','H','I'];
for (var i = 0; i < myVertexes.length ; i++){
g.addVertex(myVertexes[i]);
};
// 3.添加边
g.addEdge('A','B');
g.addEdge('A','C');
g.addEdge('A','D');
g.addEdge('C','D');
g.addEdge('C','G');
g.addEdge('D','G');
g.addEdge('D','H');
g.addEdge('B','E');
g.addEdge('B','F');
g.addEdge('E','I');
// 4. 测试结果
// alert(g);
// 5. 测试bfs
var result = "";
g.bfs(g.vertexes[0],function (v) {
result += v + ' ';
});
// alert(result);
// 6. 测试dfs
result = "";
g.dfs(g.vertexes[0],function (v) {
result += v + ' ';
});
alert(result);
</script>
</body>
</html>