Dijkstra算法Java实现

从最短路径开始,学习Dijstar算法

下面是求最短路径问题描述:


下面是Dijkstar算法的描述:


下面是使用Dijkstar算法求解右图中的问题:


下面是图的邻接矩阵:


下面是计算过程:




下面是求解最短路径:



下面是Java代码实现,其中需要注意的问题我已经标出(一定要细心!!!!):

package greedy_algorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Dijkstra {

	private Set<Integer> permanent=new HashSet<>();
	private Set<Integer> temporary=new HashSet<>();
	private Map<Integer, Integer> nodeMap=new HashMap<Integer, Integer>(); //key=永久节点,value=最短路径前一个节点,提高回溯效率
	private int [][] m;
	private Mark [][] d;
	private int n;
	private final static int MAX=65535;
	
	class Mark{
		private int length=MAX;
		private int previous=-1;
		private boolean isMarked=false;
		
		public Mark(){}
		public Mark(int length,int previous,boolean isMarked){
			this.length=length;
			this.previous=previous;
			this.isMarked=isMarked;
		}
	}
	
	public Dijkstra(){
		n=6;
		m=new int[][]{{ 0, 1, 4,-1,-1,-1},
				      { 1, 0, 2, 7, 5,-1},
				      { 4, 2, 0,-1, 1,-1},
				      {-1, 7,-1, 0, 3, 2},
				      {-1, 5, 1, 3, 0, 6},
				      {-1,-1,-1, 2, 6, 0}};
		d=new Mark[n][n];
		
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				d[i][j]=new Mark();
				//System.out.println(d[i][j].length+"  "+d[i][j].previous+"  "+d[i][j].isMarked);
			}
		}
	}
	
	public Dijkstra(int n,int [][]m,Mark [][]d){
		this.n=n;this.m=m;this.d=d;
		if(n!=m.length && n!=m[0].length &&
		   n!=d.length && n!=d[0].length){
			System.out.println("输入格式有误");
			System.exit(1);
		}
	}
	
	public void shortestPath(){
		ArrayList<Mark> vList;
		permanent.add(0);
		for(int i=1;i<n;i++){
			temporary.add(i);
		}
		d[0][0]=new Mark(0,-1,true);
		nodeMap.put(0, -1);
		/*for(int q=0;q<n;q++)
			System.out.print("("+d[0][q].length+","+d[0][q].previous+","+d[0][q].isMarked+")  ");
		System.out.println();*/
		for(int i=1;i<n;i++){
			for(int t:temporary){
				vList=new ArrayList<Dijkstra.Mark>();
				for(int p:permanent){
					if(m[t][p]!=-1){
						vList.add(new Mark(getLength(t, p),p,false));
					}
				}
				if(vList.size()!=0){
					d[i][t]=getMin(vList);
				}
			}
			markNode(i);
			/*for(int r=0;r<n;r++)
				System.out.print("("+d[i][r].length+","+d[i][r].previous+","+d[i][r].isMarked+")  ");
			System.out.println();*/
		}
		
	}
	
	public void traceBack(int end){
		int node=end;
		for(int i=0;i<n;i++){
			if(d[i][node].isMarked==true){
				System.out.println("The shortest lenth from V0 to V"+node+" is:"+d[i][node].length);
			}
		}
		System.out.println("The shortest path is:");
		trace(end,end);
	}
	
	public void trace(int end,int last){
		int node =end;
		if(node>=0){
			trace(nodeMap.get(node),last);
			if(node==last)
				System.out.print("V"+node);
			else
				System.out.print("V"+node+"->");
		}
	}
	
	public int getLength(int t,int p){
		int length=m[t][p];
		for(int i=0;i<n;i++){
			if(d[i][p].isMarked==true){
				length+=d[i][p].length;
				break;
			}
		}
		return length;
	}
	
	public Mark getMin(ArrayList<Mark> vList){
		Mark mark=new Mark();
		int min=MAX;            //注意这里一定是min=MAX,这个地方的问题查了好久的错误!!!
		//System.out.println("min="+min);
		for(Mark c:vList){
			//System.out.println("("+c.length+","+c.previous+","+c.isMarked+")");
			if(min>c.length){
				min=c.length;
				mark=c;
				//System.out.println("break");
			}
		}
		//System.out.println("("+mark.length+","+mark.previous+","+mark.isMarked+")");
		return mark==null?new Mark(-1,-1,false):mark;
	}
	
	public void markNode(int row){
		int min=MAX;
		int position=-1;
		for(int j=0;j<n;j++){
			if(d[row][j].length!=MAX){
				if(min>d[row][j].length){
					min=d[row][j].length;
					position=j;
				}
			}
		}
		if(position!=-1){
			d[row][position].isMarked=true;
			permanent.add(position);
			temporary.remove(position);
			nodeMap.put(position, d[row][position].previous);
		}
	}
	public static void main(String[] args) {
		Dijkstra dijkstra=new Dijkstra();
		dijkstra.shortestPath();
		/*for(Map.Entry<Integer, Integer> entry:dijkstra.nodeMap.entrySet())
			System.out.println(entry);*/
		dijkstra.traceBack(5);
	}
}






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是一种用于寻找图中两点之间最短路径贪心算法,通常用于解决单源最短路径问题。在Java实现Dijkstra算法,你可以按照以下步骤进行: 1. 初始化:创建一个优先队列(通常使用`PriorityQueue`或自定义最小堆),存储顶点和它们的距离(初始时距离为无穷大,源节点距离为0)。 2. 创建邻接表或邻接矩阵表示图。 3. 主循环: a. 从队列中取出当前最短距离的节点。 b. 更新与其相邻节点的距离,如果通过当前节点到达更短,更新距离,并标记该节点已访问。 c. 将未访问的邻居节点加入队列。 4. 当队列为空或找到目标节点时,算法结束。此时队列中的最后一个元素即为目标节点,且所有节点的距离值即是最短路径。 以下是简单的Java代码实现: ```java import java.util.*; public class Dijkstra { private final int V; // 图的顶点数 private List<List<Edge>> adj; // 邻接列表 private int[] dist; // 存储每个节点到源的距离 // 边类,包含起点、终点和权重 class Edge implements Comparable<Edge> { int src, dest, weight; public Edge(int src, int dest, int weight) { this.src = src; this.dest = dest; this.weight = weight; } @Override public int compareTo(Edge other) { return Integer.compare(this.weight, other.weight); } } public Dijkstra(int v, List<List<Edge>> adj) { this.V = v; this.adj = adj; dist = new int[V]; Arrays.fill(dist, Integer.MAX_VALUE); dist = 0; } // Dijkstra算法核心部分 public void dijkstra() { PriorityQueue<Edge> pq = new PriorityQueue<>(); pq.add(new Edge(0, 0, 0)); // 元素为 (距离, 节点, 来源) while (!pq.isEmpty()) { Edge curr = pq.poll(); int u = curr.dest; // 当前节点 if (dist[u] < curr.weight) continue; // 已经找到更短路径,跳过 for (Edge e : adj.get(u)) { int v = e.dest, alt = dist[u] + e.weight; if (alt < dist[v]) { dist[v] = alt; pq.removeIf(edge -> edge.src == v); // 如果找到更短路径,移除旧路径 pq.offer(new Edge(v, alt, u)); // 添加新路径 } } } } // 返回源节点到所有其他节点的最短距离 public int[] printDistances() { return dist; } // 示例用法 public static void main(String[] args) { List<List<Edge>> adj = new ArrayList<>(); // 图的邻接列表构建 // 填充邻接列表... Dijkstra dijkstraAlg = new Dijkstra(V, adj); dijkstraAlg.dijkstra(); int[] shortestDist = dijkstraAlg.printDistances(); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值