This commit is contained in:
linghuam 2019-05-23 20:33:49 +08:00
parent 78b2cfce3a
commit 47b8b209f3
4 changed files with 167 additions and 4 deletions

View File

@ -0,0 +1,102 @@
function Graph() {
this.vertices = [];
this.vertexMap = new Map();
this.adjList = new Map();
this.addVertex = function(v) {
return this.vertexMap.has(v.id) ? null : (v.status = 0, this.vertexMap.set(v.id, v), this.vertices.push(v),this.adjList.set(v.id, new Set()), v);
};
this.addEdge = function(sourceId, targetId) {
if (this.vertexMap.has(sourceId) && this.vertexMap.has(targetId)) {
this.adjList.get(sourceId).add(this.vertexMap.get(targetId));
this.adjList.get(targetId).add(this.vertexMap.get(sourceId));
}
return this;
};
this.getVertex = function(id) {
return this.vertexMap.get(id);
};
this.getVertexAdj = function(id) {
return this.adjList.get(id) || [];
};
this.toString = function() {
this.adjList.forEach((value, key) => {
console.log(key + ':' + Array.from(value).map(e => e.id).join(',') + '\n');
});
};
}
function BFS(graph, root, callback) {
var queue = [];
if (root == null) return null;
root.status = 1 && queue.push(root);
while(queue.length) {
var curVertex = queue.shift();
// 将相邻节点入队
var adjVertexs = graph.getVertexAdj(curVertex.id);
adjVertexs.forEach(e => {
// 忽略已经入队或已经被访问过的节点
if (e.status === 0) {
e.status = 1 && queue.push(e);
}
});
// 节点被访问
callback(curVertex);
curVertex.status = 2;
}
}
function DFS(graph, callback) {
var stack = [];
var vertexs = graph.vertices;
// 遍历每个节点,若节点未被访问,则入栈
// 若栈非空,出栈
// 继续遍历其相邻未被访问的子节点
for (var i = 0, length = vertexs.length; i < length; i++) {
if (vertexs[i].status === 0) {
vertexs[i].status = 1;
stack.push(vertexs[i]);
while(stack.length) {
var v = stack.pop();
v.status = 2;
callback(v);
var adjVertexs = graph.getVertexAdj(v.id);
adjVertexs.forEach(e => {
if (e.status === 0) {
e.status = 1;
stack.push(e);
}
});
}
}
}
}
var graph = new Graph();
graph.addVertex({id: 'A'});
graph.addVertex({id: 'B'});
graph.addVertex({id: 'C'});
graph.addVertex({id: 'D'});
graph.addVertex({id: 'E'});
graph.addVertex({id: 'F'});
graph.addVertex({id: 'G'});
graph.addVertex({id: 'H'});
graph.addVertex({id: '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('BFS:\n');
// BFS(graph, graph.getVertex('A'), e => {
// console.log(e.id);
// });
console.log('DFS:\n');
DFS(graph, e => {
console.log(e.id);
});

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
<script src="./graph.js"></script>
</head>
<body>
</body>
</html>

View File

@ -100,4 +100,4 @@ var root = {
}
}
};
removeNode(root, 15);
removeNode(root, 15);

View File

@ -388,7 +388,7 @@ function Graph() {
this.vertexMap = new Map();
this.adjList = new Map();
this.addVertex = function(v) {
return this.vertexMap.has(v.id) ? null : (this.vertexMap.set(v.id, v),this.vertices.push(v),this.adjList.set(v.id, new Set()), v);
return this.vertexMap.has(v.id) ? null : (v.status = 0, this.vertexMap.set(v.id, v), this.vertices.push(v),this.adjList.set(v.id, new Set()), v);
};
this.addEdge = function(sourceId, targetId) {
if (this.vertexMap.has(sourceId) && this.vertexMap.has(targetId)) {
@ -397,6 +397,12 @@ function Graph() {
}
return this;
};
this.getVertex = function(id) {
return this.vertexMap.get(id);
};
this.getVertexAdj = function(id) {
return this.adjList.get(id) || [];
};
this.toString = function() {
this.adjList.forEach((value, key) => {
console.log(key + ':' + Array.from(value).map(e => e.id).join(',') + '\n');
@ -407,8 +413,50 @@ function Graph() {
### 图的遍历
* 广度优先BFS用**栈**实现。
* 深度优先DFS用**队列**实现
* 广度优先BFS用**队列**实现。
* 深度优先DFS用**栈**实现。
用 status 表示节点状态:
* 0 - 初始状态
* 1 - 被探索状态
* 2 - 被访问过状态
```js
// 广度优先BFS算法用**队列**实现。
/*
1. 创建一个队列 Q
2. 将 v 标记为 1并入队
3. 如果 Q 非空,重复以下步骤
3.1 将 u 出队
3.2 寻找 u 的相邻节点,并将未被访问的节点入栈,并标记为 1
3.3 访问节点,标记为 2
*/
function BFS(root, callback) {
var queue = [];
if (root == null) return null;
root.status = 1 && queue.push(root);
while(queue.length) {
var curVertex = queue.shift();
// 将相邻节点入队
var adjVertexs = graph.getVertexAdj(curVertex.id);
adjVertexs.forEach(e => {
// 忽略已经入队或已经被访问过的节点
if (e.status === 0) {
e.status = 1 && queue.push(e);
}
});
// 节点被访问
callback(curVertex);
curVertex.status = 2;
}
}
```
```js
// 深度优先DFS算法用**栈**实现。
function DFS(callback) {}
```
## 排序和搜索算法