algorytm.org

Implementacja w Java

Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Algorytm Dijkstry - Implementacja w Java
Ocena użytkownikóww: *****  / 7
SłabyŚwietny
Nadesłany przez mephisto, 17 marca 2013 11:33
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.
Pobierz pełne rozwiązanie.

Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.

dijkstra.java:
/**
 * Implementacja algorytmu Dijkstry do znajdowania najkrotszych sciezek w grafie 
 * z krawedzami o nieujemnych wagach.
 * 
 * created by mephisto
 * www.algorytm.org
 */
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * Krawedz grafu skierowanego. Zawiera informacje od ktorej do ktorej krawedzi
 * jest poprowadzona krawedz oraz zawiera jej wage(np. dlugosc, czas itd).
 * 
 * @author mephisto
 */
class DirectedEdge {
	// wierzcholek zrodlowy
	private final int from;
	// wierzcholek docelowy
	private final int to;
	// waga
	private final long weight;

	public DirectedEdge(int from, int to, int weight) {
		this.from = from;
		this.to = to;
		this.weight = weight;
	}

	public int from() {
		return from;
	}

	public int to() {
		return to;
	}

	public long getWeight() {
		return weight;
	}

	@Override
	public String toString() {
		return String.format("%d->%d (%d) ", from, to, weight);
	}
}

/**
 * Graf skierowany reprezentowany za pomoca list sasiedztwa danych wierzcholkow
 * skierowanych.
 * 
 * @author mephisto
 */
class DirectedGraph {
	// liczba wierzcholkow
	private final int v;
	// liczba krawedzi
	private int e;
	// listy sasiedztwa
	private List<DirectedEdge>[] neighborhoodLists;

	@SuppressWarnings("unchecked")
	public DirectedGraph(int v) {
		this.v = v;
		this.e = 0;
		this.neighborhoodLists = (List<DirectedEdge>[]) new List[v];
		for (int i = 0; i < v; i++) {
			neighborhoodLists[i] = new ArrayList<DirectedEdge>();
		}
	}

	public int getNumberOfEdges() {
		return e;
	}

	public int getNumberOfVertices() {
		return v;
	}

	/**
	 * Dodaje krawedz skierowana do odpowiedniej listy sasiedztwa, listy
	 * wierzcholka, z ktorej zaczyna sie krawedz.
	 * 
	 * @param edge
	 *            krawedz, ktora ma zostac dodana do grafu
	 */
	public void addEdge(DirectedEdge edge) {
		neighborhoodLists[edge.from()].add(edge);
		e++;
	}

	/**
	 * Zwraca liste sasiedztwa danego wierzcholka.
	 * 
	 * @param v
	 *            indeks wierzcholka skierowanego
	 * @return zwraca iterowalna kolekcje krawedzi skierowanych
	 */
	public Iterable<DirectedEdge> getNeighborhoodList(int v) {
		return neighborhoodLists[v];
	}
}

/**
 * ShortestPath - algorytm Dijkstry
 * 
 * @author mephisto
 */
public class DijkstraShortestPath {

	/**
	 * Reprezentuje dystans do danej krawedzi. Uzywane do przechowywania w
	 * kolejce priorytetowej do wyboru najkrotszej krawedzi.
	 * 
	 * @author mephisto
	 */
	class DistanceToEdge implements Comparable<DistanceToEdge> {
		// krawedz
		private final int edge;
		// odleglosc do tej krawedzi
		private long distance;

		public DistanceToEdge(int edge, long distance) {
			this.edge = edge;
			this.distance = distance;
		}

		public long getDistance() {
			return distance;
		}

		public void setDistance(long distance) {
			this.distance = distance;
		}

		public int getEdge() {
			return edge;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + (int) (distance ^ (distance >>> 32));
			result = prime * result + edge;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			DistanceToEdge other = (DistanceToEdge) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (distance != other.distance)
				return false;
			if (edge != other.edge)
				return false;
			return true;
		}

		@Override
		public int compareTo(DistanceToEdge param) {
			int cmp = new Long(distance).compareTo(param.getDistance());

			if (cmp == 0) {
				return new Integer(edge).compareTo(param.getEdge());
			}
			return 0;
		}

		private DijkstraShortestPath getOuterType() {
			return DijkstraShortestPath.this;
		}
	}

	// ////////////////////////////////////////////////////////////////////
	// przechowuje krawedz z ktorej jest najblizej do biezacej okreslonej
	// indeksem tablicy
	private DirectedEdge[] edgeTo;
	// przechowuje najkrotsze znalezione odleglosci do danego wierzcholka
	private Long[] distanceTo;
	// kolejka przechowujaca biezace krawedzie uszeregowane od najkrotszej do
	// najdluzszej
	private Queue<DistanceToEdge> priorityQueue;

	public DijkstraShortestPath(DirectedGraph graph, int source) {
		// inicjacja wewnetrznych struktur
		edgeTo = new DirectedEdge[graph.getNumberOfVertices()];
		distanceTo = new Long[graph.getNumberOfVertices()];
		priorityQueue = new PriorityQueue<DistanceToEdge>(
				graph.getNumberOfVertices());

		// dla kazdego wierzcholka v ustawiamy najwieksza mozliwa wartosc jaka
		// moze przechowywac
		for (int v = 0; v < graph.getNumberOfVertices(); v++) {
			distanceTo[v] = Long.MAX_VALUE;
		}
		// odleglosc do wierzcholka zrodlowego to 0
		distanceTo[source] = 0L;

		// wstawiamy wierzholek zrodlowy do kolejki, od niego rozpoczynamy
		// poszukiwania
		priorityQueue.offer(new DistanceToEdge(source, 0L));

		// przeprowadzamy relaksacje grafu dopoki kolejka nie jest pusta
		while (!priorityQueue.isEmpty()) {
			relax(graph, priorityQueue.poll().getEdge());
		}

	}

