/* Copyright (c) 2014 Boundless and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/edl-v10.html * * Contributors: * Justin Deoliveira (Boundless) - initial implementation */ package org.locationtech.geogig.storage.memory; import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.PriorityQueue; import com.google.common.collect.Maps; /** * Walks a shortest path between two nodes applying Dijkstra's algorithm. * * @author Justin Deoliveira, Boundless */ public class ShortestPathWalker implements Iterator<Node> { final Node start; final Node end; final Map<Node,CostNode> nodes; final PriorityQueue<CostNode> q; ShortestPathWalker(Node start, Node end) { this.start = start; this.end = end; nodes = Maps.newHashMap(); q = new PriorityQueue<CostNode>(100, new Comparator<CostNode>() { @Override public int compare(CostNode o1, CostNode o2) { return o1.cost.compareTo(o2.cost); } }); q.offer(newNode(start, 0d)); } CostNode newNode(Node n, Double cost) { CostNode node = new CostNode(n, cost); nodes.put(n, node); return node; } @Override public boolean hasNext() { return !q.isEmpty(); } @Override public Node next() { // grab next node CostNode n = q.poll(); // update the adjacent nodes for (Node adj : n.node.to()) { CostNode m = nodes.get(adj); Double cost = n.cost + 1; if (m == null) { m = newNode(adj, cost); q.offer(m); } else { if (cost < m.cost) { // update the node m.cost = cost; q.remove(m); q.offer(m); } } } return n.node; } @Override public void remove() { throw new UnsupportedOperationException(); } static class CostNode { Node node; Double cost = Double.MAX_VALUE; CostNode(Node node, Double cost) { this.node = node; this.cost = cost; } } }