java dijkstra 单源 最短路径 优先队列 n趟

6 篇文章 0 订阅
3 篇文章 0 订阅
package dijkstra;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.PriorityQueue;

public class DijkstraDemo {
	public static int nNode; 						// 有nNode+1个节点, 从0到nNode号
	public static ArrayList<ArrayList<Node>> vList; // 邻接表
	public static int[] dist;
	public static int[] vist;
	public static int[] preId;

	public static void main(String[] args) {
		buildMap();
		for(int i = 0; i <= nNode; i++){
			System.out.println("\n#######  起点 = " + i + "  #######");
			// 起点为i
			dijkstra(i);	 
			// 起点为i到其他所有点的最短路径
			ArrayList<ArrayList<Integer>> allPathFromOneNode = getAllPath(i);
		}
	}

	private static void buildMap() {
		// read data from file
		ArrayList<String> lines = new ArrayList<String>();
		File file = new File("src/dijkstra/in.txt");
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			while (br.ready()) {
				lines.add(br.readLine());
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		//
		nNode = Integer.parseInt(lines.get(0).trim());
		initSize();

		for (int i = 2; i < lines.size(); i++) {
			String[] strs = lines.get(i).trim().split(" ");
			addNodeUndirected(Integer.parseInt(strs[0]),
					Integer.parseInt(strs[1]), Integer.parseInt(strs[2]));
		}
		// addNodeUndirected(1, 2, 5);
		// addNodeUndirected(1, 3, 7);
		// addNodeUndirected(2, 3, 1);
		// addNodeUndirected(2, 4, 10);
		// addNodeUndirected(3, 4, 1);
		// addNodeUndirected(3, 5, 2);
		// addNodeUndirected(4, 5, 3);
		System.out.println("buildMap finised...");
	}

	private static void initSize() {
		vList = new ArrayList<ArrayList<Node>>();
		for (int i = 0; i <= nNode; i++) {
			vList.add(new ArrayList<Node>());
		}
		dist = new int[nNode + 1];
		vist = new int[nNode + 1];
		preId = new int[nNode + 1];
	}

	private static void dijkstra(int startId) {
		// init data
		for (int i = 0; i <= nNode; i++) {
			dist[i] = Integer.MAX_VALUE;
			vist[i] = 0;
			preId[i] = i;
		}

		// add start Node
		PriorityQueue<Node> myQueue = new PriorityQueue<Node>();
		Node start = new Node(startId, 0);
		dist[startId] = 0;
		preId[startId] = startId;
		myQueue.add(start);

		// go
		while (!myQueue.isEmpty()) {
			Node cNode = myQueue.poll();
			if (vist[cNode.id] == 1)
				continue;
			vist[cNode.id] = 1;

			int len = vList.get(cNode.id).size();
			for (int i = 0; i < len; i++) {
				Node nextNode = vList.get(cNode.id).get(i);

				int nextNodeDistFromStart = dist[cNode.id] + nextNode.distPre;
				if (nextNodeDistFromStart < dist[nextNode.id]) {
					dist[nextNode.id] = nextNodeDistFromStart;
//					nextNode.distPre = dist[nextNode.id]; // 不能修改原始点, 如果要求多次Dijkstra
					Node nextNode2 = new Node(nextNode.id, dist[nextNode.id]);
					preId[nextNode.id] = cNode.id;
					myQueue.add(nextNode2);
				}
			}
		}
		System.out.println("dijkstra finised...");
	}

	private static ArrayList<ArrayList<Integer>> getAllPath(int startId) {
		ArrayList<ArrayList<Integer>> allPathFromOneNode = new ArrayList<ArrayList<Integer>>();
		for (int i = 0; i <= nNode; i++) {
			System.out.println("dist(" + startId + "->" + i + ") = " + dist[i]);
			ArrayList<Integer> path = getPath(startId, i);
			allPathFromOneNode.add(path);
			
			// show the path from strat node to ith node
			int flag = 0;
			for (Integer id : path) {
				if (flag > 0) {
					System.out.print(" -> ");
				}
				System.out.print(id);
				flag = 1;
			}
			System.out.println();
		}
		System.out.println("getAllPath finised...");
		return allPathFromOneNode;
	}

	private static ArrayList<Integer> getPath(int startId, int cId) {
		ArrayList<Integer> path = new ArrayList<Integer>();
		ArrayList<Integer> rePath = new ArrayList<Integer>();
		if (dist[cId] == Integer.MAX_VALUE)
			return path;

		while (preId[cId] != cId) {
			rePath.add(cId);
			cId = preId[cId];
		}
		rePath.add(cId);

		for (int i = rePath.size() - 1; i >= 0; i--) {
			path.add(rePath.get(i));
		}
		return path;
	}

	private static void addNodeUndirected(int x, int y, int w) {
		Node nodeXY = new Node(y, w);
		Node nodeYX = new Node(x, w);
		vList.get(x).add(nodeXY);
		vList.get(y).add(nodeYX);
	}

	private static void addNodeDirected(int x, int y, int w) {
		Node nodeXY = new Node(y, w);
		vList.get(x).add(nodeXY);
	}

	private static void showPreId() {
		for (int i = 0; i <= nNode; i++) {
			System.out.println(preId[i]);
		}
	}
}

class Node implements Comparable<Object> {
	int id;
	int distPre; // the distance from id Node to pre node or start Node

	public Node(int id, int dist) {
		this.id = id;
		this.distPre = dist;
	}

	@Override
	public int compareTo(Object o) {
		Node other = (Node) o;
		if (this.distPre > other.distPre) {
			return 1;
		} else if (this.distPre < other.distPre) {
			return -1;
		}
		return 0;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值