	private void relax(DirectedGraph graph, int v) {
		// przegladamy listy sasiedztwa wszystkich wierzcholkow
		for (DirectedEdge edge : graph.getNeighborhoodList(v)) {
			int w = edge.to();

			// sprawdzamy czy zmiana wierzcholka skroci dystans z wierzcholka
			// zrodlowego
			if (distanceTo[w] > distanceTo[v] + edge.getWeight()) {
				distanceTo[w] = distanceTo[v] + edge.getWeight();
				edgeTo[w] = edge;
				DistanceToEdge dte = new DistanceToEdge(w, distanceTo[w]);

				// jesli jest juz krawedz o tej wadze to ja usuwamy, bo
				// znalezlismy lepsza droge
				priorityQueue.remove(dte);
				// wstawiamy nowa krawedz z aktualna znaleziona odlegloscia
				priorityQueue.offer(dte);
			}
		}

	}

	// jesli zwrocona wartosc wynosi Long.MAX_VALUE to oznacza, ze dany
	// wierzcholek jest nieosiagalny ze zrodla
	public long getDistanceTo(int v) {
		return distanceTo[v];
	}

	// jesli istnieje droga do danego wierzcholka jest mniejsza od
	// Long.MAX_VALUE, ktore zostalo inicjalnie ustawione dla wszystkich
	// wierzcholkow
	public boolean hasPathTo(int v) {
		return distanceTo[v] < Long.MAX_VALUE;
	}

	// jesli nie istnieje sciezka do danego wierzcholka zostanie zwrocona pusta
	// kolekcja
	public Iterable<DirectedEdge> getPathTo(int v) {
		Deque<DirectedEdge> path = new ArrayDeque<DirectedEdge>();
		// jesli nie istnieje sciezka zwroc pusta sciezke
		if (!hasPathTo(v)) {
			return path;
		}
		// dopoki istnieje krawedz dodawaj ja do stosu
		// krawedz zrodlowa jest oznaczona jako null
		for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {
			path.push(e);
		}
		return path;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Rozwiazanie przykladu z lekcji HEGARTYMATHS
		// http://www.youtube.com/watch?v=xT5o1QCeWS8
		DirectedGraph graph = new DirectedGraph(7);
		graph.addEdge(new DirectedEdge(0, 1, 4));
		graph.addEdge(new DirectedEdge(0, 2, 3));
		graph.addEdge(new DirectedEdge(0, 3, 7));

		graph.addEdge(new DirectedEdge(1, 3, 1));
		graph.addEdge(new DirectedEdge(1, 5, 4));

		graph.addEdge(new DirectedEdge(2, 3, 3));
		graph.addEdge(new DirectedEdge(2, 4, 5));

		graph.addEdge(new DirectedEdge(3, 4, 2));
		graph.addEdge(new DirectedEdge(3, 5, 2));
		graph.addEdge(new DirectedEdge(3, 6, 7));

		graph.addEdge(new DirectedEdge(4, 6, 2));

		graph.addEdge(new DirectedEdge(5, 6, 4));

		int source = 0;
		DijkstraShortestPath shortestPath = new DijkstraShortestPath(graph,
				source);

		// Wyswietla najkrotsze sciezki
		for (int target = 0; target < graph.getNumberOfVertices(); target++) {
			if (shortestPath.hasPathTo(target)) {
				System.out.printf("%d do %d (%d)  ", source, target,
						shortestPath.getDistanceTo(target));
				if (shortestPath.hasPathTo(target)) {
					for (DirectedEdge edge : shortestPath.getPathTo(target)) {
						System.out.print(edge);
					}
				}
			} else {
				System.out.printf("%d do %d - brak sciezki  ", source, target);
			}
			System.out.println();
		}

	}
}
Komentarze
photo
0 # Romek 2013-04-12 19:56
Co zrobić by ten program zadziałał w NetBeansie? jestem początkującym programistą i jak wklejam ten kod to nie wyświetla wyniku tylko błąd "run:
Error: Could not find or load main class dijkstra.Dijkstra
Java Result: 1
BUILD SUCCESSFUL (total time: 2 seconds)"

i takie coś "public class DijkstraShortes tPath {" co mogę zrobić by to zadziałało?
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
0 # mephisto 2014-08-21 13:05
Najprawdopobnie j jak zrobiles projekt, to netbeans zrobil Ci pakiet dijkstra, natomiast przyklad jest w pakiecie domyslnym. Jak masz przekopiowany kod w pakiecie domyslnym do klikniecie prawym myszy na tej klasie i tam powinno byc Run.
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
0 # Abrams 2013-06-04 10:43
@Romek:
Musisz posiadać klasę główną Dijkstra (utwórz w projekcie nową klasę o nazwie Dijkstra i zaimplementuj w niej metodę o następującej sygnaturze:
public static void main(String[] args) {
// tu kod, np. DirectedGraph dg = new DirectedGraph(5 ); itd.
}
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
0 # gosc 2013-06-09 18:03
nie brakuje tam przypadkiem czegos w metodzie relax po stworzeniu obiektu dte?
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
0 # mephisto 2014-08-21 13:06
Czego? Moze cos konktrtniej, jesli cos nie dziala prosze o wskazanie co konkretnie. Moim zdaniem nic tam nie brakuje.
Odpowiedz | Odpowiedz z cytatem | Cytować
Dodaj komentarz