• Non ci sono risultati.

Mappa

N/A
N/A
Protected

Academic year: 2021

Condividi "Mappa"

Copied!
126
0
0

Testo completo

(1)

Dati e Algoritmi 1: A. Pietracaprina

(2)

Descrizione generale e applicaizoni

UnaMappa`e unacollezione di entry che permette di ricercare, inserire e rimuovere entry in base alle loro chiavi(come unindice).

APPLICAZIONI:

• Database. Ad es.,studentisu Uniweb:

- chiave: numero di matricola

- valore: tutte le informazioni dello studente

• Compilatori. Ad es., per il type checking di variabili:

- chiave: nome della variabile

- valore: tipo

• Motori di ricerca. Ad es., liste invertite:

- chiave: parola

- valore: lista di documenti (ad es., pagine web)

• Data analysis. Ad es., conteggio di frequenze dioggetti:

- chiave: oggetto

- valore: numero di occorrenze

(3)

Definizione e interfaccia

Definizione di Mappa

Mappa

: collezione di entry con

chiavi distinte

provenienti da un

universo

U

su cui `

e definito l’operatore “

=

”, che supporta i metodi

get, put, e remove specificati sotto (concetto analogo di indice).

public interface Map<K,V>{

int size();

boolean isEmpty(); V get (K key);

V put (K key, V value); V remove (K key); Iterable<K> keySet(); Iterable<V> values();

Iterable<Entry<K,V>> entrySet(); }

(4)

• get(K key): se∃ (key,x)restituiscexaltrimenti restituiscenull • put(K key, V value): se∃ (key,x) mettevalueal posto dixe

restituiscex, altrimenti inserisce l’entry(key, value)e restituisce

null

• remove(K key): se∃ (key,x) rimuove la entry e restituiscex,

altrimenti restituiscenull

• keySet(),values(),entrySet(): restituiscono strutture (Iterable) contenenti, rispettivamente, le chiavi, i valori e le entry della mappa che possono essere enumerate da iteratori (iterator).

N.B.: la mappa `e vista come associative array nel senso che la chiave

della entry `e usata come un “indice” di accesso alla mappa.

(5)

Osservazioni

• Universo delle chiavi: non necessariamente ordinato. Se ordinato,

si parla diMappa ordinata(Sorted Map in Inglese) e, in questo

caso, sono possibili implementazioni pi`u efficienti al caso pessimo.

• Chiavi distinte o replicate: la Mappa assume che le chiavi siano

tutte distinte. Una variante della Mappa, chiamataMultimap,

permette di avere pi`u entry con la stessa chiave.

Noi studieremo implementazioni basate su: • Tabelle hash(Mappa)

• Alberi di ricerca (binari e non)(Mappa ordinata) e discuteremo come implementare una Multimap.

(6)

Mappa in Java

In java.util: interface Map<K,V>

al suo interno `e definita una interfaccia statica Map.Entry<K,V>

l’interfaccia Map.Entry pu`o essere usata ovunque l’interfaccia Map

sia visibile

dichiarare Entry all’interno di Map serve solo per comunicare

all’utente che verr`a usata solo nel contesto dell’uso di Map

• Entry `e statica nel senso che `e associata alla classe Map e non a

singoli oggetti di quella classe. In realt`a tutte le interfacce nested

sono static per default.

(7)

Esercizio

SiaDun documento diN parole, rappresentato da un array

D[0], D[1], . . . , D[N − 1]. Progettare un algoritmo che, usando una Mappa d’appoggio, restituisca la parola con il massimo numero di

occorrenze inD. Se ne esistono pi`u di una, l’algoritmo ne restituisce una

arbitraria tra esse.

L’uso della Mappa deve essere fatto tramite i metodi dell’interfaccia Map.

L’analisi della complessit`a sar`a effettuata in un altro esercizio, dopo aver

studiato le possibili implementazioni della Mappa.

Osservazione

Contare le frequenze delle parole `e una primitiva importante per l’analisi

statistica di documenti, utilizzata ad esempio per classificare i documenti in catergorie.

(8)

Implementazioni semplici ma inefficienti della Mappa

Si considerino le seguenti implementazioni di unaMappa di n entry:

Lista (position-based): i metodi get, put, remove richiedono

tempoΘ (n)al caso pessimo, in quantorichiedono tutti la ricerca di

una chiave (anche put) per assicurare il vincolo dellechiavi distinte. (INEFFICIENTE in TEMPO)

• Array di taglia |U|(assumendo di avere un mapping 1-1 tra chiavi e celle dell’array): i metodi get, put, remove richiedono tempo Θ (1), al caso pessimo, ma lo spazio occupato `eΘ (|U|), che potre

essere molto elevato se |U|  n. (INEFFICIENTE in SPAZIO)

(9)

Implementazione della Mappa

tramite Tabella Hash

(10)

Tabella Hash

Una Tabella Hash `

e definita dai seguenti

3 ingredienti

principali:

Funzione hash

h

h : U = {chiavi} → [0, N − 1]

