JAVA实现Dijkstra算法

JAVA实现Dijkstra算法

在这里插入图片描述本题以此有向图为例

算法思想:

假设有两个顶点集合S和T,集合S中存放图中已找到最短路径的顶点,集合T中存放图中剩余顶点。初始状态时,集合S中只包含源点V0,然后不断从集合T中选取到顶点V0路径长度最短的顶点Vu并入到集合S中。集合S每并入一个新的顶点Vu,都要修改顶点V0到集合T中顶点的最短路径长度值。不断重复此过程,直到集合T中的顶点全部并入集合S中为止,循环结束。

算法主要思路:

1,把有向图转换为邻接表,用任意比较大的正整数表示正无穷大。
2,引入3个辅助数组dist[]、path_data[],set_data[]。
dist[Vi]表示当前已经找到的V0到每个终点Vi的最短路径长度。初始状态:若从V0到Vi有边,则dist[i]为边上的权值,则dist[Vi]为正无穷大。
path_data[Vi]中保存从V0到Vi最短路径上Vi的前一个顶点,假设最短路径上的顶点序列为V0,V1…Vi-1,Vi,则path_data[Vi]=Vi-1。初始状态:如果V0到Vi有边,则path_data[Vi]=V0,否则path[Vi]=-1。
set_data[]为标记数组,set_data[Vi]=0表示Vi在T中,没有被并入最短路径;set_data[Vi]=1,表示Vi在S中,已经并入最短路径。set_data[V0]=1,其余元素全为0。
3,算法执行过程:
从当前dist[]选出最小值,假设最小值为dist[Vu],将set_data[Vu]设置为1,表示并入新的顶点Vu。
循环扫描图中的顶点,对每个顶点进行一下检测:
假设当前顶点为Vj,检测Vj是否已经并入S中,就是看是否set_data[Vj]=1。如果set[Vj]=1,就什么都不做;如果set_data[Vj]=0;则比较dist[Vj]和dist[Vu]+W的大小,W为边<Vu,Vj>的权值。这个比较就是看V0经过旧的最短路径到达Vj和V0经过含有Vu的新的最短路径到达Vj哪个更短。如果dist[Vj]>dist[Vu]+W,则用新的路径更新旧的,并把顶点Vu加入路径中,作为路径上Vj之前的那个顶点,否则什么否不做。

代码如下

package djstl;
public class Djstl {
	public static void Dijkstra(int [][] graph, int init_node, int MIN) {
		int len = graph[0].length;
		int index_setData = 0;
		int dist[] = new int[len];
		int set_data[] = new int[len];
		int path_data[] = new int[len];
		int min = MIN;
		// 数据初始化
		for (int i = 0; i < len; i++) {
			dist[i] = graph[init_node][i];
			if (i == init_node) {
				set_data[i] = 1;
			} else {
				set_data[i] = 0;
			}
			if (graph[init_node][i] <1000) {
				path_data[i] = init_node;

			} else {
				path_data[i] = -1;
			}
		} 
		path_data[init_node]=-1;// 初始化结束
		
		//关键操作开始
		for (int i = 0; i < graph.length; i++) {
			min=MIN;
			for (int j = 0; j < graph.length; j++) {			
				if (set_data[j] == 0 && dist[j] <min) {
					index_setData = j;
					min = dist[j];
				}
			}
			set_data[index_setData] = 1;
			//算法主要思路的第三步的实现
			for (int k = 0; k < graph.length; k++) {
				if (set_data[k] == 0 && (min + graph[index_setData][k])<dist[k]) {
					path_data[k] = index_setData;
					dist[k] = min + graph[index_setData][k];
				}
				
			}
			
		}
		
		for (int i = 1; i < graph.length; i++) {
			System.out.println("最短路径前一个结点:"+path_data[i]+"-->"+i+",长度为:"+dist[i]);
		}
		
	}

}

下面对方法进行测试:

package djstl;
public class test {
	public static void main(String[] args) {
		int N = 1000;
		int M = 0;
		int init_node=0;
		int[][] graph = { 
				{ M, 4, 6, 6, N, N, N },
				{ N, M, 1, N, 7, N, N }, 
				{ N, N, M, N, 6, 4, N },
				{ N, N, 2, M, N, 5, N }, 
				{ N, N, N, N, M, N, 6 }, 
				{ N, N, N, N, 1, M, 8 }, 
				{ N, N, N, N, N, N, M } };
		Djstl.Dijkstra(graph, init_node,N);
		
	}

}

输出结果:
在这里插入图片描述

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、付费专栏及课程。

余额充值