基于无向图且权重单一的最短路径Dijkstra算法——JAVA实现
来源:互联网 发布:视频制作软件下载 编辑:程序博客网 时间:2024/05/16 19:32
做一个无向图的权重单一的最短路径算法。
模拟停车场最近车位的选择。
首先参考了博友JavaMan_chen的博文
http://blog.csdn.net/javaman_chen/article/details/8254309
但是这个算法是有问题的。
算法中,如果A点是当前点,是选取距离A点权重最小的那一点作为下一个路径点的。
这就带来了一个问题,即,距离A点的2个点如果权重相同,那就会随机选取其中一条。
于是,在数据量稍微大点的时候,就出错了。
在这里使用Dijkstra算法使用的是用OPEN, CLOSE表的方式。
首先,定义了坐标点的数据结构
Coordinate.java
Coordinate中包含相邻坐标的List,以及距离起始点的距离。
在算法中,一开始要进行所有路径点的关联。
之后,通过从起始点进行扩散,将所有点的step计算出来。
package com.harlan.dijkstra; import java.util.LinkedList; /** * 坐标点的数据结构 * * @author Harlan * */ public class Coordinate { //x坐标 public int x; //y坐标 public int y; //相邻坐标 public LinkedList<Coordinate> adj; //距离 public int steps; // 最短路径中的前一个顶点 public Coordinate lastPoint; ; public Coordinate(){ } public Coordinate(int newX, int newY) { x = newX; y = newY; adj=new LinkedList<Coordinate>(); reset(); } public void reset(){ steps=Integer.MAX_VALUE; lastPoint=null; } @Override public boolean equals(Object obj) { if (!(obj instanceof Coordinate)) return false; Coordinate other = (Coordinate) obj; if (x == other.x && y == other.y) { return true; } return false; } @Override public int hashCode() { return x*10000+y; } /** * 以JSON格式展示坐标 */ @Override public String toString() { return "{\"x\":" + x + ",\"y\":" + y + "}"; } }
并定义了路径数据结构
PathInfo.java
import java.util.List; /** * 路径信息 * @author Harlan * */ public class PathInfo { //目标点的坐标 private Coordinate targetCd; //去往目标点的最佳路径 private List<Coordinate> cdList; public Coordinate getTargetCd() { return targetCd; } public void setTargetCd(Coordinate targetCd) { this.targetCd = targetCd; } public List<Coordinate> getCdList() { return cdList; } public void setCdList(List<Coordinate> cdList) { this.cdList = cdList; } }
在算法中,对于路径点的关联方法:
<span style="white-space:pre"></span> /** * 和周围的四个点建立关系 * * @param node */private void getContactWithF(Coordinate node) {Coordinate coordinate = getCoordinate(node);Coordinate EAST = new Coordinate(node.x + 1, node.y);Coordinate SOUTH = new Coordinate(node.x, node.y + 1);Coordinate WEST = new Coordinate(node.x - 1, node.y);Coordinate NORTH = new Coordinate(node.x, node.y - 1);if (isCellSafe(EAST, mRoads)) {EAST = getCoordinate(EAST);coordinate.adj.add(EAST);}if (isCellSafe(SOUTH, mRoads)) {SOUTH = getCoordinate(SOUTH);coordinate.adj.add(SOUTH);}if (isCellSafe(WEST, mRoads)) {WEST = getCoordinate(WEST);coordinate.adj.add(WEST);}if (isCellSafe(NORTH, mRoads)) {NORTH = getCoordinate(NORTH);coordinate.adj.add(NORTH);}}/** * 判断周围的位子是不是道路 * * @param head * @return */public boolean isCellSafe(Coordinate park, Set<Coordinate> roads) {boolean isSafe = false;// 在道路集合里面,就是安全的,否则,不安全for (Coordinate info : roads) {if (info.equals(park)) {isSafe = true;}}return isSafe;}
无权最短路径的算法如下:
<span style="white-space:pre"></span>// 无权最短路径计算public void unweighted(Coordinate enter) {if (enter == null)throw new NoSuchElementException("Start vertex not found!");LinkedList<Coordinate> q = new LinkedList<Coordinate>();clearAll();enter = vertexMap.get(enter.toString());System.out.println("unweighted Harlan:" + enter.adj.toString());q.addLast(enter);enter.steps = 0;while (!q.isEmpty()) {Coordinate v = q.removeFirst();for (Iterator<Coordinate> itr = v.adj.iterator(); itr.hasNext();) {Coordinate w = itr.next();if (w.steps == Integer.MAX_VALUE) {w.steps = v.steps + 1;w.lastPoint = v;q.addLast(w);}}}}
遍历获取实际最短路径
<span style="white-space:pre"></span>private List<Coordinate> getPath(Coordinate dest, List<Coordinate> cdList) {if (dest.lastPoint != null) {cdList = (getPath(dest.lastPoint, cdList));}cdList.add(dest);return cdList;}
<span style="white-space:pre"></span>// 显示一条路径public void printPath(String coodrStr) throws NoSuchElementException {Coordinate coord = vertexMap.get(coodrStr);if (coord == null)throw new Exception(No path found!");else if (coord.steps == Integer.MAX_VALUE)System.out.println(coord.toString() + "is unreachable!");else {printPath(coord);System.out.println();}}// 显示实际最短路径private void printPath(Coordinate dest) {if (dest.lastPoint != null) {printPath(dest.lastPoint);System.out.print(",");}System.out.print(dest.toString());}
GetDijkstraPath.java
package com.harlan.dijkstra;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;public class GetDijkstraPath {private static final String TAG = GetDijkstraPath.class.getSimpleName();/** * 主函数,测试类 * @param args */ public static void main(String[] args) { Coordinate enter = new Coordinate(2, 0); Set<Coordinate> roads = new HashSet<Coordinate>(); roads.add(new Coordinate(3, 10)); roads.add(new Coordinate(3,11)); roads.add(new Coordinate(3, 8)); roads.add(new Coordinate(3, 9)); roads.add(new Coordinate(3, 6)); roads.add(new Coordinate(3, 7)); roads.add(new Coordinate(3, 4)); roads.add(new Coordinate(3, 5)); roads.add(new Coordinate(3, 2)); roads.add(new Coordinate(3, 3)); roads.add(new Coordinate(3, 1)); roads.add(new Coordinate(6, 1)); roads.add(new Coordinate(1, 9)); roads.add(new Coordinate(1, 8));roads.add(new Coordinate(1, 11));roads.add(new Coordinate(1, 10));roads.add(new Coordinate(1, 5));roads.add(new Coordinate(1, 4));roads.add(new Coordinate(1, 7));roads.add(new Coordinate(1, 6));roads.add(new Coordinate(1, 1));roads.add(new Coordinate(1, 3));roads.add(new Coordinate(1, 2));roads.add(new Coordinate(4, 1));roads.add(new Coordinate(4, 11));roads.add(new Coordinate(7, 5));roads.add(new Coordinate(7, 4));roads.add(new Coordinate(2, 11)); roads.add(new Coordinate(7, 7)); roads.add(new Coordinate(7,6)); roads.add(new Coordinate(7, 1)); roads.add(new Coordinate(7, 3)); roads.add(new Coordinate(7,2)); roads.add(new Coordinate(2, 1)); roads.add(new Coordinate(7, 9)); roads.add(new Coordinate(7,8)); roads.add(new Coordinate(7, 11)); roads.add(new Coordinate(7, 10)); roads.add(new Coordinate(5,11)); roads.add(new Coordinate(5, 10)); roads.add(new Coordinate(5, 9)); roads.add(new Coordinate(5,8)); roads.add(new Coordinate(5,7)); roads.add(new Coordinate(5,6)); roads.add(new Coordinate(5,5)); roads.add(new Coordinate(5,4)); roads.add(new Coordinate(5,3)); roads.add(new Coordinate(5,2)); roads.add(new Coordinate(5,1)); System.out.println("nearest roads.size(): "+roads.size()); Set<Coordinate> trags = new HashSet<Coordinate>(); trags.add(new Coordinate(5, 4)); trags.add(new Coordinate(5, 5)); PathInfo nearest = getNearestPathInfo(roads,trags,enter); System.out.println("nearest : "+nearest.getCdList()); } /** * 对外的接口(如果计算多入口的最短路径的时候使用) * 获取多入口的最佳路径 * @param roads * @param trags * @param enters * @return */ public static PathInfo getNearestPathInfoFromDiffEnter(Set<Coordinate> roads,Set<Coordinate> trags, Set<Coordinate> enters){ List<PathInfo> list = new ArrayList<>(); for(Coordinate enter:enters){ list.add(getNearestPathInfo(roads,trags,enter)); } //每条路径的步长 int steps = Integer.MAX_VALUE; PathInfo nearste = new PathInfo(); for(PathInfo pathInfo:list){ if(pathInfo.getCdList().size()<steps){ steps = pathInfo.getCdList().size(); nearste = pathInfo; } } return nearste; } /** * 对外的接口(如果计算单一入口的最短路径时候使用) * 获取单一入口的最佳路径 * * @param roads * @param trags * @param enter * @return */ public static PathInfo getNearestPathInfo(Set<Coordinate> roads,Set<Coordinate> trags, Coordinate enter){ List<PathInfo> list = getAllAvailablePathInfo(roads,trags,enter);// for(PathInfo info:list){// System.out.println("getNearestPathInfo targ:"+info.getTargetCd());// System.out.println("getNearestPathInfo route:"+info.getCdList());// System.out.println("getNearestPathInfo *********************");// }// //每条路径的步长 int steps = Integer.MAX_VALUE; PathInfo nearste = new PathInfo(); for(PathInfo pathInfo:list){ if(pathInfo.getCdList().size()<steps){ steps = pathInfo.getCdList().size(); nearste = pathInfo; } } return nearste; } /** * 获取到达所有目标点的所有可用路径 * * @param roads * @param trags * @param enter * @return */private static List<PathInfo> getAllAvailablePathInfo(Set<Coordinate> roads,Set<Coordinate> trags, Coordinate enter) {Set<Coordinate> availableRoadTar = getAllRoadNearTarg(roads,trags); //计算出起始点到各个可达点的距离HarlanDijkstra test=new HarlanDijkstra(roads,enter); test.unweighted(enter);//得出到停车位的可达点的最短路径List<PathInfo> availableList = new ArrayList<>();for(Coordinate info:availableRoadTar){PathInfo pathInfo = test.getPathInfo(info.toString());availableList.add(pathInfo);}return availableList;}/** * 获取通往所有目标的有效道路点(一个目标的临近道路点的集合) * @param roads * @param tragSet * @return */private static Set<Coordinate> getAllRoadNearTarg(Set<Coordinate> roads,Set<Coordinate> tragSet) {Set<Coordinate> allOfNearList = new HashSet<>();for (Coordinate targ : tragSet) {//System.out.println("getAllRoadNearTarg targ:"+targ);Set<Coordinate> childSet = getRoadNearTarg(roads,targ);allOfNearList.addAll(childSet);}return allOfNearList;}/** * 获取通往一个目标的临近道路点 * * @param roads * @param targ * @return */private static Set<Coordinate> getRoadNearTarg(Set<Coordinate> roads,Coordinate targ) {Set<Coordinate> nearList = new HashSet<>();Coordinate EAST = new Coordinate(targ.x + 1, targ.y);Coordinate SOUTH = new Coordinate(targ.x, targ.y + 1);Coordinate WEST = new Coordinate(targ.x - 1, targ.y);Coordinate NORTH = new Coordinate(targ.x, targ.y - 1);for (Coordinate info : roads) {if (EAST.equals(info)) {nearList.add(EAST);}if (SOUTH.equals(info)) {nearList.add(SOUTH);}if (WEST.equals(info)) {nearList.add(WEST);}if (NORTH.equals(info)) {nearList.add(NORTH);}}return nearList;}}
在Main方法中,距离可达目标点(5, 4)或(5, 5)输出如下:
nearest roads.size(): 49nearest : [{"x":2,"y":0}, {"x":2,"y":1}, {"x":3,"y":1}, {"x":4,"y":1}, {"x":5,"y":1}, {"x":5,"y":2}, {"x":5,"y":3}]
输出路径为json格式的,方便取用解析。
经过各种检验,算法无误。
0 0
- 基于无向图且权重单一的最短路径Dijkstra算法——JAVA实现
- 无向图的最短路径求解算法之——Dijkstra算法
- 无向图的最短路径求解算法之——Dijkstra算法【转】
- 无向图的最短路径求解算法之——Dijkstra算法
- 无向网图的最短路径--Dijkstra算法
- Dijkstra 最短路径算法详解 无向图
- 无向图的最短路径算法(队列实现 )
- 用Dijkstra算法求解无向图的最短路径
- 有向加权图的最短路径算法-Dijkstra
- Matalab代码 实现 Dijkstra求 有向图及无向图之间,任意两点之间的最短路径
- 有向图中单个源点到终点的最短路径--Dijkstra算法与实现
- 单源点最短路径Dijkstra算法的JAVA实现
- 单源点最短路径Dijkstra算法的JAVA实现
- 最短路径Dijkstra算法的JAVA实现--转载
- Dijkstra最短路径算法的java实现
- Dijkstra算法的最短路径实现
- dijkstra最短路径算法的实现
- 无向网图的最短路径--Floyd算法
- linux下调整进程、线程优先级
- 2012年5月SAT香港真题解析
- 鸡肋产品如何做好商业模式调整
- 多线程第二篇 多线程中的隐蔽问题揭秘
- 【数据结构—1】线性表的概念与定义
- 基于无向图且权重单一的最短路径Dijkstra算法——JAVA实现
- 判断一个数是奇数还是偶数
- MFC入门常用细节
- 2012年5月SAT香港真题解析
- The Managed Metadata Service or Connection is currently not available
- 多线程第三篇 经典线程同步之关键段CS
- JS框架解析1---框架介绍
- GRE写作必备句型
- maven+springMVC+mybatis+junit详细搭建过程