pi`

u in particolare (convenzione Java):

h : k

−−−−−−−−−−−→ Z

hash code

−−−−−−−−−−−−→ [0, N − 1]

compression function

Bucket Array

A

di capacit`

a

N

.

A[i ]

rappresenta l’

i

-esimo

bucket al quale vengono associate tutte le entry

< k, v >

tali

che

h(k) = i

(

0 ≤ i < N

)

Metodo di risoluzione delle collisioni che sono costituite da

chiavi distinte associate allo stesso bucket dalla funzione hash.

(11)

Tabelle Hash (continua)

Idea: usare il bucket

A[i ]

per memorizzare tutte le entry

< k, v >

con

h(k) = i

gestendo opportunamente le collisioni.

La scelta della funzione hash (nelle sue 2 componenti) diventa

cruciale. In particolare:

h

deve “assomigliare” il pi`

u possibile a un processo random

(

uniform hashing

) che associa a ogni chiave in

U

un intero su

[0, N − 1]

tale che

∀k 6= k

0

∈ U

e

∀i , j ∈ [0, N − 1]

:

• Pr[h(k) = i ] = N1

• Pr[h(k) = i |h(k0) = j ] = Pr[h(k) = i ] = N1

(12)

Metodo HashCode in Java

metodo hashCode() della classe Object restituisce un int

che dipende dalla rappresentazione in memoria dell’oggetto.

Non assicura che l’hashCode di un oggetto rimanga inalterato

in diverse esecuzioni di un programma o in diverse

implementazioni di Java

non `

e un mapping “puro” da

U

a int

Il metodo hashCode pu`

o essere riscritto in vari modi a

seconda del tipo delle chiavi, restituendo sempre un int

(13)

Hash code per chiavi numeriche

Vediamo come trasformare in Java tipi numerici in int (Z ≡int):

• byte, short, char, intk →(int)k

• float (32 bit) k →Float.floatToIntBits(k)

• long (64 bit)k →(int) ((k >> 32)+(int k))

- “k >> 32”: 32 bit pi`u significativi

- “(int)k”: 32 bit meno significativi

N.B. solo“(int)k” perde l’informazione di met`a dei bit

• double (64 bit) k →(int) Double.doubleToLongBits(k)

- Double.doubleToLongBits(k): di tipo long

(14)

Hash code per stringhe di char

S ≡ s

0

s

1

. . . s

k−1

h(S ) =

k−1

X

i =0

s

i

Oss. Non `e un buon hashcode: es.,h(stop) = h(spot) = h(tops)

Polynomial hash code

h(S ) =

k−1

X

i =0

s

i

· a

k−1−i

Oss. Per parole inglesi vanno benea = 31, 33, 37, 39, 41. La classe

String in Java implementa il metodo hashCode in questo modo cona = 31

(15)

Hash code per stringhe di char

Cyclic Shift: si sommano i singoli caratteri applicando dopo

ogni addizione un cyclic shift alla somma parziale (shift di 5

posizioni va bene in pratica)

(16)
(17)

Compression Function

Division Method Dato

i

= intero prodotto dall’hash code:

i → i mod N

dove

N

= capacit`

a del Bucket Array

Osservazione. Per una migliore distribuzione degli hash code tra gli

indici del Bucket Arrayconviene scegliere N primo e distante da una

potenza di 2.

Scelte di Npoco adeguate:

- N = 2p ⇒i mod N equivale a prendere ipbit meno

significativi dii, mentre `e meglio chei mod N dipenda da

tutti i bit dii.

- N = 10p i mod N equivale a prendere lepcifre meno

significative dii in base 10. Come prima non dipende da tutta

(18)

Compression Function

Multiply-Add-Divide (MAD) Method

i → [(ai + b) mod p] mod N

dove

• p > N conpprimo

• a, b ∈ [0, p − 1]scelti a caso,a > 0

Osservazione: il metodo MAD, leggeremente

pi`

u costoso dal

punto di vista computazionale

, assicura una

migliore distribuzione

degli hash code tra gli indici del Bucket Array

.

(19)

Risoluzione delle collisioni

Collisione:

< k

1

, v

1

>

,

< k

2

, v

2

>

con

k

1

6= k

2

e

h(k

1

) = h(k

2

)

Separate Chaining: ogni bucket `

e visto come una Map pi`

u piccola

implementata tramite lista

Open Addressing: non fa ricorso a strutture ausiliarie ma

memorizza le entry direttamente nelle celle del Bucket Array. In

questo modo si risparmia spazio ma si complica la gestione delle

collisioni. Noi non studiamo questo approccio.

(20)

Implementazione dei metodi della Mappa

Si consideri l’

implementazione di una Mappa tramite una tabella

hash (A, h) con separate chaining

.

Metodo get(

k

)

if (

una entry (

k

,

x

) in

A[h(k)]

) then return

x

;

else return null;

Metodo put(

k

,

v

)

if (

una entry (

k

,

x

) in

A[h(k)]

) then

sostituisci

x

con

v

;

return

x

;

else

inserisci (

k

,

v

) in coda al bucket

A[h(k)]

;

incrementa di

1

la size della tabella;

return null;

(21)

Implementazione dei metodi della Mappa

Metodo remove(

k

)

if (

una entry (

k

,

x

) in

A[h(k)]

) then

rimuovi (

k

,

x

) da

A[h(k)]

;

decrementa di

1

la size della tabella;

return

x

;

(22)

Esempio

(23)
(24)

Load Factor

Definizione: Load Factor

Per una tabella hash con

n

entry si definisce il

load factor λ

come:

λ =

n

N

,

ovvero la lunghezza media di un bucket

Il load factor ha un impatto significativo sull’efficienza

computazionale di una tabella hash.

(25)

Complessit`

