实现Dijkstra’s算法(文件流输入图)


要求,输入一个包含有向图信息的文件txt(包含顶点信息和边信息)、两个顶点x,y,输出结果。输出想x到y的最短距离。


package test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Stack;

public class Dijkstra {

	static int M = 100000;
	static int edge[][] = new int[3][3];

	/*{ { 0, 0, 0, 0, 0, 0, 0, 0 },
							{ 0, M, 6, M, 5, M, M, M }, 
							{ 0, 6, M, 8, 9, 7, M, M },
							{ 0, M, 8, M, M, 5, M, M },
							{ 0, 5, 9, M, M, 15, 7, M },
							{ 0, M, 7, 5, 15, M, 8, 9 },
							{ 0, M, M, M, 7, 8, M, 11 },
							{ 0, M, M, M, M, 9, 11, M } };/* 输入的邻接矩阵 */

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		readFileByLines("C:\\Users\\David\\Desktop\\算法导论实验\\dijkstra输入文件.txt");
		int [] dist =new int[edge.length] ;
		int [] path =new int[edge.length] ;
		System.out.println(djsktra('A','H', edge, dist, path));
		showPath('A', 'H', path);
		
//		System.out.println(edge[4][1]);
/*		for(int i=0;i< edge.length;i++){
			for(int j=0;j<edge[i].length;j++){
				System.out.print(edge[i][j]+" ");
			}
			System.out.println();
		}
	*/
	}

	public static void readFileByLines(String fileName) {

		File file = new File(fileName);
		BufferedReader reader = null;
		try {
			System.out.println("以行为单位读取文件内容,一次读一整行:");
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			int line = 1;
			// 一次读入一行,直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				// 显示行号
				System.out.println("line " + line + ": " + tempString);
				line++;
				
				char [] ch = tempString.toCharArray();
				
				if(!tempString.startsWith("*")){
					if(tempString.charAt(1)!='-'){	//获得是节点一行
						int VNUM = (ch.length+1)/2;	//获取节点数目
						edge= new int[VNUM][VNUM];	//建立邻接矩阵数组,初始化为0
					}else{	//获得有向边的一行
						
				//		System.out.println((int)ch[5]);
						edge[(int)(ch[0])-65][(int)(ch[3])-65] = (int)ch[5]-48;	//把取到的大写字母转化为数字,
														//然后减去'A'的ASCII码,将ABC D转化为0123	..得到的ch[5]是'1',ASCII值是49
					}
				}
		
			}
			/*************************************************/
			//将值为0的变成一个很大的值M
			for(int i=0;i< edge.length;i++){
				for(int j=0;j<edge[i].length;j++){
					if(edge[i][j] == 0)
						edge[i][j] = M;
				}
			}
			/************************************************/
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
				}
			}
		}
	}
	
	public static int djsktra(char A,char B,int [][] ed,int dist [],int path[]){
		//将char改成int
		int a = (int)A-65;
		int b = (int)B-65;
		
		//建立3个数组,visited同来标记每个顶点是否被找到最短路径,dist用来存放剩余的顶点的当前发现的最短路径值(即没有找到确定最短路径的顶点),path[i]用来存放i的上一个节点
		boolean [] visited = new boolean[ed.length];
//		dist =new int[ed.length];
//		path = new int[ed.length];
		
		//初始化
		for(int i =0 ;i<ed[a].length;i++){
			if(ed[a][i] < M && i!=a){	
				dist[i] = ed[a][i];
				path[i] = a;
			}else{
				dist[i] = M;
				path[i] = -1;
			}
			visited[i] = false;
			dist[a] = 0;
			path[a] = a;
		}
		visited[a] = true;
		
		for(int i = 1;i<ed[a].length ;i++){
			
			//先找到当前dist值最小的节点
			int min = M;
			int index=0;
			for(int j=0;j<dist.length;j++){
				if(!visited[j] && dist[j]<min){//如果节点没有被访问过,并且节点的值小于当前的最小值
					min = dist[j];
					index = j;
				}
			}
			
			//更新dist数组和path
			visited[index] = true;
			for(int k=0;k<ed[index].length;k++){
				if(!visited[k] && ed[index][k]<M && index!=k && dist[index]+ed[index][k] < dist[k]){
					dist[k] = dist[index]+ed[index][k];		//更新dist
					path[k] = index;				//更新path
				}
			}
			
		}
		
		return dist[b];
	}

	public static void showPath(char A ,char B ,int path[]){
		//将char改成int
		int a = (int)A-65;
		int b = (int)B-65;
				
		
		Stack<Integer> stack = new Stack<Integer>();
		int u =b;
		while(b!=a){
			stack.push(b);
			b = path[b];
		}
		stack.push(a);
		while(!stack.isEmpty()){
			int pp = stack.pop();
			char ppp =(char) (pp+65); 
			System.out.print(ppp+" ");
		}
	}
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要读取文件input.txt输入数据。假设文件的数据格式如下: 第一行为两个整数n和m,表示有n个节点和m条边。 接下来m行,每行三个整数u、v和w,表示从节点u到节点v有一条边,边权为w。 最后一行为一个整数s,表示起点。 我们可以使用Scanner类来读取文件的数据。具体代码如下: ```java import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Dijkstra { public static void main(String[] args) { try { Scanner scanner = new Scanner(new File("input.txt")); int n = scanner.nextInt(); // 节点数 int m = scanner.nextInt(); // 边数 List<int[]>[] graph = new ArrayList[n]; for (int i = 0; i < n; i++) { graph[i] = new ArrayList<>(); } for (int i = 0; i < m; i++) { int u = scanner.nextInt(); int v = scanner.nextInt(); int w = scanner.nextInt(); graph[u].add(new int[]{v, w}); graph[v].add(new int[]{u, w}); } int s = scanner.nextInt(); // 起点 // TODO: 实现Dijkstra算法 } catch (FileNotFoundException e) { e.printStackTrace(); } } } ``` 接下来,我们需要实现Dijkstra算法Dijkstra算法是一种单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。具体实现过程如下: 1. 创建一个数组dist,用于存储起点s到各个节点的最短距离。初始时,将dist[s]赋为0,其余元素赋为正无穷大。 2. 创建一个数组visited,用于记录节点是否已被访问。初始时,将visited[s]赋为true,其余元素赋为false。 3. 创建一个优先队列pq,用于存储待访问的节点。初始时,将起点s加入队列。 4. 从pq取出距离起点s最近的节点u,将其标记为已访问。 5. 对于u的每个邻居节点v,如果v未被访问,则计算起点s到v的距离,并更新dist[v]的值。然后将v加入pq。 6. 重复步骤4和5,直到pq为空。 具体实现代码如下: ```java import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.PriorityQueue; import java.util.Scanner; public class Dijkstra { public static void main(String[] args) { try { Scanner scanner = new Scanner(new File("input.txt")); int n = scanner.nextInt(); // 节点数 int m = scanner.nextInt(); // 边数 List<int[]>[] graph = new ArrayList[n]; for (int i = 0; i < n; i++) { graph[i] = new ArrayList<>(); } for (int i = 0; i < m; i++) { int u = scanner.nextInt(); int v = scanner.nextInt(); int w = scanner.nextInt(); graph[u].add(new int[]{v, w}); graph[v].add(new int[]{u, w}); } int s = scanner.nextInt(); // 起点 int[] dist = new int[n]; // 存储起点s到各个节点的最短距离 boolean[] visited = new boolean[n]; // 记录节点是否已被访问 // 初始化dist数组 for (int i = 0; i < n; i++) { dist[i] = Integer.MAX_VALUE; } dist[s] = 0; PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]); // 优先队列 pq.offer(new int[]{s, 0}); while (!pq.isEmpty()) { int[] curr = pq.poll(); int u = curr[0]; if (visited[u]) { continue; } visited[u] = true; for (int[] edge : graph[u]) { int v = edge[0]; int w = edge[1]; if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.offer(new int[]{v, dist[v]}); } } } // 输出结果 for (int i = 0; i < n; i++) { System.out.printf("从节点%d到节点%d的最短距离为:%d\n", s, i, dist[i]); } } catch (FileNotFoundException e) { e.printStackTrace(); } } } ``` 注意:本代码使用了Java8的Lambda表达式来创建优先队列,需要使用Java8及以上版本的JDK才能编译运行。如果使用Java7或以下版本的JDK,可以使用匿名内部类来创建优先队列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值