java 实现的Dijstra算法

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Dijstra {
	private List<Arc> arcs;
	private List<Integer> vertexs;
	private List<Integer> visitedNode; //未访问点集合
	private List<Integer> unVisitedNode;//已访问点集合
	private Map<Integer,Double> shortestPathLength;//起始点到该点的最短距离
	private Map<Integer,Integer> shortestPath;//最短距离,该点的前一个点
	private final double MAXLENGTH=100000000.0d;
	public Dijstra(List<Arc> arcs, List<Integer> vertexs) {
		this.arcs = arcs;
		this.vertexs = vertexs;
		visitedNode=new ArrayList<Integer>();
		unVisitedNode=new ArrayList<Integer>();
		shortestPathLength=new HashMap<Integer,Double>();
		shortestPath=new HashMap<Integer,Integer>();
	}
	public void init(int startNode){
		//初始化访问与未访问集合
		visitedNode.add(startNode);
		for(Integer node:vertexs){
			if(node.intValue()!=startNode){
				unVisitedNode.add(node);
			}
		}
		//初始化所有点到开始的最短路径
		shortestPathLength.put(startNode,0.0d);
		shortestPath.put(startNode, -1);
		for(int unNode:unVisitedNode){
			boolean access=false;
			for(Arc a:arcs){
				if(a.getNode1()==startNode&&a.getNode2()==unNode){ //若与起始点相连
					shortestPathLength.put(unNode, a.getLength());
					access=true;
					break;
				}
			}
			if(!access){
				shortestPathLength.put(unNode,MAXLENGTH);
			}
		}
		//初始化第一条路径
		int lastVisitedNode=startNode;
		for(int unNode:unVisitedNode){//遍历所有未访问的点
			double pathLength=getLength(lastVisitedNode,unNode);//两点的距离
			if(pathLength>0.0){//可达
				//重新计算 路径长度,与之前的对比
				double newPathLength=pathLength+shortestPathLength.get(lastVisitedNode);
				double oldPathLength=shortestPathLength.get(unNode);
				if(oldPathLength>=newPathLength){
					shortestPath.put(unNode, lastVisitedNode);
					shortestPathLength.put(unNode,newPathLength+shortestPathLength.get(lastVisitedNode));
				}
			}
		}
	}
	public void execute(){
		while(unVisitedNode.size()>0){
			int lastVisitedNode=visitedNode.get(visitedNode.size()-1);//之前最后访问的点
			for(int unNode:unVisitedNode){//遍历所有未访问的点
				double pathLength=getLength(lastVisitedNode,unNode);//两点的距离
				if(pathLength>0.0){//可达
					//重新计算 路径长度,与之前的对比
					double newPathLength=pathLength+shortestPathLength.get(lastVisitedNode);
					double oldPathLength=shortestPathLength.get(unNode);
					if(oldPathLength>newPathLength){
						shortestPath.put(unNode, lastVisitedNode);
						shortestPathLength.put(unNode,newPathLength+shortestPathLength.get(lastVisitedNode));
					}
				}
			}
		    //好到所有的未访问的节点中  到起始点距离最小的点
			Integer node=getMinPathLengthNode();
			visitedNode.add(node);
			unVisitedNode.remove(node);
		}
	}
	public List<Integer> getShortestPath(int node){
		List<Integer> path=new ArrayList<Integer>();
		getPath(path,node);
		Collections.reverse(path);
		return path;
	}
	private void getPath(List<Integer> path,int node){
		int pre=shortestPath.get(node);
		if(pre==-1){
			return;
		}else{
			path.add(pre);
			getPath(path,pre);
		}
	}
	//返回未访问的节点中 距离起始点最近的一个
	private Integer getMinPathLengthNode(){
		Integer minNode = null;
		double min=10000000000.0d;
		for(Integer node:unVisitedNode){
			double length=shortestPathLength.get(node);
			if(length<min){
				minNode=node;
				min=length;
			}
		}
		return minNode;
	}
	private double getLength(int node1,int node2){
		double length=-1.0d;
		for(Arc a:arcs){
			if(a.getNode1()==node1&&a.getNode2()==node2){
				length=a.getLength();
			}
		}
		return length;
	}
	
	
}


