利用广度优先遍历(BFS)计算最短路径 - Java实现
2015-03-15 02:46
906 查看
我们用字符串代表图的顶点(vertax),来模拟学校中Classroom, Square, Toilet, Canteen, South Gate, North Gate几个地点,然后计算任意两点之间的最短路径。
如,我想从North Gate去Canteen, 程序的输出结果应为:
首先定义一个算法接口
然后,定义图:
这里我们使用策略设计模式,将算法与Graph类分离,通过在构造Graph对象时传入一个
无向图的存储结构为邻接表,这里用一个
然后,编写
其中,
BFS算法描述:
1. 将起点标记为已访问并放入队列。
2. 从队列中取出一个顶点,得到与该顶点相通的所有顶点。
3. 遍历这些顶点,先判断顶点是否已被访问过,如果否,标记该点为已访问,记录当前路径,并将当前顶点入列。
4. 重复2、3,直到队列为空。
测试用例:
如,我想从North Gate去Canteen, 程序的输出结果应为:
BFS: From [North Gate] to [Canteen]: North Gate Square Canteen
首先定义一个算法接口
Algorithm:
public interface Algorithm { /** * 执行算法 */ void perform(Graph g, String sourceVertex); /** * 得到路径 */ Map<String, String> getPath(); }
然后,定义图:
/** * (无向)图 */ public class Graph { // 图的起点 private String firstVertax; // 邻接表 private Map<String, List<String>> adj = new HashMap<>(); // 遍历算法 private Algorithm algorithm; public Graph(Algorithm algorithm) { this.algorithm = algorithm; } /** * 执行算法 */ public void done() { algorithm.perform(this, firstVertax); } /** * 得到从起点到{@code vertex}点的最短路径 * @param vertex * @return */ public Stack<String> findPathTo(String vertex) { Stack<String> stack = new Stack<>(); stack.add(vertex); Map<String, String> path = algorithm.getPath(); for (String location = path.get(vertex) ; false == location.equals(firstVertax) ; location = path.get(location)) { stack.push(location); } stack.push(firstVertax); return stack; } /** * 添加一条边 */ public void addEdge(String fromVertex, String toVertex) { if (firstVertax == null) { firstVertax = fromVertex; } adj.get(fromVertex).add(toVertex); adj.get(toVertex).add(fromVertex); } /** * 添加一个顶点 */ public void addVertex(String vertex) { adj.put(vertex, new ArrayList<>()); } public Map<String, List<String>> getAdj() { return adj; } }
这里我们使用策略设计模式,将算法与Graph类分离,通过在构造Graph对象时传入一个
Algorithm接口的实现来为
Graph选择遍历算法。
public Graph(Algorithm algorithm) { this.algorithm = algorithm; }
无向图的存储结构为邻接表,这里用一个
Map表示邻接表,map的key是学校地点(
String),value是一个与该地点相连通的地点表(
List<String>)。
// 邻接表 private Map<String, List<String>> adj = new HashMap<>();
然后,编写
Algorithm接口的BFS实现:
/** * 封装BFS算法 */ public class BroadFristSearchAlgorithm implements Algorithm { // 保存已经访问过的地点 private List<String> visitedVertex; // 保存最短路径 private Map<String, String> path; @Override public void perform(Graph g, String sourceVertex) { if (null == visitedVertex) { visitedVertex = new ArrayList<>(); } if (null == path) { path = new HashMap<>(); } BFS(g, sourceVertex); } @Override public Map<String, String> getPath() { return path; } private void BFS(Graph g, String sourceVertex) { Queue<String> queue = new LinkedList<>(); // 标记起点 visitedVertex.add(sourceVertex); // 起点入列 queue.add(sourceVertex); while (false == queue.isEmpty()) { String ver = queue.poll(); List<String> toBeVisitedVertex = g.getAdj().get(ver); for (String v : toBeVisitedVertex) { if (false == visitedVertex.contains(v)) { visitedVertex.add(v); path.put(v, ver); queue.add(v); } } } } }
其中,
path是
Map类型,意为从 value 到 key 的一条路径。
BFS算法描述:
1. 将起点标记为已访问并放入队列。
2. 从队列中取出一个顶点,得到与该顶点相通的所有顶点。
3. 遍历这些顶点,先判断顶点是否已被访问过,如果否,标记该点为已访问,记录当前路径,并将当前顶点入列。
4. 重复2、3,直到队列为空。
测试用例:
String[] vertex = {"North Gate", "South Gate", "Classroom", "Square", "Toilet", "Canteen"}; Edge[] edges = { new Edge("North Gate", "Classroom"), new Edge("North Gate", "Square"), new Edge("Classroom", "Toilet"), new Edge("Square", "Toilet"), new Edge("Square", "Canteen"), new Edge("Toilet", "South Gate"), new Edge("Toilet", "South Gate"), };
@Test public void testBFS() { Graph g = new Graph(new BroadFristSearchAlgorithm()); addVertex(g); addEdge(g); g.done(); Stack<String> result = g.findPathTo("Canteen"); System.out.println("BFS: From [North Gate] to [Canteen]:"); while (!result.isEmpty()) { System.out.println(result.pop()); } }
相关文章推荐
- Java实现利用广度优先遍历(BFS)计算最短路径的方法
- 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径
- 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径
- 利用广度优先遍历BreadthFirstSearch (BFS)实现两个点之间是否连通
- 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径
- 用邻接表实现图的深度优先遍历、广度优先遍历、最短路径(无权图)
- 图的理解:深度优先和广度优先遍历及其 Java 实现
- 迷宫最短路径的C++实现(队列:广度优先)
- Java图以及BFS广度优先遍历
- 迷宫最短路径的C++实现(队列:广度优先)
- (广度优先搜索第一课)迷宫的最短路径 - BFS
- 数据结构--图的理解:深度优先和广度优先遍历及其 Java 实现
- 如何实现广度优先遍历(BFS) .
- 数据结构和算法之:图的深度优先和广度优先遍历及其Java实现
- 图的遍历之BFS广度优先遍历C++实现
- Java数据结构----图--深度优先遍历BFS和广度优先遍历DFS
- 图的广度优先遍历BFS(分别以邻接矩阵和邻接链表实现)
- 利用邻接表求解所有节点的最短路径 java实现 可运行
- 广度优先遍历求指定顶点之间的最短路径
- 如何实现广度优先遍历(BFS)