JAVA广度优先实现最短路径问题
来源:互联网 发布:结构优化设计 编辑:程序博客网 时间:2024/06/03 20:50
最短路径分为点到点最短路径
和源点到其他点的最短路径
问题,下面给出广度优先BFS算法
的实现。
一、点到点
1.1 问题描述
这里采用迷宫问题来举例。求从起点到终点的最短路径,采用广度优先的顺序,首先将与源点邻接的顶点的路径求出,然后再依次求解图中其他顶点的最短路径。
由于顶点的最短路径的求解顺序 是一个广度优先的顺序,因此需要一个辅助队列。具体步骤如下:
①从起点开始,先将其加入队列,设置距离为0;
②从队列首端取出位置,将从这个位置能够到达的位置加入队列,并且让这些位置的距离为上一个位置的距离加上1;
③循环2直到将终点添加到队列中,这说明我们已经找到了路径;
在这个过程中,每次处理的位置所对应的距离是严格递增的,因此一旦找到终点,当时的距离就是最短距离。
由此可见,迷宫问题是一个无向无权图。
1.2 算法实现
import java.awt.Point;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class Maze { static int M, N, dx, dy, gx, gy; static char[][] a; static int[][] deep; public static void main(String[] args) { Scanner s = new Scanner(System.in); System.out.println("请输入迷宫的行数:"); M = s.nextInt(); System.out.println("请输入迷宫的列数:"); N = s.nextInt(); a = new char[M][N]; deep = new int[M][N]; System.out.println("请输入迷宫矩阵(起点为'm',终点为'e',墙壁为'1',可行路径为'0'):"); for (int i = 0; i < M; i++) { a[i] = s.next().toCharArray(); } for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) { if (a[i][j] == 'm') { dx = i; dy = j; } if (a[i][j] == 'e') { gx = i; gy = j; } } int len = bfs(); System.out.println("从起点到终点的最短路径为:" + len); } private static int bfs() { Queue<Point> q = new LinkedList<Point>(); int[] tx = { -1, 1, 0, 0 }; int[] ty = { 0, 0, 1, -1 }; q.offer(new Point(dx, dy)); for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) deep[i][j] = -1; deep[dx][dy] = 0; while (q.size() > 0) { Point p = q.poll(); if (p.x == gx && p.y == gy) break; for (int i = 0; i < 4; i++) { int x = p.x + tx[i]; int y = p.y + ty[i]; if (x >= 0 && x < M && y >= 0 && y < N && a[x][y] != '1' && deep[x][y] == -1) { deep[x][y] = deep[p.x][p.y] + 1; q.offer(new Point(x, y)); } } } return deep[gx][gy]; }}
1.3 算法测试
测试数据为10*10矩阵;
矩阵为:
1111111111
1m01000101
1001000101
1000011001
1011100001
1000100001
1010001001
1011101101
11000000e1
1111111111
运行结果为:
二、源点到其他点
2.1 问题描述
源点的最短路径距离为0,从源点开始,采用广度优先的顺序,首先将与源点邻接的顶点的路径求出,然后再依次求解图中其他顶点的最短路径。
由于顶点的最短路径的求解顺序、是一个广度优先的顺序,因此需要一个辅助队列。初始时,将源点的最短路径距离设置为0,将源点入队列。
然后,在一个while循环中,从队列中弹出顶点,遍历该顶点的邻接点,若该邻接点的距离未被更新过(表示该邻接点未被访问过),更新邻接点的最短路径距离为该顶点的距离加上1,并将所有的邻接点入队列。
这里采用的图为有向无权图。
2.2 算法实现
//边类:class Edge { String to;//边指向的节点 public String getTo() { return to; } public void setTo(String to) { this.to = to; } Edge nextEdge;//具有同一起点的下一条边 public Edge(String to) { this.to = to; this.nextEdge = null; }}
//点类:public class Vertex { String from;// 边的起点 int pathLength = 0;//路径长度 boolean isVisted = false; int indegree;// 每个顶点的入度 Edge first;// 以from为起点的第一条边 public boolean getIsVisted() { return isVisted; } public void setIsVisted(boolean isVisted) { this.isVisted = isVisted; } public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public Vertex(String from) { this.from = from; first = null; this.indegree = 0; } public int getPathlength() { return pathLength; } public void setPathlength(int counter) { pathLength = counter; }}
//图类:import java.util.ArrayList;import java.util.Scanner;public class Graph { public Vertex[] v; public Edge[] e; public int edgeNumber; public int vertexNumber; // 根据输入建立一个有向图 public void buildGraph() { Scanner s = new Scanner(System.in); System.out.println("请输入有向图的顶点数:"); vertexNumber = s.nextInt(); System.out.println("请输入有向图的边数:"); edgeNumber = s.nextInt(); // 建立顶点数组 v = new Vertex[vertexNumber]; e = new Edge[edgeNumber]; System.out.println("请输入顶点的名称:"); for (int i = 0; i < vertexNumber; i++) { String name = s.next(); v[i] = new Vertex(name); } for (int i = 0; i < edgeNumber; i++) { System.out.print("输入第" + (i + 1) + "条有向边的端点A:"); String startVertex = s.next(); System.out.print("输入第" + (i + 1) + "条有向边的端点B:"); String endVertex = s.next(); // 找到起止点的vertex索引值 int vBeginIndex = findvIndex(startVertex); int vEndIndex = findvIndex(endVertex); e[i] = new Edge(endVertex);// 由终点建立到该终点的边 v[vEndIndex].indegree++;// 相应Vertex的入度+1 e[i].nextEdge = v[vBeginIndex].first;// 将该边的下一条边连接到以startVertex的所有边 v[vBeginIndex].first = e[i];// 将e作为v[startVertex]的第一条边 } } public int getLength() { return v.length; } // 返回一个包含相邻节点的ArrayList public ArrayList<Vertex> getAdjacentVertex(Vertex ver) { int index; ArrayList al = new ArrayList(); // 找到指向ver的相邻节点 for (int j = 0; j < v.length; j++) { if (v[j].first != null) for (Edge e = v[j].first; e != null; e = e.nextEdge) if (e.to.equals(ver.from)) { al.add(v[j]); } } index = findvIndex(ver.from); // 找到以ver为起点指向的相邻节点 for (Edge e = v[index].first; e != null; e = e.nextEdge) { al.add(v[findvIndex(e.to)]); } return al; } public int findvIndex(String s) { int vIndex = -1; for (int j = 0; j < v.length; j++) { if (v[j].from.equals(s)) vIndex = j; } return vIndex; }}
//主类:import java.util.ArrayList;import java.util.LinkedList;import java.util.Scanner;public class BFS { Graph g; public BFS() { g = new Graph(); g.buildGraph(); } public static void main(String[] args) { BFS s = new BFS(); System.out.print("输入路径的起点:"); Scanner input = new Scanner(System.in); String first = input.next(); s.shortestPath(first); } public void shortestPath(String first) { LinkedList<Vertex> queue = new LinkedList<Vertex>(); Vertex firstVertex = g.v[g.findvIndex(first)]; firstVertex.setIsVisted(true); int counter = 0; firstVertex.setPathlength(counter); queue.add(firstVertex); System.out.println("最短路径为:"); String path; while (!queue.isEmpty()) { Vertex v = queue.poll(); // 得到队顶的path和Counter,用于下面for循环的赋值 path = v.getFrom(); counter = v.getPathlength(); System.out.println(v.getFrom() + "的路径长度为 " + v.getPathlength()); ArrayList<Vertex> al = g.getAdjacentVertex(v); for (Vertex vertex : al) { if (!(vertex.getIsVisted()))// 没被访问过 { vertex.setIsVisted(true); vertex.setPathlength(counter + 1); queue.add(vertex); } } } }}
2.3 算法测试
测试数据为下图:
运行结果为:
- JAVA广度优先实现最短路径问题
- 最短路径/广度优先
- 广度优先算法最短路径问题 Dijkstra算法
- 最短路径条数问题 - 广度优先搜索
- 城市最短路径问题--图的广度优先搜索
- 迷宫问题(广度优先搜索,输出最短路径)
- (原创)广度优先搜索解决最短路径问题
- 利用广度优先遍历(BFS)计算最短路径 - Java实现
- 无权最短路径-广度优先搜索
- 最短路径算法-广度优先搜索
- 无权最短路径-广度优先搜索
- 最短路径算法之----广度优先
- 广度优先搜索 最短路径 队列
- 广度优先搜索之最短路径
- 无权最短路径 广度优先搜索
- 最短路径算法-广度优先搜索
- BFS广度搜索(最短路径问题)
- 两个城市之间寻找最短路径问题(广度优先搜索)
- lintcode 4.丑数 II(优先队列)
- 面向对象的三大特性
- 从无到有RNN
- [LeetCode
- Android context运用
- JAVA广度优先实现最短路径问题
- 让浏览器记住ajax请求并能前进和后退方法(一)
- 变量——JavaScript
- python成绩统计(优化版)
- Android发送邮件
- java初学--数组
- 553. Optimal Division
- 南阳理工29题
- kotlin基础