class Arc{
	
	private int node1;
	private int node2;
	private double length;
	public Arc(int node1, int node2, double length) {
		this.node1 = node1;
		this.node2 = node2;
		this.length = length;
	}
	public int getNode1() {
		return node1;
	}
	public void setNode1(int node1) {
		this.node1 = node1;
	}
	public int getNode2() {
		return node2;
	}
	public void setNode2(int node2) {
		this.node2 = node2;
	}
	public double getLength() {
		return length;
	}
	public void setLength(double length) {
		this.length = length;
	}
}


		List<Arc> arcs=new ArrayList<Arc>();
		List<Integer> vertexs=new ArrayList<Integer>();
		vertexs.add(1);
		vertexs.add(2);
		vertexs.add(3);
		vertexs.add(4);
		vertexs.add(5);
		arcs.add(new Arc(1,2,10));
		arcs.add(new Arc(1,4,30));
		arcs.add(new Arc(1,5,100));
		arcs.add(new Arc(2,3,50));
		arcs.add(new Arc(3,5,10));
		arcs.add(new Arc(4,3,20));
		arcs.add(new Arc(4,5,60));
		
		
		
		Dijstra dj=new Dijstra(arcs,vertexs);//Dijstra找全局最优
		dj.init(1);
		dj.execute();
		List<Integer> result=dj.getShortestPath(5);
		System.out.println(result.toString());



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是用于解决单源最短路径问题的一种高效算法,特别是在有向无环图(DAG)或带权重的边的图中。在Java实现Dijkstra算法,你可以使用优先队列(通常使用`java.util.PriorityQueue`)来存储尚未确定最短路径的节点,以及一个哈希映射或邻接表来存储图的结构。 以下是Java实现Dijkstra算法的一个基本步骤: 1. 初始化:创建一个HashMap或类似的数据结构,将起点的距离设为0,其他所有节点的距离设为无穷大,同时标记为未访问。 2. 创建优先队列:将起点放入队列,并设置其优先级为起点距离。 3. 主循环:从队列中取出当前距离最小的节点(通常是最小优先级的节点),然后更新其相邻节点的距离,如果通过当前节点到达更短,就更新这些节点的距离并将它们加入队列。 4. 遍历邻接节点:对于每个相邻节点,检查通过当前节点到达它的路径是否比之前记录的更短。如果是,更新并标记该节点为已访问。 5. 重复步骤3和4,直到队列为空或找到终点。如果队列为空且未访问到终点,说明找不到从起点到终点的路径。 ```java import java.util.*; class Node implements Comparable<Node> { int id; int distance; Node previous; public Node(int id) { this.id = id; this.distance = Integer.MAX_VALUE; } @Override public int compareTo(Node other) { return Integer.compare(this.distance, other.distance); } } public class Dijkstra { // 使用PriorityQueue存储节点 private PriorityQueue<Node> queue = new PriorityQueue<>(); // 图的邻接表或哈希映射 private Map<Integer, List<Node>> graph; public List<Node> dijkstra(int start) { // ... (初始化、添加起点到队列等) while (!queue.isEmpty()) { Node current = queue.poll(); // 取出距离最小的节点 // 更新未访问的邻居 for (Node neighbor : graph.get(current.id)) { int distanceToNeighbor = current.distance + neighbor.distance; if (distanceToNeighbor < neighbor.distance) { neighbor.distance = distanceToNeighbor; neighbor.previous = current; queue.offer(neighbor); } } } // 返回从起点到终点的路径,如果找到 return buildPath(start); } private List<Node> buildPath(int end) { List<Node> path = new ArrayList<>(); Node currentNode = endNode(end); while (currentNode != null) { path.add(currentNode); currentNode = currentNode.previous; } Collections.reverse(path); return path; } // ... (获取结束节点的方法,可能需要一个额外的哈希映射存储每个节点的结束标识) } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值