a di get, put e remove

Studieremo:

Complessit`

a al caso pessimo, in funzione del numero di entry

presenti nella tabella hash

Complessit`

a al caso medio (definito meglio dopo), in funzione

del load factor

λ

della tabella hash.

Assumeremo sempre che il calcolo della funzione hash per un dato

valore k della chiave richieda O (1) operazioni.

(26)

Complessit`

a al caso pessimo

Si consideri una tabella hash contenentenentry.

La complessit`a al caso pessimo di get, put, remove `e Θ (n), ed `e

dominata dalla ricerca della entry con chiavek, necessaria per tutti e tre

i metodi.

• O (n): banale

• Ω (n): (istanza cattiva) tutte le entry nello stesso bucket e chiavek assente.

Esercizio (R-10.9 [GTG14])

Stimare asintoticamente il numero di operazioni richiesto al caso migliore

(best-case) e al caso pessimo (worst-case) per l’inserimento dinentry in

una Mappa implementata tramite Tabella Hash con separate chaining,

inizialmente vuota. (Si assumaN > n.)

(27)
(28)

Complessit`

a al caso medio

Il seguente teorema dimostra che al caso medio le prestazioni della

tabella hash sono molto buone, e questo `e il motivo del suo successo e

del largo impiego.

Teorema

Sotto l’ipotesi di hashing uniform, in una tabella hash con separate

chaining e load factorλlacomplessit`a al caso medio di get, put,

remove `e O (1 + λ). Tale complessit`a vale per:

• qualsiasi chiavek non presente: in questo caso la media `e fatta su

tutti i possibili valori dih(k), che sono equiprobabili sotto l’ipotesi

di uniform hashing.

• chiavek presente: in questo caso la media `e fatta su tutte le

possibili chiavik presenti nella tabella che si assumono inserite una

dopo l’altra senza cancellazioni.

Osservazione. In pratica si suggerisce di mantenereλ < 0.9

(java.util.HashMap usa separate chaining conλ = 0.75come default)

(29)

Rehashing

Si esegue quandoλsopra la soglia prefissata (ad es., λ > 0.75):

1 creazione di un nuovo bucket array di capacit`aN0≥ 2N.

2 scelta di una nuova funzione hash.

3 trasferimento delle delle entry dalla vecchia alla nuova tabella hash.

Osservazioni:

• Il trasferimento dinentry da una tabella all’altra pu`o essere

implementato in tempoΘ (n)al caso pessimo (non serve ricercare una

entry prima di inserirla, si sa gi`a che le chiavi sono distinte).

• Dato che un rehash si esegue quandoλsupera una data costante, e la

capacit`a del bucket array almeno raddoppia, il rehash dinentry `e

preceduto daΩ (n)put senza rehash⇒il costo del rehash viene

ammortizzato (ovvero nascosto) da quello aggregato dei put.

• In un rehash pu`o essere necessario cercare un numero primo≥ 2N, che

(30)

PROS & CONS delle Hash Table

PROS

facile implementazione

buone prestazioni (al caso medio)

non richiede che le chiavi vengano da un universo ordinato

CONS

complessit`

a elevata al caso pessimo

alea dovuta alla bont`

a della funzione hash

spreco di spazio (per mantenere un basso load factor)

(31)

Altri usi importanti delle funzioni hash: firma digitale

Consideriamo lafirma digitaledi un documentomcheAdeve

trasmettere via rete aB.

Requisiti:

• Autenticazione: il destinatario deve poter verificare l’identit`a del mittente

• Non ripudio: al mittente non deve essere permesso di disconoscere un documento da lui firmato

• Integrit`a: deve essere possibile accertare la conformit`a del documento ricevuto con quello inviato

• Privacy: a un soggetto terzo non deve poter leggere il documento Strumenti:

• Chiavi pubbliche/private: Kpub(A), Kpriv(A), Kpub(B), Kpriv(B)

• Funzione hashhin grado di mappare un messaggiomin un

(32)

Altri usi importanti delle funzioni hash: firma digitale

(33)

Implementazione della Mappa

tramite Alberi di Ricerca

(34)

Assumiamo che le chiavi provengano da un universo ordinato

Strutture basate su alberi:

• Albero Binario di Ricerca • Multi-Way Search Tree • (2,4)-Tree

(35)
(36)

Definizione

Definizione: Albero Binario di Ricerca

