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 Prima - Implementacja w Java
Ocena użytkownikóww: *****  / 4
SłabyŚwietny
Nadesłany przez mephisto, 25 marca 2013 21:30
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.

LazyPrimMinimumSpanningTree.java:
/**
 * Implementacja leniwej wersji algorytmu Prima do znajdowania minimalnego drzewa 
 * rozpinajacego w spojnym nieskierowanym grafie.
 * 
 * created by mephisto
 * www.algorytm.org
 */
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * Krawedz grafu nieskierowanego. Zawiera informacje, ktore wierzcholki laczy
 * krawedz oraz zawiera jej wage(np. dlugosc, czas itd).
 * 
 * @author mephisto
 */
class Edge implements Comparable<Edge> {
	// jeden wierzcholek
	private final int v;
	// drugi wierzcholek
	private final int w;
	// waga
	private final long weight;

	public Edge(int v, int w, int weight) {
		this.v = v;
		this.w = w;
		this.weight = weight;
	}

	/**
	 * 
	 * @return jeden z wierzcholkow
	 */
	public int getEitherVertex() {
		return v;
	}

	/**
	 * 
	 * @param vertex
	 *            jeden z wierzcholkow krawedzi
	 * @return wierzcholek, ktory wspoltworzy krawedz z wierzcholkiem
	 *         {@code vertex}
	 */
	public int getOtherVertex(int vertex) {
		if (vertex == v) {
			return w;
		} else if (vertex == w) {
			return v;
		}
		throw new IllegalArgumentException("Wrong vertex!");
	}

	/**
	 * 
	 * @return wage krawedzi
	 */
	public long getWeight() {
		return weight;
	}

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

	@Override
	public int compareTo(Edge arg) {
		if (getWeight() < arg.getWeight()) {
			return -1;
		} else if (getWeight() > arg.getWeight()) {
			return 1;
		}
		return 0;
	}
}

/**
 * Graf nieskierowany reprezentowany za pomoca list sasiedztwa danych
 * wierzcholkow.
 * 
 * @author mephisto
 */
class Graph {
	// liczba wierzcholkow
	private final int v;
	// liczba krawedzi
	private int e;
	// listy sasiedztwa
	private List<Edge>[] adjacencyLists;

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

	/**
	 * 
	 * @return liczbe krawedzi w grafie
	 */
	public int getNumberOfEdges() {
		return e;
	}

	/**
	 * 
	 * @return liczbe wierzcholkow w grafie
	 */
	public int getNumberOfVertices() {
		return v;
	}

	/**
	 * Dodaje krawedz do odpowiednich list sasiedztwa(obu koncow krawedzi).
	 * 
	 * @param edge
	 *            krawedz, ktora ma zostac dodana do grafu
	 */
	public void addEdge(Edge edge) {
		int v = edge.getEitherVertex();
		int w = edge.getOtherVertex(v);
		adjacencyLists[v].add(edge);
		adjacencyLists[w].add(edge);
		e++;
	}

	/**
	 * Zwraca liste sasiedztwa danego wierzcholka.
	 * 
	 * @param v
	 *            indeks wierzcholka
	 * @return zwraca iterowalna kolekcje krawedzi
	 */
	public Iterable<Edge> getAdjacencyList(int v) {
		return adjacencyLists[v];
	}
}

public class LazyPrimMinimumSpanningTree {
	// zawiera flagi, czy dany wierzcholek zostal odwiedzony
	private boolean[] marked;
	// krawedzie minmalnego drzewa rozpinajacego
	private Queue<Edge> minimumSpanningTree;
	// krawedzie przekroju i krawedzie niewybieralne
	private Queue<Edge> priorityQueue;
	// sumaryczna waga drzewa
	private long weight;

	public LazyPrimMinimumSpanningTree(Graph graph) {
		marked = new boolean[graph.getNumberOfVertices()];
		minimumSpanningTree = new LinkedList<Edge>();
		priorityQueue = new PriorityQueue<Edge>(graph.getNumberOfVertices());

		// odwiedzamy pierwszy wierzcholek
		visit(graph, 0);
		while (!priorityQueue.isEmpty()) {
			// pobieramy kolejna krawedz z kolejki priorytetowj
			Edge e = priorityQueue.poll();
			int v = e.getEitherVertex();
			int w = e.getOtherVertex(v);
			// jesli wierzcholki sa oznaczone jako odwiedzone pomijamy reszte
			// instrukcji
			if (marked[v] && marked[w]) {
				continue;
			}
			// dodajemy do drzewa rozpinajacego krawedz
			minimumSpanningTree.offer(e);
			// aktualizacja wagi drzewa rozpinajacego
			weight += e.getWeight();

			// dodajemy do drzewa wierzcholki jesli sa nieodwiedzone
			if (!marked[v]) {
				visit(graph, v);
			}
			if (!marked[w]) {
				visit(graph, w);
			}
		}
	}

	/**
	 * 
	 * @return iterowalna kolekcje krawedzi wyznaczonego drzewa
	 */
	public Iterable<Edge> edges() {
		return minimumSpanningTree;
	}

	public long getWeight() {
		return weight;
	}

	private void visit(Graph graph, int v) {
		// oznaczamy wierzcholek jako odwiedzony
		marked[v] = true;
		// dodajemy wszystkie nieodwiedzone sasiednie wierzcholki vierzcholka v
		// do kolejki priorytetowej
		for (Edge edge : graph.getAdjacencyList(v)) {
			if (!marked[edge.getOtherVertex(v)]) {
				priorityQueue.offer(edge);
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Rozwiazanie przykladu z lekcji HEGARTYMATHS
		// http://www.youtube.com/watch?v=DqpmZiC3ito&list=PL7F1A69E79B5D6E3D
		Graph graph = new Graph(5);
		graph.addEdge(new Edge(0, 1, 6));
		graph.addEdge(new Edge(0, 2, 4));
		graph.addEdge(new Edge(0, 3, 8));
		graph.addEdge(new Edge(0, 4, 2));

		graph.addEdge(new Edge(1, 2, 5));
		graph.addEdge(new Edge(1, 3, 8));
		graph.addEdge(new Edge(1, 4, 6));

		graph.addEdge(new Edge(2, 3, 9));
		graph.addEdge(new Edge(2, 4, 4));

		graph.addEdge(new Edge(3, 4, 7));

		LazyPrimMinimumSpanningTree lazyPrimMST = new LazyPrimMinimumSpanningTree(
				graph);

		// krawedzie znalezionego drzewa
		for (Edge edge : lazyPrimMST.edges()) {
			System.out.println(edge);
		}
		System.out.println("Suma wag: " + lazyPrimMST.getWeight());

	}
}
Dodaj komentarz