Code a priorità (comparatore) Set Mappe. TDA Priority Queue: def. informale

Documenti analoghi
TDA Priority Queue. Situazioni concrete. Definizione. Alta priorità come trovarla? Relazione di ordine totale ( ) Le implementazioni che vedremo

Esercizio. Strutture Dati

Il TDA Map. Tabelle hash

Definizione informale. Il TDA Map memorizza coppie formate da una chiave k e da un valore v. La coppia è chiamata entry. Ogni chiave deve essere unica

Il TDA Map. Definizione informale. I metodi del TDA Map 2. I metodi del TDA Map 1. Interfaccia Map 1 NO_SUCH_KEY. Tabelle hash

Il TDA Dictionary. Definizione informale. I metodi del TDA Dictionary 1. Applicazioni. I metodi del TDA Dictionary 2. I metodi del TDA Dictionary 3

Definizione informale

Definizione informale. Il TDA Dictionary (dizionario) modella una collezione di voci su cui è possibile effettuare delle ricerche

ADT Mappa. Le chiavi (il mezzo per accedere agli elementi) hanno lo scopo di rendere efficiente la ricerca. Strutture Dati

ADT Dizionario. Come nella Mappa: Diversamente dalla Mappa:

Code a priorità. Progettazione di Algoritmi Matricole congrue a 1. Docente: Annalisa De Bonis

Il TDA List è la versione orientata agli oggetti della struttura dati lista. Una sequenza di nodi

List. Il TDA List. Interfaccia Position. Il TDA Position. Il TDA List 1. Ancora su Position

Parte di laboratorio

Fondamenti di Informatica T-1

Esercizi proposti per il corso di Strutture Dati

Fondamenti di Informatica T1 Interfaccia Comparable Collezioni

Esercizio. Scrivere una classe ListMap<K, V> che implementa la mappa con una lista. Strutture Dati

Implementazione con alberi binari di ricerca

Programmazione Orientata agli Oggetti in Linguaggio Java

Metodi di una Collection

Liste concatenate. Collezione ordinata di nodi. Carlo Paolo Simona. Anna. ciascun nodo contiene due riferimenti:

Strutture dati. Il che cosa e il come. F. Damiani - Alg. & Lab. 04/05

STRUTTURE DATI: OLTRE GLI ARRAY LISTE

