赞
踩
通俗的说,图就是由 顶点(Vertex) 和 边(edge) 组成的。一般来说又分为 有向图 和 无向图,即顶点到顶点的边是否是有方向区分的。
广度优先搜索(Breadth First Search)通常用于指出是否存在一条路径由顶点 A 到达顶点 B,如果有,则找出顶点 A 到顶点 B 的最短路径。
注意,这里的最短路径是没有权重概念的,即可以认为任一边的长度均为 1。
首先,我们从顶点 A 出发,找出它的所有直接邻居点(可以想象为一度人脉),检查这里面是否存在顶点 B。
然后,假设上述 “一度人脉” 中不存在顶点 B,这将邻居点的邻居点(可以想象为二度人脉)也加入到搜索队列中,并检查其中是否存在顶点 B。
如上,我们依次扩大到 “三度人脉”、“四度人脉” … 直到找到顶点 B 为止。
如果找完了都找不到顶点 B 的话,则说明图中不存在顶点 A 到顶点 B 的路径。
注意: 找过的点务必不要再去检查,否则可能导致无限循环!
广度优先搜索的运行时间为 O(顶点数 + 边数),通常记为 O(V + E)。
自己的id
,有哪些邻居
等基本特性。是否被检查过
和 它的上一个顶点是谁
这两个属性。首先创建一个 Vertex 类,如下:
import java.util.LinkedList; public class Vertex { private int id; // 顶点的标识 private LinkedList<Vertex> neighbors; // 这个顶点的邻居顶点 private boolean isSerched; // 这个顶点是否被搜索过了 private Vertex predecessor; // 这个顶点的前驱,用来记录路径的 public Vertex(int id) { this.id = id; } public void addNeighbor(Vertex... vertexes) { this.neighbors = new LinkedList<>(); for (Vertex vertex : vertexes) { this.neighbors.add(vertex); } } public int getId() { return id; } public void setId(int id) { this.id = id; } public LinkedList<Vertex> getNeighbors() { return neighbors; } public void setNeighbors(LinkedList<Vertex> neighbors) { this.neighbors = neighbors; } public boolean isSerched() { return isSerched; } public void setSerched(boolean isSerched) { this.isSerched = isSerched; } public Vertex getPredecessor() { return predecessor; } public void setPredecessor(Vertex predecessor) { this.predecessor = predecessor; } }
然后,创建一个场景类,并实现和调用 BFS 方法:
import java.util.LinkedList; public class Main { public static void main(String[] args) { // init data (对照上面题目给的图) Vertex[] vertexes = new Vertex[9]; for (int i = 0; i < vertexes.length; i++) { vertexes[i] = new Vertex(i); } vertexes[0].addNeighbor(vertexes[1], vertexes[3]); vertexes[1].addNeighbor(vertexes[0], vertexes[2]); vertexes[2].addNeighbor(vertexes[1], vertexes[4], vertexes[5]); vertexes[3].addNeighbor(vertexes[0], vertexes[5], vertexes[6]); vertexes[4].addNeighbor(vertexes[2], vertexes[8]); vertexes[5].addNeighbor(vertexes[2], vertexes[3], vertexes[6], vertexes[8]); vertexes[6].addNeighbor(vertexes[3], vertexes[5], vertexes[7]); vertexes[7].addNeighbor(vertexes[6], vertexes[8]); vertexes[8].addNeighbor(vertexes[4], vertexes[5], vertexes[7]); // start search Vertex start = vertexes[0]; Vertex end = vertexes[8]; boolean hasPath = bfs(start, end); if (hasPath) { // print path Vertex predecessor = end; do { System.out.print(predecessor.getId() + " -> "); predecessor = predecessor.getPredecessor(); } while (predecessor != null); } else { System.out.println("不存在该起点到该终点的路径"); } } public static boolean bfs(Vertex start, Vertex end) { LinkedList<Vertex> queue = new LinkedList<>(); queue.addLast(start); // 添加到队尾 while (!queue.isEmpty()) { Vertex vertex = queue.pollFirst(); // 从队首取出一个元素 // 如果这个顶点是否已经检索过了,则跳过 if (vertex.isSerched()) { continue; } if (vertex == end) { // 如果到了终点了就可以返回了 return true; } else { // 如果还不是终点,这把该顶点可以到达的邻居全部添加到队列末端 for (Vertex neighbor : vertex.getNeighbors()) { if (neighbor.getPredecessor() == null && neighbor != start) { neighbor.setPredecessor(vertex); } queue.addLast(neighbor); } } vertex.setSerched(true); } return false; } }
执行结果:
8 -> 5 -> 3 -> 0 ->
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。