UnAlbero Binario di Ricerca`e un albero binario proprio i cui nodi interni memorizzano entry con chiavi provenienti da un universo ordinato, tale

che per ogni nodo internov la cui entry ha chiavek:

• le chiavi nel sottoalbero sx div sono< k

• le chiavi nel sottoalbero dx div sono> k

(37)

Esempio (solo chiavi)

(38)

TreeSearch

SiaT un Albero Binario di Ricerca

Algoritmo TreeSearch(k, v)

Input: chiavek, nodov ∈ T

Output: nodo diTv con chiavek, o foglia in posizione ”giusta” perk

if (T.isExternal(v) OR (v.getElement().getKey()=k)) then

returnv;

if (k < v.getElement().getKey()) then

return TreeSearch(k, T.left(v)); else

return TreeSearch(k, T.right(v))

Osservazioni

• Per ricercare in tutto l’albero si parte conv = T.root().

• Correttezza: banale

(39)
(40)

Complessit`

a di TreeSearch

(41)

Complessit`

a di TreeSearch

Analizziamo l’albero della ricorsione per TreeSearch(k,T.root()):

• L’albero ha≤ h + 1 nodi, dato che ciascuna invocazione ricorsiva di

TreeSearch scende di un livello inT.

• Ogni invocazione esegue Θ (1)operazioni, oltre a un’eventuale

chiamata ricorsiva.

Esistono istanze per cui TreeSearch scende effettivamente lungo

un cammino di lunghezzaΘ (h)(quando restituisce la foglia pi`u

profonda).

⇒complessit`aΘ (h)

(42)

Implementazione dei metodi della Mappa:

get

get(

k

)

w ←

TreeSearch(

k

,

T

.root());

if

T

.isExternal(

w

) then return

null

;

else return

w

.getElement().getValue();

Complessit`

a:

Θ (h)

dominata da TreeSearch

(43)

Implementazione dei metodi della Mappa:

put

put(

k

,

x

)

w ←TreeSearch(k,T.root());

if T.isInternal(w) then

y ← w.getElement().getValue();

sostituiscix ay nella entryw.getElement();

returny

trasformaw in nodo interno contenentee = (k, v )con 2 figli foglia;

e" w" w"

incrementa numero di entry di T di1;

returnnull

Complessit`

a:

Θ (h)

dominata da TreeSearch

N.B.: In [GTG14] mancano le istruzioni di return, e per trasformarew

(44)

Esempio (solo chiavi)

9" 17" 14" 16" 21" 12" put(18,*)* 9" 17" 14" 16" 21" 12" 18" 44

(45)

Esercizio R-11.1 [GTG14]

Inserire in un albero binario di ricerca vuoto 8 entry con chiavi

30, 40, 24, 58, 48, 26, 11, 13, e far vedere l’albero risultante dopo ciascun inserimento.

(46)
(47)

Esercizio

Se nell’esercizio precedente le stesse entry fossero inserite in un ordine diverso, alla fine si otterrebbe lo stesso albero? Motivare la risposta.

(48)

Implementazione dei metodi della Mappa:

remove

remove(

k

)

w ←

TreeSearch(

k

,

T

.root());

if

T

.isExternal(

w

) then return

null

;

else

value

← w

.getElement().getValue();

decrementa numero di entry in

T

di 1;

if ((

T

.isExternal(

T

.left(

w

)) OR

(

T

.isExternal(

T

.right(

w

))) then

/*

w

interno e padre di almeno 1 foglia

*/

esegui Caso 1 (vedi lucidi successivi);

else

/*

w

interno e padre di 2 nodi interni

*/

esegui Caso 2 (vedi lucidi successivi);

return value;

(49)

Caso 1:

w

interno e padre di almeno 1 foglia

k"

w"

v"

u"

v"

u"

se

w

era radice

u

diventa radice;

(50)

Caso 2:

w

interno e padre di 2 nodi interni

k’#

k

w#

y#

u#

z#

k’#

u#

y

= predecessore “interno” di

w

nella visita inorder

k

0

predecessore di

k

nell’ordine crescente delle chiavi

(51)

Complessit`

a di remove

Θ (h)

per TreeSearch (con

h

l’altezza di

T

)

O (h)

per trovare il predecessore interno di

w

nella visita

inorder;

O (1)

per fare l’update dei nodi

(52)

Esempio

(53)
(54)

Esercizio

Scrivere una versione iterativa di TreeSearch con la stessa specifica.

(55)
(56)

Esercizio

Progettare un algoritmo (iterativo o ricorsivo) che, dato un albero binario

di ricercaT contenete entry con chiavi reali e un intervallo[A, B],

restituisca un nodow ∈ T contenente una entry con chiavek ∈ [A, B],

se esiste, altrimenti una foglia nella posizione giusta per una chiave in [A, B], e analizzarne la complessit`a.

Esercizio

Progettare un algoritmo non ricorsivo che, dato un albero binario di

ricercaT contenete entry con chiavi reali distinte, determina la pi`u

