import java.util.*; public class GraphUtil { /* Stampa del grafo */ public static void print(Graph g) { for (Node v : g.getNodes()) { System.out.print(v + " : "); for (Edge u : g.getOutEdges(v)) { System.out.print(u+" "); } System.out.println(); } } /* Depth-First Search (Visita in Profondità) */ public static void dfs(Graph g, Node source) { System.out.println("DFS: "); Stack> stack = new Stack>(); HashSet> marked = new HashSet>(); stack.push(source); marked.add(source); while(!stack.empty()) { Node u = stack.pop(); System.out.print(u.getElement() + " "); for(Edge e : g.getOutEdges(u)) { Node v = e.getTarget(); if(!marked.contains(v)) { stack.push(v); marked.add(v); } } } System.out.println(); } /* Breadth-First Search (Visita in Ampiezza) */ public static void bfs(Graph g, Node source) { System.out.println("BFS: "); Queue> queue = new ArrayDeque>(); HashSet> marked = new HashSet>(); queue.add(source); marked.add(source); while(!queue.isEmpty()) { Node u = queue.remove(); System.out.print(u.getElement() + " "); for(Edge e : g.getOutEdges(u)) { Node v = e.getTarget(); if(!marked.contains(v)) { queue.add(v); marked.add(v); } } } System.out.println(); } /* Algoritmo di Dijkstra per Single Source Shortest Path Variante che non utilizza il metodo replaceKey del MinHeap (inserisce più HeapEntry corrispondenti allo stesso nodo) */ public static void sssp(Graph g, Node source) { System.out.println("SSSP: "); MinHeap> pqueue = new MinHeap>(); HashMap, Integer> dist = new HashMap, Integer>(); final int INFINITY = 100000; // = "Infinito" // (NB.: deve essere maggiore della somma di tutti i pesi del grafo, altrimenti è scorretto) // Inizializzazione for(Node u : g.getNodes()) { if(u == source) { pqueue.insert(0, u); dist.put(u, 0); } else { pqueue.insert(INFINITY, u); dist.put(u, INFINITY); } } // Ciclo principale while (!pqueue.isEmpty()) { HeapEntry> hu = pqueue.removeMin(); Node u = hu.getValue(); for(Edge e : g.getOutEdges(u)) { Node v = e.getTarget(); if (dist.get(u) + e.getWeight() < dist.get(v)) { pqueue.insert(dist.get(u) + e.getWeight(), v); dist.put(v, dist.get(u) + e.getWeight()); } } } for(Node u : g.getNodes()) { System.out.println(u + " " + dist.get(u)); } } /* Algoritmo di Dijkstra per Single Source Shortest Path Variante che utilizza il metodo replaceKey del MinHeap (sfrutta il fatto che le HeapEntry aggiornano da sole la loro posizione nel MinHeap) */ public static void sssp_fast(Graph g, Node source) { System.out.println("SSSP-fast: "); MinHeap> pqueue = new MinHeap>(); HashMap, HeapEntry>> dist = new HashMap, HeapEntry>>(); final int INFINITY = 100000; // = "Infinito" // (NB.: deve essere maggiore della somma di tutti i pesi del grafo, altrimenti è scorretto) // Inizializzazione for(Node u : g.getNodes()) { HeapEntry> hu = pqueue.insert(u == source ? 0 : INFINITY, u); dist.put(u, hu); } // Ciclo principale while (!pqueue.isEmpty()) { HeapEntry> hu = pqueue.removeMin(); Node u = hu.getValue(); for(Edge e : g.getOutEdges(u)) { Node v = e.getTarget(); if (dist.get(u).getKey() + e.getWeight() < dist.get(v).getKey()) { pqueue.replaceKey(dist.get(v), dist.get(u).getKey() + e.getWeight()); } } } for(Node u : g.getNodes()) { System.out.println(u + " " + dist.get(u).getKey()); } } /* Test */ public static void main(String[] args) { Graph gra = new Graph(); Node a = new Node(new String("a")); Node b = new Node(new String("b")); Node c = new Node(new String("c")); Node d = new Node(new String("d")); Node e = new Node(new String("e")); Node f = new Node(new String("f")); gra.insertNode(a); gra.insertNode(b); gra.insertNode(c); gra.insertNode(d); gra.insertNode(e); gra.insertNode(f); gra.insertEdge(a, b, 2); gra.insertEdge(a, c, 1); gra.insertEdge(a, d, 5); gra.insertEdge(b, c, 2); gra.insertEdge(b, d, 3); gra.insertEdge(c, d, 3); gra.insertEdge(c, e, 1); gra.insertEdge(e, d, 1); gra.insertEdge(d, f, 5); gra.insertEdge(e, f, 2); print(gra); System.out.println(); // Test per DFS dfs(gra, a); // Test per BFS bfs(gra, a); // Test per SSSP (Dijkstra) //sssp(gra, a); sssp_fast(gra, a); } }