无向图的最短路径算法JAVA实现(转)
一,问题描述
给出一个无向图,指定无向图中某个顶点作为源点。求出图中所有顶点到源点的最短路径。
无向图的最短路径其实是源点到该顶点的最少边的数目。
本文假设图的信息保存在文件中,通过读取文件来构造图。文件内容的格式参考这篇文章第一部分。
二,算法实现思路
无向图的最短路径实现相对于带权的有向图最短路径实现要简单得多。
源点的最短路径距离为0,从源点开始,采用广度优先的顺序,首先将与源点邻接的顶点的路径求出,然后再依次求解图中其他顶点的最短路径。
由于顶点的最短路径的求解顺序 是一个 广度优先的顺序,因此需要一个辅助队列。初始时,将源点的最短路径距离设置为0,将源点入队列。
然后,在一个while循环中,从队列中弹出顶点,遍历该顶点的邻接点,若该邻接点的距离未被更新过(表示该邻接点未被访问过),更新邻接点的最短路径距离为 该顶点的距离加上1,并将所有的邻接点入队列。
三,最短路径算法的实现
感觉该算法的实现与 二叉树的层序遍历,有向图的拓扑排序算法实现都非常的相似。他们都采用了广度的思想在里面。
广度优先的思想就是:处理完某个顶点后,去处理该顶点的所有邻接点,处理完它的邻接点后,再去处理更远(更外层)的顶点。
算法的代码如下:

1 /*
2 * 计算源点s到无向图中各个顶点的最短路径
3 * 需要一个队列来保存图中的顶点,初始时,源点入队列,然后以广度的形式向外扩散求解其他顶点的最短路径
4 */
5 private void unweightedShortestPath(Vertex s){
6 //初始化
7 Queue<Vertex> queue = new LinkedList<>();
8 s.dist = 0;
9 queue.offer(s);//将源点dist设置为0并入队列
10
11 while(!queue.isEmpty()){
12 Vertex v = queue.poll();
13 for (Edge e : v.adjEdges) {//扫描v的邻接边(点)
14 if(e.endVertex.dist == Integer.MAX_VALUE){//如果这个顶点(e.endVertex)未被访问(每个顶点只会入队列一次)
15 e.endVertex.dist = v.dist + 1;//更新该顶点到源点的距离
16 queue.offer(e.endVertex);
17 e.endVertex.preNode = v;//设置该顶点的前驱顶点
18 }//end if
19 }//end for
20 }//end while
21 }

第11行while循环,每个顶点出队列一次,第13行for循环,表示每条边被处理一次,故算法的时间复杂度为O(V+E)
第14行if语句表明,图中每个顶点只会入队列一次。因为,顶点入队列后,该顶点的 dist 设置为 v.dist+1,不再是 Integer.MAX_VALUE
四,完整代码实现
NonDirectedGraph.java构造图并实现最短路径算法