piccola chiave positiva presente inT, e analizzarne la complessit`a. Se in

T non esistono chiavi positive, l’algoritmo deve restituire ’no positive

key’.

(57)

Esercizio

SiaT un albero binario di ricerca dove ogni nodov ∈ T memorizza in

una variabilev .sizeil numero di entry inTv (inclusa quella inv).

Progettare un algoritmo ricorsivo che conti quante entry inT hanno

(58)
(59)

Esercizio

Risolvere l’esercizio del Lucido 57 modificato per contare quante entry

hanno chiave≥ k.

Esercizio

Risolvere l’esercizio del Lucido 57 usando un algoritmo iterativo.

Esercizio

Analizzare la complessit`a dell’algoritmo sviluppato per l’esercizio del

Lucido 57 assumendo che al posto della variabile v.size si abbia a

disposizione un metodoT .size(v)che restituisce il numero di entry in

Tv, con complessit`a lineare nel valore restituito. (Suggerimento:

esprimere la complessit`a come somma di due termini, uno dei quali `e il

costo aggregato di tutte le invocazioni del metodo size.)

Esercizio

Come cambia l’algoritmo sviluppato per l’esercizio del Lucido 57 se non si hanno a disposizione le variabili size?

(60)

Esercizio

SiaT un albero binario di ricerca le cui entry rappresentano studenti di

un’universit`a. Ogni studente `e associato a una entry(k, x ), dovek `e la

matricola, ex indica se lo studente `e straniero (x = 1) o italiano (x = 0).

Per ogni nodov ∈ T esiste un interov.numStr che riporta il numero di

studenti stranieri inTv (sottoalbero con radicev). Progettare un

algoritmo ricorsivo MinMatStraniero(T , v )che dato un nodov ∈ T

restituisce la pi`u piccola matricola di uno studente straniero inTv, e

analizzarne la complessit`a. Se non ci sono studenti stranieri inTv

l’algoritmo restituisce null.

(61)
(62)

Multi-Way Search Tree (MWS-Tree)

I MWS-Tree generalizzano gli Alberi Binari di Ricerca permettendo ai

nodi di contenere pi`u entry, cosa che rende pi`u agevole il bilanciamento

(variante (2,4)-Tree)

Definizione

UnMWS-Tree T `e un albero ordinato tale che

• ogni nodo interno ha≥ 2figli

• ogni nodo interno con d ≥ 2figliv1, v2, . . . , vd (d-node) soddisfa le

seguenti propriet`a:

• memorizzad − 1entry: (k1,x1),(k2,x2),...,(kd −1,xd −1) dove

k1< k2< · · · < kd −1

• per1 ≤ i ≤ d vale che la chiave di ogni entrye memorizzata

in un nodo diTvi soddisfa la relazione

ki −1< e.getKey() < ki (assumendok0= −∞ekd = +∞).

N.B.: come per gli alberi binari di ricerca, per convenzione le foglie non memorizzano entry

(63)
(64)

Esempio di MWS-Tree (solo chiavi)

(65)

Proposizione (11.2 [GTG14])

(66)
(67)
(68)

Osservazione

Se tutti i nodi interni fossero dei

d

-node l’ MWS-Tree

T

sarebbe

un albero

d

-ario. Detto

x

il numero di nodi interni e

y

il numero di

foglie di

T

sappiamo (Problema 8 della dispensa di esercizi sugli

alberi) che

y = (d − 1)x + 1

, che `

e coerente con la proposizione

precedente dato che l’albero in questo caso memorizzerebbe

n = (d − 1)x

entry.

(69)

Ricerca in un MWS-Tree

T

