图的实现

149 阅读1分钟

图的实现

实现思路:首先是封装一个对象,对象中包含一个存储顶点的数组和一个存储边的Map。实现添加顶点,添加边,toString(),图的广度优先遍历和图的深度优先遍历。

广度优先遍历的思路:广度优先遍历是通过队列来实现的。

  1. 首先将所有的结点颜色置为白色
  2. 将传入的顶点加入到队列当中。
  3. 通过while循环遍历队列,直到队列为空时,停止遍历。
  4. 从队列中取出一个顶点,将他置位灰色。并且查询与之相连的顶点。
  5. 然后遍历得到的与之相连的顶点,如果是白色,说明没有没有被遍历过,将其加入到队列当中。
  6. 最后处理正在while循环遍历的顶点。并将其置位黑色,表示已探索完该顶点。

深度优先遍历的思路:通过递归来实现深度优先遍历。

  1. 首先将所有的结点颜色置为白色
  2. 遍历所有的顶点进行遍历,调用递归函数,进行探索顶点。
  3. 将当前递归的顶点置位灰色,并且处理当前顶点。
  4. 然后搜索与该顶点相连的所有的顶点。
  5. 遍历相邻的顶点,进行递归处理。
  6. 最后将遍历完的顶点颜色置位黑色。
 //队列
 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);
 ​

\