Conoscere l uso delle collezioni in Java. Conoscere il concetto di Generics (programmazione

Implementazione della coda con liste concatenate. x v. il front della coda è memorizzato nel primo nodo (head) della lista

Il tipo astratto di dati Node List

semplici ogni elemento contiene un riferimento al successivo doppie ogni elemento contiene un riferimento al successivo e al precedente

L ADT Priority Queues Implementazione di PQ mediante Sequenza Alberi Heap Heap Sort Adaptable Priority Queues

LINKEDLIST: implementazione iteratore. LINKEDLIST: iteratore INNERITERATOR INNERITERATOR

Fondamenti di Informatica e Laboratorio T-AB T-15 Strutture dati

Heap e Code di Priorità

ADT albero binario completo

E` un tipo astratto di dati che supporta tutti i metodi dell'adt Array list e dell'adt Lista di nodi più i seguenti:

Liste doppie. Doubly Linked Lists. GT: 6.2 (e 3.3) Argomenti della lezione

semplici ogni elemento contiene un riferimento al successivo doppie ogni elemento contiene un riferimento al successivo e al precedente

Esempi in Java di program.ne O-O

Collezioni, mappe e iteratori (a cura del Prof. Marco Patella)

La Standard Template Library Heap, algoritmi e funtori

Coda a doppio ingresso (Deque)

Standard Template Library

Interfacce. Esempio: interfaccia I con una sola funzione g() public interface I {

Coda a doppio ingresso (Deque)

SET: specifica INTRODUZIONE. SET: esempio Si stampano i numeri casuali in ordine di generazione e il contenuto dell insieme.

18 - Vettori. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Dati e Algoritmi 1: A. Pietracaprina. Mappa (I parte)

Lezione 15 programmazione in Java. Nicola Drago Dipartimento di Informatica Università di Verona

Corso: Strutture Dati Docente: Annalisa De Bonis

Gerarchie e polimorfismo: liste

TDA Position (TDA List Sequence)

Algoritmi di ordinamento

Generics & Collections

Fondamenti di Informatica T1 Mappe

Esercizi riassuntivi (Fondamenti di Informatica 2 Walter Didimo) Soluzioni

tipi di dato astratti

Programmazione in Java (I modulo) Lezione 21: Classi derivate e l'operatore instanceof Riscrivere il metodo tostring() Riscrivere il metodo equals()

Esercitazione n 2. Obiettivi

Array. Walter Didimo

Concetti Base Encapsulation ed Ereditarietà Programmare con l Ereditarietà. Java: Ereditarietà. Damiano Macedonio

lezione 5 Tipo di dato Lista Liste

Implementazione Java di un ADT

Map<K,V> ESERCITAZIONE. Dalla documentazione Java 02/04/15

Introduzione Generics Iteratori. Collezioni in Java. Dr. Giulio Pellitta. 13 aprile 2011

Corso di Algoritmi e Strutture Dati con Laboratorio. The JCF(continua): L interfaccia Map

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Binary Search Trees ( 10.1)

INFORMATICA III Parte B -Progettazione e Algoritmi

TIPO DI DATO ASTRATTO

Fondamenti di Informatica T-1

Le liste. Le liste linkate

Algoritmi di ordinamento

STRUTTURE DINAMICHE. (slide: A. Baratè L.A. Ludovico) Programmazione per la Musica Adriano Baratè

Esercitazione 5 Alberi Binari di Ricerca

Si usano quando serve accesso rapido sia in lettura che in scrittura su un insieme non ordinato

Le liste. ADT e strutture dati per la rappresentazione di sequenze. Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 5

Implementazione ADT: Alberi

SOMMARIO STACK. STACK: specifica STACK

Esercitazione n 2. Obiettivi

Strutture dati: array & co.

Array e Oggetti. Corso di Laurea Ingegneria Informatica Fondamenti di Informatica. Dispensa 17. A. Miola Gennaio 2012

Programmazione in Java (I modulo) Lezione 20: Ereditarietà

Esercitazione n 2. Obiettivi

Programmazione a Oggetti Metodologie di Programmazione 14 Maggio 2012

La struttura dati CODA

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento

Ricerca in Array/Lista. Dato un array o lista di n elementi, vogliamo trovarne uno (e.g., un numero x in un array di interi)

Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti

Handle di Funzioni Università degli Studi di Milano

Programmazione I - Preparazione A.A. 2010/2011

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Alberi. In informatica, un albero è un modello astratto di una struttura dati gerarchica

Esercizio: Lista Circolare

Implementare un'interfaccia

Algoritmi di Ricerca. Esempi di programmi Java. Prof. Angela Bonifati

Ricerca in una sequenza ordinata

Esempio su strutture dati dinamiche: ArrayList

Programmazione a Oggetti. Astrazione sui Dati e Iteratori

Transcript:

Oggi rivedremo Code a priorità (comparatore) Set Mappe TDA Priority Queue: def. informale Una coda a priorità (PQ) è un contenitore di elementi, ciascuno dei quali possiede una chiave (tipicamente numerica), che rappresenta una priorità. La chiave viene assegnata nel momento in cui l elemento è inserito nella coda (può essere modificata successivamente) Le chiavi determinano la priorità degli elementi, ovvero l ordine in cui vengono rimossi dalla coda (inserimenti arbitrari): rimuovo l elemento che ha la priorità maggiore. In realtà non c è una nozione di position, ma memorizzo gli elementi in base alle priorità. 2 1

Il TDA PriorityQueue Contenitore di oggetti Ogni oggetto è una coppia (key, value) [o anche (chiave, valore)], dove key è la priorità abbinata a value. Metodi principali insert(k, x) inserisce un oggetto (k, x) [inserisce il valore x con priorità k] removemin() [o anche extractmin()] rimuove l oggetto con chiave (key) più piccola, restituendo in output il suo valore 3 Due domande e due risposte 1. Come si fa ad associare le chiavi ai rispettivi valori? Si usa il design pattern Composition: un singolo oggetto è definito come composizione di altri oggetti public interface Entry { public Object key(); public Object element(); Interfaccia Java per gli oggetti della PQ 4 2

Due domande ancora senza risposta Come si confrontano le chiavi in modo da individuare la chiave più piccola? (Devo stabilire un criterio di confronto, cioè un ordine all interno della collezione, che consenta di confrontare una qualsiasi coppia di chiavi). Si usa il design pattern Comparator: consente di ordinare oggetti di una qualsiasi classe (anche quando non posso realizzare l interfaccia di Comparable). Il Comparatore fornisce le regole in base alle quali effettuare il confronto delle chiavi (la relazione d ordine totale) Relazione binaria riflessiva, antisimmetrica, transitiva (esiste il minimo). Indicata con 5 Ci sono diversi modi per confrontare le chiavi Vedere BENE dal testo/slides la discussione in merito ai vari modi per confrontare due oggetti (a seconda dell uso, a seconda del tipo) Vedere BENE dal testo/slides l esempio della classe per l ordinamento lessicografico dei punti tridimensionali 6 3

2.Design Pattern Comparator Ci consente di non fare riferimento alle chiavi per stabilire la regola di confronto. Un oggetto di tipo comparatore è esterno alle chiavi Permette di confrontare due chiavi (i.e., una generica coda a priorità usa un comparatore ausiliario per confrontare due chiavi) Il comparatore viene fornito al momento della costruzione della PQ La PQ può rimpiazzare un comparatore con un nuovo comparatore se diventa obsoleto o si vuole cambiarlo. 7 2. Interfaccia del TDA Comparator public interface Comparator { public int compare(object a, Object b); Se C è un oggetto di tipo comparatore, l invocazione di C.compare(a,b) restituisce un intero i, tale che i<o, se a<b; (a precede b, nell ordinamento) i=0, se a=b; (a e b sono uguali) i>0, se a>b. (a segue b nell ordinamento) C è errore se a e b non sono confrontabili. 8 4

Interfaccia/eccezioni per il TDA PQ public interface PriorityQueue { public int size(); public boolean isempty(); //restituisce il numero di entry della PQ //verifica se la PQ è vuota public Entry min() throws EmptyPQException; //restituisce, senza //rimuovere un oggetto di key minimo public Entry insert(object key, Object value) throws InvalidKeyException; //inserisce una coppia key-value e // restituisce l entry che ha creato public Entry removemin() throws EmptyPQException; //rimuove e // restituisce l entry con key minima. (ad esempio, se k è null o k è di una classe non compatibile con la classe delle altre chiavi nella PQ). 9 COME IMPLEMENTIAMO??? Due implementazioni usando liste (facili anche se non molto efficienti. Implementazione basata su heap: vedi nota sulle slides) Memorizziamo gli oggetti in una lista. Vedremo due realizzazioni, a seconda se vogliamo tenere traccia o no degli oggetti della lista ordinati sulle chiavi. Supponiamo che il confronto tra due chiavi è fatto in tempo O(1). 10 5

Implementazione PQ con una lista NON ORDINATA Memorizza gli oggetti (entry) della PQ in una lista L, implementata con una lista doppiamente concatenata, sulla quale non manteniamo l ordinamento Vantaggi/svantaggi: inserimento veloce, cancellazione lenta. Implementazione PQ con una lista ORDINATA Memorizza gli elementi della PQ in una lista (implementata come lista a doppi puntatori) per valore di chiave in ordine non decrescente. In altre parole, il primo elemento della lista è l entry con la più piccola key. Vantaggi/Svantaggi: cancellazione veloce, inserimento lento. Precisamente: 11 Implementazione di PQ con lista ordinata (porzione del codice) public class SortedListPriorityQueue implements PriorityQueue protected List L; protected Comparator c; /** Inner class for entries */ protected static class MyEntry implements Entry { protected Object k; // key protected Object v; // value public MyEntry(Object key, Object value) { //costruttore k = key; v = value; // methods of the Entry interface public Object key() { return k; public Object value() { return v; 12 6

Implementazione di PQ con lista ordinata (porzione del codice) /** Inner class for a default comparator using the natural ordering */ protected static class DefaultComparator implements Comparator { public DefaultComparator() { /* default constructor */ public int compare(object a, Object b) throws ClassCastException { return ((Comparable)a).compareTo(b); 13 Implementazione di PQ con lista ordinata (porzione del codice) /**creazione di una PQ con il default comparator public SortedListPriorityQueue () { L= new NodeList(); c= new DefaultComparator(); /**creazione di una PQ con un dato comparator public SortedListPriorityQueue (Comparator comp){ L= new NodeList(); c= comp; public void setcomparator(comparator comp) throws IllegalStateException { if (!isempty()) throw new IllegalStateException( PQ is not empty"); c = comp; Osservazione: Questo metodo consente di cambiare il comparatore 14 abbinato ad una PQ. Perché è indispensabile che la PQ sia vuota? 7

Implementazione di PQ con lista ordinata (porzione del codice) public int size() {return L.size(); public boolean isempty() {return L.isEmpty(); public Entry min() throws EmptyPQException { if (L.isEmpty()) throws EmptyPQException( PQ vuota, non c è minimo ); else return (Entry) L.first().element(); public Entry removemin() throws EmptyPQException { if (L.isEmpty()) throws EmptyPQException( PQ vuota, non c è minimo ); else return (Entry) (L.remove(first())); /** Auxiliary method that returns the key stored at a given node. */ protected Object key(position pos) { return ((Entry) pos.element()).key(); 15 /** Inserts a key-value pair and return the entry created. */ public Entry insert(object k, Object v) throws InvalidKeyException { checkkey(k); // scrivetelo voi Entry entry = new MyEntry(k, v); insertentry(entry); return entry; /** Auxiliary method used for insertion. */ protected void insertentry(entry e) { Object k = e.key(); if (L.isEmpty()) { L.insertFirst(e); // insert into empty list else if (c.compare(k, key(l.last())) > 0) { L.insertLast(e); // insert at the end of the list else { Position curr = L.first(); while (c.compare(k, key(curr)) > 0) { curr = L.after(curr); // advance toward insertion position L.insertBefore(curr, e); 16 8

Rivedete voi la discussione su setcomparator(c): si può settare il comparatore anche se ho un solo oggetto nella PQ, piuttosto che nessuno. Posso avere due entry (k,v) e (k,v) con lo stesso value, contemporaneamente nella PQ (il metodo insert(k,v) non controlla se c è un entry che ha già v come value). Perché? Se voglio usare la PQ per implementare Prim o Dijkstra, non va bene avere duplicati su un certo v: aggiungo un metodo Decrease-Key(k1,v) [se c è (k,v), DOPO ho (k1,v)] Il testo presenta le Code a Priorità adattabili (paragrafo 7.4) in cui devo gestire situazioni più vincolate (rivedetela voi dalle slides ) Implementare PQ-Sort con: UnsortedListPriorityQueue (Selection Sort) SortedListPriorityQueue (Insertion Sort) 17 Appello riservato 05-06 Scrivere un metodo removein(object x, Object y) che, invocato su una coda a priorità, restituisce un iteratore degli elementi (values) che hanno chiave compresa tra x e y, estremi inclusi, secondo l'ordine definito. Per effettuare i confronti, occorre usare il comparatore della coda a priorità (si supponga che si chiami Comp). Il metodo proposto deve usare i metodi dell'interfaccia del TDA Priority Queue e del TDA Entry per risolvere l'esercizio. Il metodo deve lasciare inalterato il contenuto della coda a priorità su cui il metodo è invocato (può modificarlo durante). Soluzione mostrata in aula 18 9

VI Appello 08-09 (ultimo fatto) Scrivere un metodo int PrimiNumeri(int k) che, invocato su una sequenza contenente interi, restituisce la somma dei k interi più piccoli che sono presenti nella sequenza. Ad esempio, se il metodo viene invocato sulla sequenza S = (45, 3, 3, 3, 4, 44, 5, 6, 6, 14, 14, 16, 42) con k = 1, allora il metodo restituirà 3. Se invece viene invocato con k = 10, il metodo restituirà 3 + 3 + 3 + 4 + 5 + 6 + 6 + 14 + 14 + 16 = 74. Il metodo proposto deve usare i metodi dell interfaccia del TDA Sequence per risolvere il quesito. Si possono usare altri TDA di appoggio, ma non array. Prestare particolare attenzione alle condizioni di errore (da gestire come eccezioni). Il metodo non deve modificare il contenuto della sequenza su cui il metodo è invocato (può modificarlo durante). Soluzione mostrata in aula Interfaccia TDA Set E un contenitore di oggetti distinti (non ci sono duplicati) non ordinati supporta le seguenti operazioni: Sia A un oggetto di tipo Set public interface Set { // Restituisce il numero degli elementi nell insieme public int size(); // Restituisce true se l insieme è vuoto public boolean isempty(); // Restituisce l unione di this e B public Set union(set B) // Restituisce l intersezione di this e B public Set intersect(set B) // Restituisce differenza di this e B public Set subtract(set B) 10

Implementazione del TDA Set con sequenza ordinata Occorre definire una relazione di ordine sugli elementi dell insieme (una qualsiasi va bene ) Usare una variabile istanza per la sequenza La classe che implementa il TDA Set avrà anche una variabile di istanza di tipo Comparator per confrontare gli elementi in base alla relazione di ordine desiderata Quindi: non implementiamo una classe Set per ciascun tipo di oggetti che si vuole usare e per ciascun modo di confrontare ciascun tipo di oggetti il metodo di confronto non dipenderà dal contesto e potrebbe anche non essere stato previsto al momento della creazione della classe Implementazione del TDA Set con sequenza ordinata Qual è la strategia usata per l implementazione dei metodi? In realtà ogni operazione che dobbiamo implementare (unione, intersezione e differenza tra due insieme), richiede che si sostituisca uno dei due (quello su cui si invoca il metodo) o se ne crei un altro - con il risultato dell operazione. Quindi da due insiemi distinti se ne crea uno, con la modalità dettata dalla operazione insiemistica invocata. Si tratta perciò di FONDERE due insiemi, dove fondere assume significati diversi a seconda dell operazione. 11

Implementazione del TDA Set con sequenza ordinata Specializzo un algoritmo generale ridefinendo alcuni passi Procediamo in questo modo (template method pattern): 1. Scriviamo una classe astratta contenente un metodo genericmerge. Si tratta di una versione generica dell algoritmo merge usato nel MergeSort. 2. Si specializza questa classe scrivendo TRE sottoclassi distinte, una per ogni metodo. Infatti ogni operazione fonde gli elementi di due insiemi, seguendo criteri diversi. Dunque le sottoclassi specializzano genericmerge rispettivamente in o Union o Intersect o subtract genericmerge: O(nA + nb) Dove na e nb sono il numero di elementi di A e di B rispettivamente Dunque le operazioni di union, intersect e subtract possono essere implementate in O(n) Implementazione del TDA Set con sequenza ordinata /** Generic merge per sequenze ordinate. */ public abstract class Merge { private Object a, b; // elementi correnti in A e B private Iterator itera, iterb; // iteratori per A e B... (continua nelle prossime slides) 12

Implementazione: template method public void merge(sequence A, Sequence B, Comparator comp, Sequence C) { itera = A.elements(); iterb = B.elements(); boolean aexists = advancea(); // Boolean test if there is a current a boolean bexists = advanceb(); // Boolean test if there is a current b while (aexists && bexists) { // Main loop for merging a and b int x = comp.compare(a, b); if (x < 0) { aisless(a, C); aexists = advancea(); else if (x == 0) { bothareequal(a, b, C); aexists = advancea(); bexists = advanceb(); else { bisless(b, C); bexists = advanceb(); while (aexists) { aisless(a, C); aexists = advancea(); while (bexists) { bisless(b, C); bexists = advanceb(); Implementazione: metodi ausiliari protected void aisless(object a, Sequence C) { protected void bothareequal(object a, Object b, Sequence C) { protected void bisless(object b, Sequence C) { Saranno specializzati nelle sottoclassi private boolean advancea() { if (itera.hasnext()) { a = itera.next(); return true; return false; Metodi ausiliari private boolean advanceb() { if (iterb.hasnext()) { b = iterb.next(); return true; return false; 13

Implementazione: specializzazioni /** Classe che specializza il genericmerge per l UNIONE di 2 insiemi */ public class UnionMerge extends Merge { protected void aisless(object a, Sequence C) { C.insertLast(a); // add a protected void bothareequal(object a, Object b, Sequence C) { C.insertLast(a); // add a (but not its duplicate b) protected void bisless(object b, Sequence C) { C.insertLast(b); // add b public class IntersectMerge extends Merge public class SubtractMerge extends Merge Implementazione interfaccia Set public class SortedListSet implements Set{ protected Sequence L; protected Comparator comp; protected int size; /** Inner class for a default comparator using the natural ordering */ protected static class DefaultComparator implements Comparator { public DefaultComparator() { /* default constructor */ public int compare(object a, Object b) throws ClassCastException { return ((Comparable)a).compareTo(b); \\ inserire i costruttori Fate voi! public int size() { return L.size(); public boolean isempty() { return L.isEmpty(); public Sequence getstructure() { return L; 14

Implementazione interfaccia Set public Set union(set B) { UnionMerge U = new UnionMerge(); Set C = new // invoco uno dei costruttori U.merge(this.getStructure(), B.getStructure(), comp, C.getStructure()); SortedListSet newset=new //invoco uno dei costruttori return newset; public Set intersect(set B) { public Set subtract(set B) { TDA MAP: definizione Il TDA Map è un contenitore di oggetti (Entry) che sono coppie chiave-valore (k,v) Sia la chiave k sia il valore v possono essere oggetti qualsiasi. Differenza con PQ: non sono consentite più entry con la stessa chiave k. Esempio di applicazione: Mappa che conserva le informazioni sugli studenti (ad esempio, nome, cognome, indirizzo, esami, numero di matricola ): la chiave potrebbe essere il numero di matricola. (Infatti non consentiamo a due persone (valori) di avere la stessa matricola (key)). 15

Operazioni sul TDA Map Le operazioni principali da fare su un TDA Map sono di ricerca, inserimento e cancellazione di elementi. size(), isempty() keys(): restituisce un iteratore delle chiavi di M values(): restituisce un iteratore dei valori di M get(k): Se la mappa M ha l entry con chiave k, restituisce il valore associato, altrimenti null. put(k, v): Inserisce l entry (k, v) nella mappa M. Se la chiave k non è già presente in M, restituisce null; altrimenti restituisce il vecchio valore associato a k. remove(k): Se nella mappa M c è un entry con chiave k, si rimuove l entry con chiave k e si restituisce il valore associato. Altrimenti si restituisce null. Osservazione su null Abbiamo visto che le operazioni get(k), put(k,v) e remove(k) se eseguite su una mappa M che non contiene un entry con chiave k, restituisce null Si tratta di un value speciale, detto sentinella. Questo significa che potrebbe esserci ambiguità con l entry (k,null), ossia con value null [poco appropriato] Se si vuole mantenere questa possibilità, si può pensare ad un eccezione. 16

Interfaccia per il TDA Map public interface Map { public int size(); //restituisce il numero di entry della Map public boolean isempty(); //verifica se la Map è vuota //inserisce una coppia key-value e rimpiazza il value precedente, se k //c è già, altrimenti null. public Object put(object key, Object value) throws InvalidKeyException; //Restituisce il value associato a k public Object get(object key) throws InvalidKeyException; //Cancella la coppia (chiave-valore) specificata da key public Object remove(object key) throws InvalidKeyException; public Iterator keys(); public Iterator values(); //Restituisce un iteratore delle chiavi della mappa //Restituisce un iteratore dei valori della mappa COME IMPLEMENTIAMO??? Cose abbastanza naturali 1. Una entry della mappa viene rappresentata dalla classe MyEntry, come fatto per le code a priorità. public interface Entry { public Object key(); public Object element(); L implementazione sarà una classe interna, come per le code a priorità. 17

COME IMPLEMENTIAMO??? Cose abbastanza naturali 2. I metodi presenti nell interfaccia Map devono lanciare l eccezione InvalidKeyException se la chiave specificata non è valida per il contenitore in esame. Ma qual è qui il criterio di validità???? 3. Il metodo checkkey dovrà solo controllare che k non è null, non c è bisogno di una relazione d ordine totale tra le chiavi Abbiamo bisogno di confrontare le chiavi. Dobbiamo decidere se due chiavi sono uguali. Se le chiavi hanno una relazione d ordine totale determinata da qualche comparatore C, possiamo usare C.compare(k1,k2) e vedere quando ritorna 0 ma non conviene. Per una mappa generica, possiamo usare un oggetto EQUALITY TESTER che supporta l operazione isequalto(k1,k2) sulle chiavi. Potremmo anche usare il metodo equals di Java, ma non è generale. 18

Abbiamo bisogno di confrontare le chiavi. Quando creiamo una mappa M, abbiniamo un EQUALITY TESTER basato su un comparatore. Nelle slides successive, usiamo = per testare l uguaglianza. Nell implementazione Java possiamo fare come per la coda a Priorità, ossia protected static class DefaultEqualityTester implements EqualityTester{ public DefaultEqualityTester() { /* default constructor */ Interfaccia da scrivere public boolean isequalto(object a, Object b) throws ClassCastException { return (a.equals(b)); Confronto con il package java.util.map Metodi del TDA Map size() isempty() get(k) put(k,v) remove(k) keys() values() Metodi java.util.map size() isempty() get(k) put(k,v) remove(k) keyset().iterator() values().iterator() Inoltre, non si usa un Equality Tester esterno, ma solo il metodo equals (se non è appropriato per il nostri oggetti vedi esempio dei punti nel piano occorre sovrascriverlo ) 19

Un implementazione basata su liste Possiamo implementare efficientemente il TDA Map usando una lista non ordinata (implementata come lista doppiamente-linkata) Memorizziamo gli elementi della mappa in una lista senza un ordinamento header nodes/positions trailer 9 a 6 c 5 f 8 d entries Esistono implementazioni migliori (basate su tabelle hash) Algoritmo get(k) [compl. O(size)] Algorithm get(k): B = M.positions() //B è un iteratore delle posizioni in M while B.hasNext() do p = B.next() //la prossima posizione in B if (p.element().key() == k) then return (p.element()).value() return null //non ci sono entry con chiave uguale a k 20

Algoritmo remove(k) [compl. O(size)] Algorithm remove(k): B =M.positions() while B.hasNext() do p = B.next() if (p.element().key() == k) then t = p.element().value() M.remove(p) size = size 1 return t return null //non c erano entry con chiave k Algoritmo put(k,v) [compl. O(size)] Algorithm put(k,v): B = M.positions() while M.hasNext() do p = B.next() if (p.element().key() == k) then t = p.element().value() M.replace(p,(k,v)) //come implemento??? Esercizio. return t M.insertLast((k,v)) size = size + 1 return null //non c erano già value con chiave k 21

III appello 08-09 Scrivere un metodo Iterator ShowValue(List KEY) che, invocato su una mappa M restituisce un iteratore dei value le cui chiavi sono conservate nella lista KEY (se una chiave in KEY non è presente in M, si dovrà avere null come valore associato). Il metodo proposto deve usare i metodi dell'interfaccia del TDA Map e del TDA List per accedere alla mappa e alla lista e risolvere l'esercizio. Il metodo non deve modificare il contenuto della mappa su cui viene invocato (può modificarlo durante). Soluzione mostrata in aula III appello 05-06 Scrivere un metodo void removemaxocc() che, invocato su una lista contenente interi, in cui ogni elemento può occorrere più volte, cancella dalla lista tutte le occorrenze dell'elemento che ha occorrenza massima. Per semplicità, si può supporre che l'elemento di occorrenza massima sia unico (ad esempio, non posso avere nella lista (1; 1; 3; 1; 3; 3; 2), essendo sia 1 sia 3 due elementi di occorrenza massima). Ad esempio, se si invoca il metodo sulla lista L = (3; 1; 4; 3; 5; 6; 3; 3; 1; 7; 4), al termine dell'esecuzione del metodo si avrà L = (1; 4; 5; 6; 1; 7; 4) (l'elemento di occorrenza massima è 3). Il metodo proposto deve usare i metodi dell'interfaccia del TDA List per accedere alla lista. Deve produrre una modifica della lista su cui si invoca il metodo. Si richiede di usare il TDA Map come struttura di appoggio. Metodi che non usano il il TDA Map non saranno valutati. Giusticare la richiesta di tale struttura di appoggio. Soluzione mostrata in aula 44 22