(In [GTG14] l’algoritmo `e descritto solo a parole)

Algoritmo MWTreeSearch(k,v)

Input: chiavek, nodov ∈ T

Output: nodo diTv contenente una entry con chiavek, se esiste, o

foglia in posizione “giusta” perk

if (T.isExternal(v)) then returnv;

Siano(k1, x1),...,(kd −1, xd −1)le entry in v, con k1< · · · < kd −1;

(k1,x1)''''''…''''(kd*1,xd*1)'' v1' v2' vd*1' vd'

Trovai tale che ki −1< k ≤ ki (si assumak0= −∞,kd= +∞);

if (k=ki) then returnv;

(70)

Esempio: MWTreeSearch(

12

,

T

.root())

(71)
(72)

Complessit`

a di MWTreeSearch

(73)
(74)

Implementazione dei metodi della Mappa:

get

get(

k

)

w ←

MWTreeSearch(

k

,

T

.root());

if (

T

.isExternal(

w

)) then return null;

else

trova

e ∈ w

tale che

e

.getKey()

= k

;

return

e

.getValue();

Complessit`

a:

`

e dominata dal quella di MWTreeSearch, ed `

e quindi

O (d

max

h)

, dove

d

max

`

e il massimo numero di figli di un nodo e

h

`

e

l’altezza dell’albero.

(75)

(2,4)-Tree

Definizione

Un

(2,4)-Tree

`

e un MWS-Tree tale che

ogni nodo interno `

e un

d

-node con

2 ≤ d ≤ 4

;

tutte le foglie hanno la stessa profondit`

a.

Osservazione: Si pu`

o definire un (2,3)-Tree con

2 ≤ d ≤ 3

per il

quale si applicano gli stessi algoritmi e le stesse complessit`

a. Il

vantaggio del (2,4)-Tree `

e che si generalizza al B-tree che `

e una

struttura dati molto usata per la realizzazione di indici in memoria

secondaria (ad es., nelle basi di dati).

(76)

Esempio di (2,4)-Tree

(77)

Altezza di un (2,4)-Tree

Proposizione 11.3 [GTG14]

Un (2,4)-Tree con

n > 0

entry ha altezza

Θ (log n)

.

Il seguente corollario `

e una conseguenza immediata della

proposizione e di quanto visto prima.

Corollario

In (2,4)-Tree con

n

entry, la complessit`

a di MWTreeSearch e del

metodo get della mappa `

e

Θ (log n)

.

(78)

Dimostrazione della proposizione

(79)
(80)

Esercizio R-11.17 [GTG14]

Disegnare due (2,4)-Tree con 15 entry le cui chiavi sono gli interi da 1 a 15. Il numero di nodi deve essere minimo in un albero e massimo nell’altro.

(81)
(82)

Implementazione dei metodi della Mappa: put

IDEA:

Se la chiave non presente inserisci la nuova entry

(k, x )

nel

nodo giusto

per

k

ad altezza 1.

Gestisci l’eventuale

overflow

(4 entry in un nodo) sfruttando

la flessibilit`

a, se pur limitata, sul numero di entry ammissibili

in un nodo.

Se necessario, propaga l’overflow verso l’alto, eventualmente

arrivando alla radice e facendo crescere di 1 l’altezza

dell’albero.

(83)

Implementazione dei metodi della Mappa: put

put(k,x)

w ←MWTreeSearch(k,T.root());

if (T.isInternal(w)) then

trovae ∈ w tale chee.getKey()= k;

y ← e.getValue();

sostituiscix a y ine;

returny;

e ←(k,x);

if (T.isRoot(w)) then

trasforma w in nodo interno contenente e con 2 figli foglia else

u ← T.parent(w);

inserisci e in u aggiungendo una foglia w0;

if (u `e un 5-node) then Split(u); /* overflow */

incrementa il numero di entry inT di1;

(84)

Descrizione grafica delle operazioni in rosso del lucido precedente:

trasforma w in nodo interno contenente e con 2 figli foglia(w radice):

e" w" w"

inserisci e in u aggiungendo una foglia w0 (w non radice):

e’# #e’’# u# e’# ##e#######e’’# u#

w# w# w’#

N.B.e0 oppure e00 potrebbe non esistere

(85)

Esempio (senza split)

put(8,x))

nuovo)) inserimento)

(86)

split(

u

)

Descritta a parole in [GTG14]

Input: 5-node

u ∈ T

, unica violazione delle propriet`

a di

(2,4)-Tree

Output: Ripristino dele propriet`

a di (2,4)-Tree

Sia

Crea

. . .

e

1#####

e

2

####

e

3

####e

4#

u#=##

u

2#

u

1#

u

3#

u

4#

u

5#

e

1#####

e

2

####

#

u’#=##

u

2#

u

1#

u

3#

e

4#

u’’#=##

u

5#

u

4# 86

(87)

split(

u

)

. . .

if (

!T

.isRoot(

u

)) then

v ← T

.parent(

u

);

/* vedi figura sotto */

inserisci

e

3

in

v

tra

e

0

ed

e

00

;

assegna

u

0

, u

00

come figli di

v

a sx e dx di

e

3

;

cancella

u

;

if (

v

`

e un 5-node) then split(

v

);

else

/* u `

e radice */

crea una nuova radice contenente

e

3

e con 2 figli

u

0

, u

00

;

cancella

u

;

"

e’""""e’’

""

"…"

"

v"=""

u

"

"

e’""""

e

3

""""e’’

"

"…"

"

v"=""

u’

"

u’’

"

(88)

Esempio

put(5,*))

split)

(89)

Esempio

put(17,*)*

split*

(90)

Complessit`

a di put

Proposizione

Per una mappa connentry implementata tramite un (2,4)-Tree la

complessit`a di put `eΘ (log n).

(91)

Esercizio (R-11.18.a [GTG14])

Inserire in un (2,4)-Tree inizialmente vuoto entry con chiavi 5, 16, 22, 45, 2, 10, 18, 30, 50, 12, 1, nell’ordine dato.

(92)
(93)
(94)

Implementazione dei metodi della Mappa: remove

IDEA:

Si rimuovono solo entry in nodi ad altezza 1.

Se la entry da rimuovere `

e in un nodo ad altezza

> 1

,

sostituiscila con una in un nodo ad altezza 1 e rimuovi quella.

Gestisci l’eventuale

underflow

(0 entry in un nodo) sfruttando

la flessibilit`

a, se pur limitata, sul numero di entry ammissibili

in un nodo.

Se necessario, propaga l’underflow verso l’alto, eventualmente

arrivando alla radice e facendo diminuire di 1 l’altezza

dell’albero.

(95)

Implementazione metodi della mappa: remove

remove(

k

)

w ←MWTreeSearch(k,T.root());

if (T.isExternal(w)) then return null;

else

trovae ∈ w tale chee.getKey() =k;

y ← e.getValue();

if (altezza(w)=1) then Delete(e,w,R);

else

siav il figlio diw a sx die;

z ←ultimo nodo interno nella visita in preorder diTv;

e0 ←entry con chiave max inz;

metti una copia die0 al posto die inw;

Delete(e0,z,R);

decrementa di1 il numero di entry inT;

(96)

Osservazione: quando il nodo

w

restituito da MWTreeSearch `

e ad

altezza

> 1

, la entry

e

0

che si sostituisce al posto di

e

in

w

`

e il

predecessore di

e

nella sequenza delle entry ordinate per chiave.

e" v" w"

e’" z"

(97)

Delete(

e

,

u

,

α

)

Descritta a parole in [GTG14]

Input: entryenel nodou ∈ T tale che il figlio a sx (α = L) o a dx

(α = R) della entry `e cancellabile

Output: rimozione die daT ripristinando le propriet`a di (2,4)-Tree

SianoA,Z i figli diu discriminati dae doveZ `e quello cancellabile;

e" u"" A"" Z"" e" u"" Z"" A"" oppure&& rimuovieeZ;

if (u non ha pi`u entry) then /* underflow */

(98)

Caso 1:

u

radice

imposta

A

come nuova radice del (2,4)-Tree;

return;

(99)

Caso 2:

u

ha un fratello

u

L

a sx che `

e un

d

-node, con

d ≥ 3

Esegui la seguente operazione:

…"""e’"""…

"

v""

A""

u

L

""

B""

…"""e’’"""e’’’

"

C"" D""

u""

…"""e’’’"…

"

v""

D""

u

L

""

B""

…"""e’’

"

C""

u""

e’

"

A""

return;

(100)

Caso 3:

u

ha un fratello

u

R

a dx che `

e un

d

-node, con

d ≥ 3

Esegui la seguente operazione:

…"""e’"""…

"

v""

A""

u""

B""

"e’’"""e’’’"…

"

C"" D""

u

R"

…"""e’’""…

"

v""

C""

u""

A""

"""e’

"

B""

u

R

""

e’’’"…

"

D""

return;

100

(101)

Caso 4:

u

ha un fratello

u

L

a sx che `

e un

2

-node

Esegui la seguente operazione:

…"""e’"""…

"

v""

A""

u

L

""

B""

"""e’’

"

C""

u""

…"""e’"""…

"

v""

A""

u

L

""

B""

"""e’’"""e’

"

C""

u""

Delete(

e

0

,

v

,

R

);

/* propagazione verso l’alto */

return;

(102)

Caso 5:

u

ha un fratello

u

R

a dx che `

e un

2

-node

Esegui la seguente operazione:

…"""e’"""…

"

v""

A""

u

R

""

B""

"""e’’

"

C""

u""

…"""e’"""…

"

v""

A""

u

R

""

B""

"""e’"""e’’

"

C""

u""

Delete(

e

0

,

v

,

L

);

return;

102

(103)
(104)
(105)
(106)
(107)

Proposizione

Per una mappa connentry implementata tramite un (2,4)-Tree la

(108)

Multimap

(109)

Definizione e metodi caratterizzanti

Definizione: unaMultimap`e una Map che ammette la presenza di> 1

entry con la stessa chiave. Questa differenza richiede una modifica della specifica dei metodi caratterizzanti.

Metodi caratterizzanti:

• get(k): restituisce una collezione (eventualmente vuota) con tutti i

valori associati alle entry con chiave k

• put(k,v): inseriscesempreuna nuova entry(k, v )senza intaccare

altre entry con chiavek gi`a presenti. Non restituisce alcun output.

• remove(k,v): rimuove una entry con chiavek e valorev, se tale

entry esiste. Restituisce un boolean: yes se si `e rimossa la entry e

(110)

Implementazione

Una Multimap pu`o essere implementata tramiteuna Mappa in cui le

entry sono costituite da coppie (k, Lk), dove k `e una chiave, e Lk una

lista, non vuota, di valori associati alla chiave.

SeLk = {v1, v2, . . . , v`}, allora(k, Lk)rappresenta, in modo compatto, le

`entry(k, v1), (k, v2), . . . , (k, v`).

Implementazione dei metodi:

• get(k): se esiste una entry(k, Lk)restituisceLk, altrimenti

restituisce una collezione vuota.

• put(k, v ): se esiste una entry(k, Lk)si aggiunge semplicemente il

valore v aLk, altrimenti si aggiunge la entry (k, Lk = {v })alla

struttura.

• remove(k, v ): se esiste una entry(k, Lk)eLk contiene solo il valore

v, si rimuove la entry(k, Lk)dalla mappa, altrimenti si rimuove

(un’occorrenza di)v daLk.

(111)
(112)
(113)
(114)

Riepilogo complessit`

a per la Mappa

Si consideri unaMappa con n entry:

Metodo Tabella Hash ABR (2,4)-Tree

get(k) Θ (1 + λ) Θ (h) Θ (log n)

put(k, v) Θ (1 + λ) Θ (h) Θ (log n)

remove(k) Θ (1 + λ) Θ (h) Θ (log n)

N.B.:

• Per l’ABR, h`el’altezza dell’albero chepu`o assumere valori

compresi tra Θ (log n) e Θ (n).

• Le complessit`a per la Tabella Hash sono al caso medio eλ`e ilload

factor.

(115)

Riepilogo complessit`

a per la Multimap

Si consideri unaMultimap con n entry:

Metodo Tabella Hash ABR (2,4)-Tree

get(k) Θ (1 + λ) Θ (h) Θ (log n)

put(k, v) Θ (1 + λ) Θ (h) Θ (log n)

remove(k, v) Θ (s + 1 + λ) Θ (s + h) Θ (s + log n)

N.B.:

• Per l’ABR, h`el’altezza dell’albero chepu`o assumere valori

compresi tra Θ (log n) e Θ (n).

• Il termines nelle complessit`a di remove indica il massimo numero di

entry con la stessa chiave.

• Nelle complessit`a per la Tabella Hash, il termine1 + λ(doveλload

factor) si riferisce al tempo medio di ricerca della chiave, mentre, nel

(116)

Esercizio

Progettare e analizzare un algoritmo iterativo efficiente che determini l’altezza di un (2,4)-Tree.

(117)
(118)

Esercizio

SiaT un (2,4)-Tree dove ogni nodov ∈ T memorizza in una variabile

v .sizeil numero di entry inTv (incluse quelle inv). Progettare un

algoritmo ricorsivo che conti quante entry inT hanno chiave≤ k, e

analizzarne la complessit`a.

(119)
(120)

Esercizio

Risolvere l’esercizio precedente tramite un algoritmo iterativo.

Esercizio

Analizzare l’algoritmo 24CountLE assumendo che al posto della variabile v .sizesi abbia a disposizione un metodoT .size(v)che restituisce il

numero di entry inTv, con complessit`a lineare nel valore restituito.

(121)

Esercizio

SianoT eU due (2,4)-Tree di altezzahe tali che la massima chiave in

T `e minore della minima chiave inU.

1 Progettare un algoritmo di complessit`a O (h)per fondereT eU in

un unico (2,4)-TreeTU.

(122)
(123)
(124)

Esercizio

SianoT eU due (2,4)-Tree contenenti rispettivamentenedmentry e

tali che la massima chiave inT `e minore della minima chiave inU.

Progettare un algoritmo di complessit`aO (log n + log m)per fondereT e

U in un unico (2,4)-TreeTU.

Suggerimento: Se i due alberi hanno altezze diverse, fondere l’albero di altezza minore con un opportuno sottoalbero dell’altro di uguale altezza (utilizzando l’algoritmo sviluppato per l’esercizio del Lucido 121), e sostituirlo a tale sottoalbero.

Esercizio

Analizzare la complessit`a dell’algoritmo sviluppato per l’esercizio del

Lucido 7, scegliendo una opportuna implementazione per la Mappa.

(125)

Riepilogo

Mappa: definizione come ADT

Tabelle Hash:

• Ingredienti principali

• Funzione hash: hash code e compression function

• Risoluzione delle collisioni tramite chaining

Implementazione dei metodi della Mappa e loro complessit`a al

caso medio sotto l’ipotesi di uniform hashing

• Load factor e rehashing

Alberi Binari di Ricerca

• Definizione

• Metodo TreeSearch

(126)

Riepilogo

(2,4)-Tree

Definizione di Multi-Way Search (MWS) Tree

• Relazione tra numero di entry e foglie in un MWS-Tree

• Metodo MWTreeSearch

• Definizione di (2,4)-Tree

• Altezza di un (2,4)-Tree

• Implementazione dei metodi della Mappa

Implementazione di una Multimap

Riferimenti

Documenti correlati

Our case is curiously unique, in which we report a single artery, originating from the right coronary artery (RCA) with double drainage sites – one to the left pulmonary artery and

• void setup_timer( struct timer_list *timer, void (*function)(unsigned long), unsigned long data );. • int mod_timer( struct timer_list *timer, unsigned long

• void setup_timer( struct timer_list *timer, void (*function)(unsigned long), unsigned long data );. • int mod_timer( struct timer_list *timer, unsigned long

VII Malattie dell’occhio e degli annessi oculari (H00-H59) VIII Malattie dell’orecchio e dell’apofisi mastoide (H60-H95) IX Malattie del sistema circolatorio (I00-I99) X Malattie

La mappa che hai completato può esserti utile per analizzare le preposizioni. Completa la tabella scegliendo una delle opzioni, come nell’esempio.. PREPOSIZIONE SEMPLICE

Very recently, the existence of such waves with one critical layer as solutions of the full Euler equations with exact nonlinear boundary conditions was established [25],

The Commission rejected the com­ plaint, but its reasoning in this case illustrates the principle that a dominant company, which sells both the raw material and the

– la mappa di una città mette in evidenza le strade, le piazze, i parchi e i giardini, gli edifici più importanti. Vai al blog CIAO