Capitolo 18: Strutture di dati avanzate Capitolo 18 Strutture di dati avanzate ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 1 Capitolo 18: Strutture di dati avanzate Figura 1 Un insieme di stampanti ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 2 Capitolo 18: Strutture di dati avanzate Figura 2 Classi e interfacce per gli insiemi nella libreria standard ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 3 Capitolo 18: Strutture di dati avanzate File SetTest.java import import import import java.util.HashSet; java.util.Iterator; java.util.Set; javax.swing.JoptionPane; /** Programma che illustra il funzionamento di un insieme di stringhe. L'utente può inserire e rimuovere stringhe. */ public class SetTest { public static void main(String[] args) { Set names = new HashSet(); boolean done = false; while (!done) { ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 4 Capitolo 18: Strutture di dati avanzate String input = JoptionPane.showInputDialog( "Add name, Cancel when done"); if (input == null) done = true; else { names.add(input); print(names); } } done = false; while (!done) { String input = JoptionPane.showInputDialog( "Remove name, Cancel when done"); if (input == null) done = true; else { names.remove(input); print(names); ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 5 Capitolo 18: Strutture di dati avanzate } } System.exit(0); } /** Stampa il contenuto di un insieme. @param s un insieme */ private static void print(Set s) { Iterator iter = s.iterator(); System.out.print("{ "); while (iter.hasNext()) { System.out.print(iter.next()); System.out.print(" "); } System.out.println("}"); } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 6 Capitolo 18: Strutture di dati avanzate Figura 3 Una mappa ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 7 Capitolo 18: Strutture di dati avanzate Figura 4 Classi e interfacce per le mappe nella libreria standard ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 8 Capitolo 18: Strutture di dati avanzate File MapTest.java import import import import import java.awt.Color; java.util.HashMap; java.util.Iterator; java.util.Map; java.util.Set; /** Questo programma collauda una mappa che associa nomi a colori. */ public class MapTest { public static void main(String[] args) { Map favoriteColors = new HashMap(); favoriteColors.put("Juliet", Color.pink); favoriteColors.put("Romeo", Color.green); favoriteColors.put("Adam", Color.blue); favoriteColors.put("Eve", Color.pink); print(favoriteColors); } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 9 Capitolo 18: Strutture di dati avanzate /** Stampa i contenuti di una mappa. @param m una mappa */ private static void print(Map m) { Set keySet = m.keySet(); Iterator iter = keySet.iterator(); while (iter.hasNext()) { Object key = iter.next(); Object value = m.get(key); System.out.println(key + "->" + value); } } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 10 Capitolo 18: Strutture di dati avanzate Figura 5 Una realizzazione molto semplice di tabella hash ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 11 Capitolo 18: Strutture di dati avanzate Figura 6 Una tabella hash con liste concatenate per memorizzare elementi aventi lo stesso codice hash ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 12 Capitolo 18: Strutture di dati avanzate File HashSet.java import java.util.Iterator; import java.util.AbstractSet; /** Un HashSet memorizza una raccolta non ordinata di oggetti usando una tabella di hash. */ public class HashSet extends AbstractSet { /** Costruisce una tabella di hash. @param bucketsLength la lunghezza dell’array buckets */ public HashSet(int bucketsLength) { buckets = new Link[bucketsLength]; size = 0; } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 13 Capitolo 18: Strutture di dati avanzate /** Verifica l’appartenenza all’insieme. @param x un oggetto @return true se x è un elemento dell’insieme */ public boolean contains(Object x) { int h = x.hashCode(); if (h < 0) h = -h; h = h % buckets.length; Link current = buckets[h]; while (current != null) { if (current.data.equals(x)) return true; current = current.next; } return false; } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 14 Capitolo 18: Strutture di dati avanzate /** Inserisce un elemento all’insieme. @param x un oggetto @return true se x è un oggetto nuovo, false se x era gia' presente nell'insieme */ public boolean add(Object x) { int h = x.hashCode(); if (h < 0) h = -h; h = h % buckets.length; Link current = buckets[h]; while (current != null) { if (current.data.equals(x)) return false; // gia' nell'insieme current = current.next; } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 15 Capitolo 18: Strutture di dati avanzate Link newLink newLink.data newLink.next buckets[h] = size++; return true; = new Link(); = x; = buckets[h]; newLink; } /** Elimina un oggetto dall'insieme. @param x un oggetto @return true se x viene eliminato dall’insieme, false se x non e' presente nell'insieme */ public boolean remove(Object x) { int h = x.hashCode(); if (h < 0) h = -h; h = h % buckets.length; ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 16 Capitolo 18: Strutture di dati avanzate Link current = buckets[h]; Link previous = null; while (current != null) { if (current.data.equals(x)) { if (previous == null) buckets[h] = current.next; else previous.next = current.next; size--; return true; } previous = current; current = current.next; } return false; } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 17 Capitolo 18: Strutture di dati avanzate /** Restituisce il numero di elementi nell'insieme. @return il numero di elementi */ public int size() { return size; } private Link[] buckets; private int size; private class Link { public Object data; public Link next; } private class HashSetIterator implements Iterator { ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 18 Capitolo 18: Strutture di dati avanzate /** Costruisce un iteratore per insiemi hash che punta al primo elemento dell'insieme. */ public HashSetIterator() { bucket = 0; previous = null; previousBucket = buckets.length; // imposta bucket all'indice del primo bucket non vuoto while (bucket < buckets.length && buckets[bucket] == null) bucket++; if (bucket < buckets.length) current = buckets[bucket]; else current = null; } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 19 Capitolo 18: Strutture di dati avanzate public Object next() { Object r = current.data; if (current.next == null) // avanza al prossimo bucket { previousBucket = bucket; bucket++; while (bucket < buckets.length && buckets[bucket] == null) bucket++; if (bucket < buckets.length) current = buckets[bucket]; else current = null; } else // avanza al prossimo elemento in bucket { previous = current; current = current.next; } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 20 Capitolo 18: Strutture di dati avanzate return r; } public void remove() { if (previous != null) previous.next = previous.next.next; else if (previousBucket < buckets.length) buckets[previousBucket] = null; else throw new IllegalStateException(); previous = null; previousBucket = buckets.length; } private int bucket; private Link current; private int previousBucket; private Link previous; } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 21 Capitolo 18: Strutture di dati avanzate File SetTest.java import java.util.Iterator; import java.util.Set; /** Questo programma collauda la classe insieme realizzata con tabella hash. */ public class SetTest { public static void main(String[] args) { Set names = new HashSet(101); // 101 e' un numero primo names.add("Sue"); names.add("Harry"); names.add("Nina"); names.add("Susannah"); names.add("Larry"); names.add("Eve"); names.add("Sarah" ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 22 Capitolo 18: Strutture di dati avanzate names.add("Adam"); names.add("Tony"); names.add("Katherine"); names.add("Juliet"); names.add("Romeo"); names.remove("Romeo"); names.remove("George"); Iterator iter = names.iterator(); while (iter.hasNext()) System.out.println(iter.next()); } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 23 Capitolo 18: Strutture di dati avanzate File Coin.java /** Una moneta con un valore monetario. */ public class Coin { /** Costruisce una moneta. @param aValue il valore monetario della moneta @param aName il nome della moneta */ public Coin(double aValue, String aName) { value = aValue; name = aName; } /** Restituisce il valore della moneta. @return il valore ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 24 */ public double getValue() { return value; } Capitolo 18: Strutture di dati avanzate /** Restituisce il nome della moneta. @return il nome */ public String getName() { return name; } public boolean equals(Object otherObject) { if (otherObject == null) return false; if (getClass() != otherObject.getClass()) return false; Coin other = (Coin)otherObject; return (value == other.value && name.equals(other.name)); } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 25 Capitolo 18: Strutture di dati avanzate public int hashCode() { int h1 = name.hashCode(); int h2 = new Double(value).hashCode(); final int HASH_MULTIPLIER = 29; int h = HASH_MULTIPLIER * h1 + h2; return h; } public String toString() { return "Coin[value=" + value + ",name=" + name + "]"; } private double value; private String name; } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 26 File HashCodeTest.java Capitolo 18: Strutture di dati avanzate import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** Un programma per collaudare i codici di hash delle monete. */ public class HashCodeTest { public static void main(String[] args) { Coin coin1 = new Coin(0.25, "quarter"); Coin coin2 = new Coin(0.25, "quarter"); Coin coin3 = new Coin(0.05, "nickel"); System.out.println("hash code of coin1=" + coin1.hashCode()); System.out.println("hash code of coin2=" + coin2.hashCode()); System.out.println("hash code of coin3=" + coin3.hashCode()); ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 27 Capitolo 18: Strutture di dati avanzate Set coins = new HashSet(); coins.add(coin1); coins.add(coin2); coins.add(coin3); Iterator iter = coins.iterator(); while (iter.hasNext()) System.out.println(iter.next()); } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 28 Capitolo 18: Strutture di dati avanzate Figura 7 Un albero di ricerca binario ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 29 Capitolo 18: Strutture di dati avanzate Figura 8 Un albero binario che non è un albero di ricerca binario ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 30 Capitolo 18: Strutture di dati avanzate Figura 9 Un albero di ricerca binario dopo quattro inserimenti ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 31 Capitolo 18: Strutture di dati avanzate Figura 10 Un albero di ricerca binario dopo cinque inserimenti ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 32 Capitolo 18: Strutture di dati avanzate File TreeTest.java /** Questo programma collauda una classe che realizza un albero di ricerca binario. */ public class TreeTest { public static void main(String[] args) { Tree names = new Tree(); names.insert("Romeo"); names.insert("Juliet"); names.insert("Tom"); names.insert("Dick"); names.insert("Harry"); names.print(); } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 33 Capitolo 18: Strutture di dati avanzate Figura 11 Un albero di ricerca binario sbilanciato ©2002 Apogeo 34 Capitolo 18: Strutture di dati avanzate File Tree.java /** Questa classe implementa un albero di ricerca binario i cui nodi contengono oggetti che implementano l’interfaccia Comparable. */ public class Tree { /** Costruisce un albero vuoto. */ public Tree() { root = null; } /** Inserisce un nuovo nodo nell’albero. @param obj l'oggetto da inserire */ ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 35 Capitolo 18: Strutture di dati avanzate public void insert(Comparable obj) { Node newNode = new Node(); newNode.data = obj; newNode.left = null; newNode.right = null; if (root == null) root = newNode; else root.insertNode(newNode); } /** Stampa il contenuto dell’albero in successione ordinata. */ public void print() { if (root != null) root.printNodes(); } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 36 Capitolo 18: Strutture di dati avanzate private Node root; /** Un nodo di un albero conserva un dato e i riferimenti ai nodi figlio sinistro e figlio destro. */ private class Node { /** Inserisce un nuovo nodo come discendente di questo nodo. @param newNode il nodo da inserire */ public void insertNode(Node newNode) { if (newNode.data.compareTo(data) < 0) { if (left == null) left = newNode; else left.insertNode(newNode); } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 37 Capitolo 18: Strutture di dati avanzate else if (newNode.date.compareTo (data) > 0) { if (right == null) right = newNode; else right.insertNode(newNode); } } /** Stampa questo nodo e tutti i suoi discendenti in successione ordinata. */ public void printNodes() { if (left != null) left.printNodes(); System.out.println(data); if (right != null) right.printNodes(); } public Comparable data; public Node left; public Node right; } } ©2002 Apogeo 38 Capitolo 18: Strutture di dati avanzate File TreeSetTest.java import import import import java.util.Comparator; java.util.Iterator; java.util.Set; java.util.TreeSet; /** Un programma per collaudare un insieme ad albero. */ public class TreeSetTest { public static void main(String[] args) { Coin coin1 = new Coin(0.25, "quarter"); Coin coin2 = new Coin(0.25, "quarter"); Coin coin3 = new Coin(0.25, "penny"); Coin coin4 = new Coin(0.25, "nickel"); ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 39 Capitolo 18: Strutture di dati avanzate class CoinComparator implements Comparator { public int compare(Object firstObject, Object secondObject) { Coin first = (Coin)firstObject; Coin second = (Coin)secondObject; if (first.getValue() < second.getValue()) return –1; if (first.getValue() == second.getValue()) return 0; return 1; } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 40 Capitolo 18: Strutture di dati avanzate Comparator comp = new CoinComparator(); Set coins = new TreeSet(comp); coins.add(coin1); coins.add(coin2); coins.add(coin3); coins.add(coin4); Iterator iter = coins.iterator(); while (iter.hasNext()) System.out.println(iter.next()); } } ©2002 Apogeo Horstmann-Concetti di informatica e fondamenti di Java 2 41