图的实现
实现思路:首先是封装一个对象,对象中包含一个存储顶点的数组和一个存储边的Map。实现添加顶点,添加边,toString(),图的广度优先遍历和图的深度优先遍历。
广度优先遍历的思路:广度优先遍历是通过队列来实现的。
- 首先将所有的结点颜色置为白色
- 将传入的顶点加入到队列当中。
- 通过while循环遍历队列,直到队列为空时,停止遍历。
- 从队列中取出一个顶点,将他置位灰色。并且查询与之相连的顶点。
- 然后遍历得到的与之相连的顶点,如果是白色,说明没有没有被遍历过,将其加入到队列当中。
- 最后处理正在while循环遍历的顶点。并将其置位黑色,表示已探索完该顶点。
深度优先遍历的思路:通过递归来实现深度优先遍历。
- 首先将所有的结点颜色置为白色
- 遍历所有的顶点进行遍历,调用递归函数,进行探索顶点。
- 将当前递归的顶点置位灰色,并且处理当前顶点。
- 然后搜索与该顶点相连的所有的顶点。
- 遍历相邻的顶点,进行递归处理。
- 最后将遍历完的顶点颜色置位黑色。
//队列
class Queue {
constructor() {
this.items = [];
}
//尾部添加元素
enqueue(ele) {
return this.items.push(ele);
}
//头部删除元素
dequeue() {
return this.items.shift();
}
//查看队列头元素
front() {
return this.items[0];
}
//队列长度
size() {
return this.items.length;
}
//队列是否为空
isEmpty() {
return this.items.length == 0;
}
toString() {
let resultString = "";
for (let i = 0; i < this.items.length; i++) {
resultString +=
this.items[i].element + "-" + this.items[i].priority + ";";
}
return resultString;
}
}
//图
class Graph {
constructor() {
//存储顶点
this.vertexes = [];
//使用map来存储边
this.edge = new Map();
}
//添加顶点
addVertex(v) {
this.vertexes.push(v);
this.edge.set(v, []);
}
//添加边
addEdge(v1, v2) {
this.edge.get(v1).push(v2);
this.edge.get(v2).push(v1);
}
//toString方法的重写
toString() {
let resStr = "";
for (let i = 0; i < this.vertexes.length; i++) {
let v = this.vertexes[i];
resStr += v + "->";
let vEdges = this.edge.get(v);
for (let j = 0; j < vEdges.length; j++) {
resStr += vEdges[j] + "";
}
resStr += "\n";
}
return resStr;
}
//初始化颜色
initColors() {
let colors = [];
for (let i = 0; i < this.vertexes.length; i++) {
colors[this.vertexes[i]] = "white";
}
return colors;
}
//广度优先搜索遍历图
BFS(vertex, handler) {
let colors = this.initColors();
//利用队列实现
let queue = new Queue();
queue.enqueue(vertex);
//队列不为空一直循环
while (!queue.isEmpty()) {
//取出一个元素
let v = queue.dequeue();
//搜索相邻的结点
let vlist = this.edge.get(v);
//将遍历的结点颜色变为灰色
colors[v] = "gray";
for (let i = 0; i < vlist.length; i++) {
if (colors[vlist[i]] == "white") {
colors[vlist[i]] = "gray";
//添加到队列中
queue.enqueue(vlist[i]);
}
}
//处理当前遍历的结点
handler(v);
//处理完以后颜色变为黑色
colors[v] = "black";
}
}
//深度优先搜索
DFS(handler) {
//初始化颜色
let colors = this.initColors();
//遍历每一个结点
for (let i = 0; i < this.vertexes.length; i++) {
if (colors[this.vertexes[i]] == "white") {
this.RecursionDFS(this.vertexes[i], colors, handler);
}
}
}
RecursionDFS(v, colors, handler) {
colors[v] = "gray";
//处理当前节点
if (handler) {
handler(v);
}
//获取所有连接结点
let vlist = this.edge.get(v);
console.log(vlist);
for (let i = 0; i < vlist.length; i++) {
if (colors[vlist[i]] == "white") {
this.RecursionDFS(vlist[i], colors, handler);
}
}
//探索完以后设为黑色
colors[v] = "black";
}
}
let graph = new Graph();
let vertexes = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
for (let i = 0; i < vertexes.length; i++) {
graph.addVertex(vertexes[i]);
}
graph.addEdge("a", "b");
graph.addEdge("a", "c");
graph.addEdge("a", "d");
graph.addEdge("c", "d");
graph.addEdge("c", "g");
graph.addEdge("d", "g");
graph.addEdge("d", "h");
graph.addEdge("b", "e");
graph.addEdge("b", "f");
graph.addEdge("e", "i");
graph.initColors();
console.log(graph.toString());
let res = "";
// graph.BFS("a", (v) => {
// res += v;
// });
graph.DFS((v) => {
res += v;
});
alert(res);
\