1 import java.util.Collection;
2 import java.util.LinkedHashMap;
3 import java.util.LinkedList;
4 import java.util.List;
5 import java.util.Map;
6 import java.util.Queue;
7
8 /*
9 * 求解无向图的单源最短路径
10 */
11 public class NonDirectedGraph {
12 private class Vertex{
13 private String vertexLabel;//顶点标识
14 private List<Edge> adjEdges;//与该顶点邻接的边(点)
15 private int dist;//顶点距离
16 private Vertex preNode;
17
18 public Vertex(String vertexLabel) {
19 this.vertexLabel = vertexLabel;
20 adjEdges = new LinkedList<>();
21 dist = Integer.MAX_VALUE;
22 preNode = null;
23 }
24 }
25 private class Edge{
26 private Vertex endVertex;
27 public Edge(Vertex endVertex) {
28 this.endVertex = endVertex;
29 }
30 }
31
32 private Map<String, Vertex> nonDirectedGraph;
33 private Vertex startVertex;//图的起始顶点
34
35 public NonDirectedGraph(String graphContent) {
36 nonDirectedGraph = new LinkedHashMap<>();
37 buildGraph(graphContent);
38 }
39
40 private void buildGraph(String graphContent){
41 String[] lines = graphContent.split("\n");
42
43 String startNodeLabel, endNodeLabel;
44 Vertex startNode, endNode;
45 for(int i = 0; i < lines.length; i++){
46 String[] nodesInfo = lines[i].split(",");
47 startNodeLabel = nodesInfo[1];
48 endNodeLabel = nodesInfo[2];
49
50 endNode = nonDirectedGraph.get(endNodeLabel);
51 if(endNode == null){
52 endNode = new Vertex(endNodeLabel);
53 nonDirectedGraph.put(endNodeLabel, endNode);
54 }
55
56 startNode = nonDirectedGraph.get(startNodeLabel);
57 if(startNode == null){
58 startNode = new Vertex(startNodeLabel);
59 nonDirectedGraph.put(startNodeLabel, startNode);
60 }
61 Edge e = new Edge(endNode);
62 //对于无向图而言,起点和终点都要添加边
63 endNode.adjEdges.add(e);
64 startNode.adjEdges.add(e);
65 }
66 startVertex = nonDirectedGraph.get(lines[0].split(",")[1]);//总是以文件中第一行第二列的那个标识顶点作为源点
67 }
68
69 public void unweightedShortestPath(){
70 unweightedShortestPath(startVertex);
71 }
72
73
74 /*
75 * 计算源点s到无向图中各个顶点的最短路径
76 * 需要一个队列来保存图中的顶点,初始时,源点入队列,然后以广度的形式向外扩散求解其他顶点的最短路径
77 */
78 private void unweightedShortestPath(Vertex s){
79 //初始化
80 Queue<Vertex> queue = new LinkedList<>();
81 s.dist = 0;
82 queue.offer(s);//将源点dist设置为0并入队列
83
84 while(!queue.isEmpty()){
85 Vertex v = queue.poll();
86 for (Edge e : v.adjEdges) {//扫描v的邻接边(点)
87 if(e.endVertex.dist == Integer.MAX_VALUE){//如果这个顶点(e.endVertex)未被访问(每个顶点只会入队列一次)
88 e.endVertex.dist = v.dist + 1;//更新该顶点到源点的距离
89 queue.offer(e.endVertex);
90 e.endVertex.preNode = v;//设置该顶点的前驱顶点
91 }//end if
92 }//end for
93 }//end while
94 }
95
96 //打印图中所有顶点到源点的距离及路径
97 public void showDistance(){
98 Collection<Vertex> vertexs = nonDirectedGraph.values();
99 for (Vertex vertex : vertexs) {
100 System.out.print(vertex.vertexLabel + "<--");
101 Vertex tmpPreNode = vertex.preNode;
102 while(tmpPreNode != null){
103 System.out.print(tmpPreNode.vertexLabel + "<--");
104 tmpPreNode = tmpPreNode.preNode;
105 }
106 System.out.println("distance=" + vertex.dist);
107 }
108 }
109 }

打印路径也可以使用递归来实现:
1 public void showDistanceRecursive(Vertex v){
2 if(v.preNode != null){
3 showDistanceRecursive(v.preNode);
4 }
5 System.out.print(v.vertexLabel + " ");
6 }
打印顶点 v 的路径,第三行 先打印 v 的前驱顶点的路径,然后再在第5行打印 v 。
第5行的打印输出语句在第三行的递归调用语句之后,故最里层的递归调用最先被打印出来,最里层的递归调用即源点,因为只有源点的 preNode == null。
当所有的里层递归调用返回后,最终执行到最外层的递归调用处,执行第5行打印 顶点 v 后,整个递归结束。
TestShortestPath.java是个测试类,用来测试结果。

1 public class TestShortestPath {
2 public static void main(String[] args) {
3 String graphFilePath;
4 if(args.length == 0)
5 graphFilePath = "F:\\xxx";
6 else
7 graphFilePath = args[0];
8
9 String graphContent = FileUtil.read(graphFilePath, null);
10 NonDirectedGraph graph = new NonDirectedGraph(graphContent);
11 graph.unweightedShortestPath();
12 graph.showDistance();
13 }
14 }

FileUtil.java负责读取存储图信息的文件。具体参考有向图的拓扑排序算法JAVA实现
保存图的 文件内容如下:
0,0,1,4
1,0,2,7
2,0,3,3
3,1,2,3
4,1,4,2
5,3,4,3
6,2,5,2
7,4,5,2
测试输出结果如下:

源点标识是 0,
0 号顶点到 1 号顶点的最短距离为1,路径为:0-->1
0 号顶点到 5 号顶点的最短距离为2,路径为:0-->2-->5
.....
....
http://www.cnblogs.com/hapjin/p/5435724.html
无向图的最短路径算法JAVA实现(转)的更多相关文章
- 无向图的最短路径算法JAVA实现
一,问题描述 给出一个无向图,指定无向图中某个顶点作为源点.求出图中所有顶点到源点的最短路径. 无向图的最短路径其实是源点到该顶点的最少边的数目. 本文假设图的信息保存在文件中,通过读取文件来构造图. ...
- 加权图的最小生成树、最短路径算法 - java实现
加权图相关算法 前言 本文主要介绍加权图算法中两个重要应用:最小生成树和最短路径. 求最小生成树时针对的是加权无向图,加权有向图的最小生成树算法成为"最小属树形图"问题,较为复杂, ...
- 带权图的最短路径算法(Dijkstra)实现
一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...
- 有向图的拓扑排序算法JAVA实现
一,问题描述 给定一个有向图G=(V,E),将之进行拓扑排序,如果图有环,则提示异常. 要想实现图的算法,如拓扑排序.最短路径……并运行看输出结果,首先就得构造一个图.由于构造图的方式有很多种,这里假 ...
- 最短路径算法之Dijkstra算法(java实现)
前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知 ...
- Java邻接表表示加权有向图,附dijkstra最短路径算法
从A到B,有多条路线,要找出最短路线,应该用哪种数据结构来存储这些数据. 这不是显然的考查图论的相关知识了么, 1.图的两种表示方式: 邻接矩阵:二维数组搞定. 邻接表:Map<Vertext, ...
- 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)
一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...
- 最短路径算法(Dijkstra算法、Floyd-Warshall算法)
最短路径算法具体的形式包括: 确定起点的最短路径问题:即已知起始结点,求最短路径的问题.适合使用Dijkstra算法. 确定终点的最短路径问题:即已知终结结点,求最短路径的问题.在无向图中,该问题与确 ...
- 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson
根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...
随机推荐
- java设计模式之观察者模式(9)
Java观察者模式的浅析 简单地说,观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监察一个主题对象.这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者 ...
- ubunut在系统恢复模式下无法改动rootpassword的分析和解决
前些日子本猫的ubuntu 14.10貌似出了点问题,想改动下rootpassword,可是无奈原系统有错正常情况下无法改动啊.这是逼我重装的节奏吗? 在ubuntu开机后马上按住left_shift ...
- ASP.NET - Repeater控件删除按钮,点击删除信息
前台代码: <!--类别信息--> <div id ="newnews" class ="Frm"> <h4>类别管理< ...
- 程序员必须知道的几个Git代码托管平台(转)
上一篇博客中2015继续任性——不会Git命令,照样玩转Git我们简单的介绍了在VS2013中使用Git,和GitHub客户端的使用.那么使用Git到底有什么好处呢?最为明显的是支持Git代码托管的平 ...
- 14.10.2 File Space Management 文件空间管理:
14.10.2 File Space Management 文件空间管理: 数据文件 你定义在配置文件形成了InnoDB的系统表空间, 文件是逻辑连接形成表空间,没有条带化使用. 你不能定义你的表在表 ...
- Kendo UI开发教程(20): Kendo MVVM 数据绑定(九) Text
Text绑定可以使用ViewModel来设置DOM元素的文本属性,如果需要设置input,textarea,或select的显示,需要使用value属性. 1 <span data-bind=& ...
- spring mvc3中的addFlashAttribute方法
spring mvc3中的addFlashAttribute方法
- Oracle死锁、数据库链接问题
--查询数据库锁表的信息 select do.object_name,t2.username,t2.sid,t2.serial#,t2.logon_time,t2.MACHINE,t2.state,t ...
- Shell echo命令
Shell echo命令 echo "It is a test" 这里的双引号完全可以省略 .显示变量 read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shel ...
- 3xian退役贴【深思。】
这是原文: 最后一天,漫天飘起了雪花,假装欢送我离去. 这次WF之战不太顺利,早期的C题大概花了1秒钟构思,然而由于输出格式多了一个空格直到两个半小时才逃脱Wrong Answer的纠缠.还好lynn ...