Relazione ASD Iafrate Arturo - Università degli Studi di Napoli

Download Report

Transcript Relazione ASD Iafrate Arturo - Università degli Studi di Napoli

Università degli studi di Napoli
“Parthenope”
Facoltà di Scienze e Tecnologie
Corso di laurea in Informatica
A.A. 2012/2013
Laboratorio di Algoritmi e Strutture Dati
Docente: F. Camastra
* Problema della catena di montaggio *
* Costruzione di una coda di max-priorità utilizzando un
albero red-black *
Relazione a cura di:
Arturo Iafrate
0124/343
Contents
1 Analisi della traccia
4
1.1
Catena di montaggio . . . . . . . . . . . . . . . . . . . . . . . . .
4
1.2
Coda di max priorità . . . . . . . . . . . . . . . . . . . . . . . . .
4
2 Il problema della Catena di Montaggio: Cenni teorici
6
2.1
Caratterizzazione della struttura di una soluzione ottima . . . . .
7
2.2
Denizione ricorsiva del valore di una soluzione ottima . . . . . .
7
2.3
Calcolo del tempo minimo . . . . . . . . . . . . . . . . . . . . . .
8
2.4
Calcolo del percorso più rapido
9
. . . . . . . . . . . . . . . . . . .
3 Il problema della catena di montaggio: implementazione
3.1
3.2
10
Diagramma delle classi . . . . . . . . . . . . . . . . . . . . . . . .
11
3.1.1
Classe Station
12
3.1.2
Classe AssemblyLine . . . . . . . . . . . . . . . . . . . . .
13
3.1.3
Classe Factory
14
3.1.4
Classe MyFactory
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
15
. . . . . . . . . . . . . . . . . . . . . . . . . .
16
3.2.1
Note per la compilazione e l'esecuzione . . . . . . . . . . .
16
3.2.2
Test 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
3.2.3
Test 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
3.2.4
Test 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
Test di esecuzione
4 Coda di max priorità: Cenni teorici
21
4.1
Alberi binari di ricerca . . . . . . . . . . . . . . . . . . . . . . . .
21
4.2
Alberi Red-Black . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
4.2.1
Proprietà
22
4.2.2
Inserimento di un elemento
. . . . . . . . . . . . . . . . .
23
4.2.3
Eliminazione di un elemento . . . . . . . . . . . . . . . . .
25
. . . . . . . . . . . . . . . . . . . . . . . . . . .
5 Coda di max priorità: implementazione
5.1
5.2
27
Diagramma delle classi . . . . . . . . . . . . . . . . . . . . . . . .
28
5.1.1
Classe Color
. . . . . . . . . . . . . . . . . . . . . . . . .
29
5.1.2
Classe Node . . . . . . . . . . . . . . . . . . . . . . . . . .
29
5.1.3
Classe BST . . . . . . . . . . . . . . . . . . . . . . . . . .
30
5.1.4
Classe RedBlackTree . . . . . . . . . . . . . . . . . . . . .
32
5.1.5
Classe MaxPriorityQueue
33
Test di esecuzione
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
34
5.2.1
Note per la compilazione e l'esecuzione . . . . . . . . . . .
34
5.2.2
Test 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
5.2.3
Test 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
5.2.4
Test 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
5.2.5
Test 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
6 Risorse utilizzate
40
1
A Codice catena di montaggio
42
A.1
Station.h
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.2
Station-methods.cpp . . . . . . . . . . . . . . . . . . . . . . . . .
43
A.3
AssemblyLine.h . . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
A.4
AssemblyLine-methods.cpp
45
A.5
Factory.h
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
A.6
MyFactory.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
A.7
MyFactory-methods.cpp . . . . . . . . . . . . . . . . . . . . . . .
47
A.8
Main.cpp
48
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B Codice coda max priorità
42
50
B.1
Color.h
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
B.2
Color-methods.cpp . . . . . . . . . . . . . . . . . . . . . . . . . .
51
B.3
Node.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
B.4
Node-methods.cpp
. . . . . . . . . . . . . . . . . . . . . . . . . .
53
B.5
Bst.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
B.6
Bst-methods.cpp
. . . . . . . . . . . . . . . . . . . . . . . . . . .
55
B.7
RedBlackTree.h . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
B.8
RedBlackTree-methods.cpp
63
B.9
MaxPriorityQueue.h
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
69
B.10 MaxPriorityQueue-methods.cpp . . . . . . . . . . . . . . . . . . .
70
B.11 Main.cpp
71
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
3
1
Analisi della traccia
Date le tracce, si è scelto di implementare la numero 5:
(a) La Fiat per la produzione della Nuova Panda ha installato nello stabilimento di Pomigliano d' Arco
di montaggio ha
L
lavorazione dierente
I
iniziale
K
catene di montaggio, con
K > 1.
Ogni catena
stazioni di lavoro. Ogni stazione di lavoro ha un tempo di
T.
Inoltre il telaio della Nuova Panda impiega un tempo
per entrare nella catena di montaggio ed un tempo
U
per uscire,
tempi dierenti per ogni catena di montaggio. Inne, per fornire all'impianto
la massima essibilità si preveda la possibilità che la Nuova Panda possa migrare da una catena di montaggio ad un'altra e tale operazione impieghi un
tempo, dierente per ogni catena, pari a
S.
Si implementi, un programma,
utilizzando la programmazione dinamica, che individui per ogni vettura il percorso più rapido. Si verichi la correttezza dell'implementazione su una serie di
congurazioni possibili dell'impianto.
(b) Si costruisca, utilizzando, un albero Red-Black una coda di max priorità. Si ricorda che l'interfaccia pubblica della coda di priorità deve contenere i
seguenti metodi (extract-max, insert, maximum, increase-key) più gli eventuali
costruttori e distruttore.
Prendiamole in esame singolarmente.
1.1 Catena di montaggio
Al ne di produrre nel minor tempo possibile il telaio della Nuova Panda, è
necessario trovare il percorso più veloce che tenga conto dei vari tempi di ingresso
I
nelle
K
catene, dei tempi di uscita
U
dalle catene, dei tempi di lavorazione
delle stazioni che compongono le catene, e gli eventuali tempi di trasferimento
T
S
X appartenente ad una determinata catena, alla
X + 1 di una seconda catena. Inoltre, c'è da considerare che i tempi di
trasferimento S da una stazione X alla stazione X + 1, entrambe appartenenti
nel passaggio da una stazione
stazione
alla medesima catena, sono trascurabili.
Al ne di risolvere tale quesito, è
espressamente chiesto di adottare un approccio alla programmazione dinamica:
è infatti impensabile calcolare ogni possibile soluzione e scegliere quella con
valore minimo, in quanto sono presenti
esse vi sono
L
K
catene di montaggio e in ciascuna di
stazioni di lavoro, avendo quindi
K L possibili
soluzioni.
Ciò che si è cercato di fare, e che verrà esposto successivamente, è stato
implementare mediante il linguaggio
C + + tale problema,
e risolverlo mediante
l'utilizzo della Programmazione Dinamica.
1.2 Coda di max priorità
Una coda di priorità è un insieme di
che ne rappresentano la priorità.
n elementi a cui sono associate delle chiavi,
Nella fattispecie, una coda di max priorità
supporta le operazioni di:
•
Insert(A,x) inserisce un elemento
x
4
nell'insieme
A
•
•
Maximum(A) restituisce l'elemento di
Extract-Max(A) restituisce l'elemento di
ina da
•
A
con chiave massima
A
con chiave massima e lo elim-
A
Increase-Key(A,x,k) incrementa il valore della chiave dell'elemento x dell'insieme
A
ad un valore
k
Ad un primo impatto, tale implementazione può sembrare banale, ma tale coda
dev'essere implementata mediante l'utilizzo di un albero Red-Black, una struttura dati con una logica di gestione relativamente complessa, ma che ore ottime
prestazioni anche nel caso peggiore. A sua volta però, un albero Red-Black è
un'ottimizzazione di un Albero Binario di Ricerca. Quindi ciò che si è dovuto
fare al ne di poter implementare la coda di max priorità, è stato partire dalle
radici, ovvero implementare la struttura dell'Albero Binario di Ricerca, su di
esso costruire un albero Red-Black, e solo inne implementare la coda, il tutto
ovviamente in linguaggio
C + +.
5
2
Il problema della Catena di Montaggio: Cenni
teorici
La programmazione dinamica è una tecnica che, come il Divide-et-Impera, si
basa sulla suddivisione del problema in sottoproblemi. A dierenza del Divideet-Impera, la programmazione dinamica risulta essere eciente quando i sottoproblemi sono dipendenti tra di essi. Eventuali sottoproblemi comuni quindi
vengono risolti una sola volta: la soluzione viene quindi salvata in una tabella,
evitando di ricalcolare la soluzione ogni qual volta si presenti lo stesso sottoproblema.
Tale tecnica, viene adottata per risolvere i problemi di ottimizzazione,
ciascuno dei quali ammette solitamente più soluzioni ottime.
Un algoritmo che adotta questo approccio, prevede quattro fasi di sviluppo:
•
caratterizzazione della struttura di una soluzione ottima
•
denizione ricorsiva del valore di una soluzione ottima
•
calcolo del valore di una soluzione ottima secondo uno schema bottom-up
•
costruzione di una soluzione ottima a partire dalle informazioni calcolate
nel punto precedente.
Analizziamo quindi, il problema della catena di montaggio, introducendo un po'
di notazioni:
•
lo stabilimento presenta
•
ogni catena
Ki
ha un dierente tempo di ingresso e
•
ogni catena
Ki
ha un dierente tempo di uscita x
•
ogni catena
Ki
contiene
tempo di lavorazione
•
K
T
4
L
catene di montaggio, con
•
Li,j
Si,j
è possibile trasferire il telaio dalla stazione
la catena
Ki
1
2
3 stazioni di lavoro, ciascuna delle quali con
pagando un tempo di trasferimento pari a
•
K > 1.
alla stazione
può scambiare il telaio con tutte le rimanenti
il tempo di trasferimento dalla stazione
Li,j
alla stazione
Ln(n!=i),j+1
Ki−1
Li,j+1
catene
è trascur-
abile
Andiamo ora ad analizzare, le quattro fasi di sviluppo della Programmazione
Dinamica relative al problema della Catena di Montaggio.
1 Indicheremo
2 Indicheremo
3 Indicheremo
4 Indicheremo
con
con
con
con
ei il tempo di ingresso alla catena Ki
xi il tempo di uscita dalla catena Ki
Li,j la j − sima stazione della i − sima catena
Ti,j il tempo di lavorazione della stazione Li,j
6
2.1 Caratterizzazione della struttura di una soluzione ottima
Si vuole dimostrare che il problema della Catena di Montaggio possiede una
struttura ottima, ovvero che la soluzione ottima al problema, contiene al suo
interno le soluzioni ottime dei sottoproblemi.
Consideriamo il percorso più veloce possibile che il telaio può seguire, par-
L1,j .
tendo dal punto iniziale, alla stazione
•
se
j = 1,
Si evince, che i casi possibili sono:
c'è solo un percorso che il telaio può seguire, quindi è facile
determinare quanto tempo impiega per arrivare alla stazione
•
se
j > 1 ∪ j = 2, 3, ..., L,
allora ci sono due possibili scelte:
il telaio può provenire dalla stazione
ed entrare direttamente in
mento
S
L1,j .
L1,j ,
L1,j−1 (ovvero dalla stessa catena)
avendo cosi un tempo di trasferi-
trascurabile
il telaio può provenire dalla stazione
ed entrare in
L1,j
Li,j−1 (ovvero da un'altra catena)
pagando con un tempo di trasferimento pari a
Si,j−1
Analizzando questa struttura, possiamo aermare che si tratta quindi di una
struttura ottima. In pratica, so per certo che le scelte fatte dal punto iniziale no
ad una certa stazione sono state ottime, quindi se costruisco l'intero percorso
seguendo questa logica, so per certo che il percorso nale rappresenterà una
soluzione ottima del problema.
2.2 Denizione ricorsiva del valore di una soluzione ottima
Questa fase consiste nel denire il valore di una soluzione ottima ricorsivamente,
in funzione delle soluzioni ottime dei sottoproblemi.
Deniamo come sottoproblema il trovare il percorso più rapido no alla
stazione
j
in tutte le
alla stazione
L
K
catene di montaggio. Il telaio quindi, deve arrivare no
di una catena e poi uscire dallo stabilimento.
Indichiamo con:
• fi [j]
il minor tempo possibile che impiega un telaio dal punto iniziale no
alla stazione
• f ∗ il
Li,j
minor tempo possibile che impiega un telaio per attraversare l'intero
stabilimento
Abbiamo quindi:
(
1.
f1 [j] =
(
2.
f2 [j] =
e1 + T1,1 j = 1
min(...) j > 1
e2 + T2,1 j = 1
min( ...) j > 1
7
(
3.
fK [j] =
4.
f∗ = min(...)
eK + TK,1 j = 1
min( ... ) j > 1
2.3 Calcolo del tempo minimo
A questo punto occorre scrivere un algoritmo ricorsivo per calcolare il percorso
più rapido che attraversa lo stabilimento, basandosi sui risultati ottenuti nella
fase precedente. L' algoritmo presentato sul libro di testo
5 considera soltanto
due catene di montaggio; per questo motivo, per poter funzionare su
di montaggio, l'algoritmo è stato adattato.
Algorithm 1 Fastest-Way
5 Robert
Sedgewick, Algoritmi in C + +, Addison Wesley
8
K
catene
2.4 Calcolo del percorso più rapido
L'ultima fase consiste nel costruire la sequenza delle stazioni utilizzate nel percorso più rapido che attraversa lo stabilimento.
Algorithm 2 Print-Stations
9
3
Il problema della catena di montaggio: implementazione
L'implementazione è stata eettuata in linguaggio
C + +.
Essendo questo un
linguaggio Object Oriented, il primo passo è stato denire le classi e quelle che
sono le interfacce pubbliche e private ad esse inerenti. Inoltre è stato ritenuto opportuno, al ne di semplicare il codice e renderlo quindi più leggibile, l'utilizzo
della Standard Template Library, ovvero una libreria software inclusa nel linguaggio stesso, la quale denisce strutture dati, algoritmi e iteratori generici. In
particolare, tra le strutture dati adottate, è stato fatto un assiduo utilizzo di:
•
map: un array associativo ordinato rispetto alla chiave; consente la mappatura di un dato (chiave) associato ad un altro (valore).
Entrambi i
tipi di dato possono essere deniti dall'utente. Permette ricerche rapide
rispetto alla chiave e l'accesso ai dati in tempo
di assegnare più chiavi ad un singolo valore.
•
6
O(log(n)).
Non consente
vector: un array dinamico con la capacità di ridimensionarsi automaticamente a causa dell'inserimento o della cancellazione di elementi. Gli elementi vengono memorizzati su una porzione di memoria continua. L'inserimento
e la rimorzione degli elementi nel/dal vector in coda viene eettuato in un
tempo costante
O(1).
L'inserimento e la rimorzione all'inizio o nel centro
e la ricerca vengono eettuate in tempo lineare
•
O(n).7
iterator: un oggetto che consente di visitare tutti gli elementi contenuti in
un altro oggetto, tipicamente un contenitore, senza doversi preoccupare
dei dettagli di una specica implementazione.
Inoltre, essendo il
C ++
8
un linguaggio Object Oriented, si è pensato sfruttare,
oltre all'incapsulamento, l'astrazione, l'ereditarietà e il polimorsmo.
L'incapsulamento è stato adottato fornendo ad ogni classe, un'interfaccia
pubblica ed una privata. Nella maggior parte dei casi, in quella privata sono
stati inseriti gli attributi, e in quella pubblica i metodi.
L'astrazione è stata adottata implementando alcuni metodi virtual, e rendendo difatto cosi, la classe astratta.
L'ereditarietà è stata sfruttata mediante l'opportunità che il linguaggio ore
di poter dichiarare una classe che estende una seconda classe. Così facendo, si
viene a creare una gerarchia di classi, dove la classe che eredita viene chiamata
glia, e quella che viene estesa classe madre.
Il polimorsmo, ovvero la possibilità di un metodo di assumere più forme,
in questo caso è una diretta conseguenza dell'ereditarietà e dell'astrazione. E'
stato necessario infatti re-implementare alcuni metodi dichiarati nella classe
base anchè il loro comportamento cambi nella classe glia.
Vediamo ora nello specico le classi implementate, servendoci dell'UML.
6 Fonte:
7 Fonte:
8 Fonte:
Wikipedia, the free encyclopedia
Wikipedia, the free encyclopedia
Wikipedia, the free encyclopedia
10
3.1 Diagramma delle classi
Prima di mostrare il diagramma delle classi, un po' di chiarimenti sul simbolismo
adottato:
•
-: attributo/metodo privato
•
#: attributo/metodo protetto
•
+: attributo/metodo pubblico
•
linea con rombo: operatore di aggregazione (è parte di)
•
linea con freccia: operatore di ereditarietà (è un)
Figure 1: Catena di montaggio: UML
Come è possibile vedere dall'UML, sono state implementate quattro classi,
ciascuna delle quali strettamente collegata ad un'altra. Vediamole nello specico.
11
3.1.1
Classe Station
La classe Station è stata la prima classe implementata. Siccome ogni catena di
montaggio che compone lo stabilimento, è a sua volta composta da un numero
di stazioni denite in input dall'utente, si è pensato di partire proprio da questa.
Figure 2: Classe Station
Come è possibile notare dalla gura, la suddetta classe contiene nell'interfaccia
privata due attributi:
•
workingTime di tipo int, il quale conterrà il tempo di lavorazione sulla
stazione di lavoro
•
trasferTime di tipo map<int, int>, il quale conterrà il costo di tempo di
trasferimento ad una catena. In particolare:
nel primo campo (chiave), l'indice della catena
nel secondo campo (valore), il costo in termini di tempo di trasferimento alla catena identicata nel primo campo
Nell'interfaccia pubblica invece, sono presenti i metodi per la gestione della
stazione:
•
PrintStation(int) permette di stampare i dati relativi alla stazione
•
GetWorkingTime() ritorna il tempo di lavoro della stazione
•
GetTransferTime(int) ritorna il tempo di trasferimento alla catena passata
in input
12
3.1.2
Classe AssemblyLine
Dopo aver implementato la classe Station, è stata impelementata la classe As-
semblyLine che, come il nome stesso suggerisce, è la classe le cui istanze comporranno lo stabilimento.
Figure 3: Classe AssemblyLine
Come mostrato nell'immagine, la classe presenta nell'interfaccia privata tre
attributi:
•
entryTime di tipo int, il quale rappresenta il tempo di ingresso nella catena
di montaggio
•
exitTime di tipo int, il quale rappresenta il tempo di uscita dalla catena
di montaggio
•
stations di tipo vector<Station>, il quale rappresenta le stazioni che compongono la catena. In particolare, è possibile vedere dalla Figure 1, che la
classe AssemblyLine fa parte di un'aggregazione: è composta da
L oggetti
di tipo Station.
Inoltre, nell'interfaccia pubblica, presenta cinque metodi:
•
GetEntryTime() il quale restituisce il tempo di ingresso alla catena
•
GetExitTime() il quale restituisce il tempo di uscita dalla catena
•
GetStationWorkingTime(int) il quale restituisce il tempo di lavoro della
stazione interna alla catena
•
GetStationTransferTime(int,int) il quale restituisce il tempo di trasferimento di una stazione ad una catena
•
PrintLine() il quale permette di stampare le informazioni relative alla
catena
13
3.1.3
Classe Factory
Una volta aver implementato le classi Station e AssemblyLine, è nata la necessità
di implementare una classe che fosse stata in grado di aggregare le varie catene
di montaggio e compiere operazioni su di esse. E' stata cosi implementata la
classe Factory, che rappresenta lo stabilimento.
Figure 4: Classe Factory
Come è possibile intuire dall'immagine, questa non è la classe che implementerà l'algoritmo di programmazione dinamica richiesto dalla traccia.
Si
tratta bensì di una classe, facente parte anch'essa di un'aggregazione (si veda
Figure 1 ), il cui scopo è fornire un'interfaccia alla classe che la estenderà. Non
presenta interfaccia privata, bensì ne presenta una protetta, nella quale è presente un attributo:
•
lines di tipo vector<AssemblyLine>, il quale rappresenta le catene che
compongono lo stabilimento
Nell'interfaccia pubblica, è possibile invece trovare due metodi:
•
AddLine() metodo
virtuale che verrà implementato nella classe che ered-
iterà da Factory
•
PrintFactory() anch'esso
virtuale, il quale verrà implementato nella classe
che erediterà da Factory
14
3.1.4
Classe MyFactory
Si tratta della classe fulcro del progetto: contiene il metodo che implementa
l'algoritmo di programmazione dinamica sopracitato.
Figure 5: Classe MyFactory
La classe estende la classe Factory, ereditandone così gli attributi e metodi
protetti e pubblici. Presenta un'interfaccia pubblica ed una privata. Nell'interfaccia
privata abbiamo:
•
f di tipo vector<vector<int> > (matrice), che conterrà i percorsi più brevi
per arrivare alle stazioni
•
way di tipo vector<vector<int> > (matrice), che ci servirà per ricomporre
il percorso migliore
•
nStations di tipo int, che conterrà il numero di stazioni in ogni catena
•
nLines di tipo int, che conterrà il numero di catene che compone lo stabilimento
•
fastTime di tipo int, che conterrà il tempo migliore in uscita
•
exitFrom di tipo int, che conterrà l'indice della catena dalla quale uscire
Nell'interfaccia pubblica abbiamo invece:
•
AddLine(...) il quale permette di aggiungere allo stabilimento una catena
di montaggio
•
PrintFactory() che permette di stampare a video la struttura dello stabilimento
•
FastestWay() il quale implementa l'algoritmo omonimo
•
BestWay() il quale permette di stampare a video il percorso migliore
15
3.2 Test di esecuzione
Al ne di dimostrare la bontà del codice implementato, si riportano di seguito,
alcuni test di esecuzione del software prodotto, su una serie di congurazioni
possibili.
3.2.1
Note per la compilazione e l'esecuzione
Il codice sorgente allegato alla relazione, è stato compilato, eseguito e testato in
ambiente Linux x64, e nello specico su ElementaryOS (Ubuntu based). Al ne
di poter compilare correttamente il codice, spostarsi nella cartella CatenaDi-
Montaggio . Saranno presenti:
•
Station.h, contenente la classe Station
•
Station-methods.cpp, contenente l'implementazione dei metodi della classe
Station
•
AssemblyLine.h, contenente la classe AssemblyLine
•
AssemblyLine-methods.cpp, contenente l'implementazione dei metodi della
classe AssemblyLine
•
Factory.h, contenente la classe Factory
•
MyFactory.h, contenente la classe MyFactory
•
MyFactory-methods.cpp, contenente l'implementazione dei metodi della
classe MyFactory
•
main.cpp, contenente il main del programma
Per compilare, in ambiente Linux utilizzare:
g++
−o
AssemblyLine
Factory . h
AssemblyLine . h
MyFactory−methods . cpp
A s s e m b l y L i n e −methods . cpp
MyFactory . h
Station . h
−Wall − p e d a n t i c
Per eseguire, in ambiente Linux utilizzare:
. / AssemblyLine
3.2.2
Test 1
In questo primo test, verrà mostrato il comportamento del programma nel caso
in cui l'utente inserisca un numero di catene di montaggio o di stazioni non
idoneo.
16
main . cpp
S t a t i o n −methods . cpp
Figure 6: Catena di montaggio, test 1
Come è possibile notare dall'immagine, il programma non accetta come input
un numero di catene inferiore a due e un numero di stazioni inferiori ad uno.
17
3.2.3
Test 2
In questo test, viene mostrato l'output relativo all'esecuzione dell'algoritmo su
due catene di montaggio, ciascuna delle quali con tre stazioni.
Figure 7: Catena di montaggio, test 2
Vengono indicati:
•
Line j =
j − sima
•
ET = tempo di ingresso alla
•
XT = tempo di uscita dalla
•
WT[i] = tempo di lavorazione nella
•
TT[k] = tempo di trasferimento dalla
catena di montaggio
catena. Si noti che se
j = k,
j − sima
j − sima
catena
catena
i − sima
stazione
i − sima
stazione alla
k − sima
TT[k]=0 in quanto il tempo di trasferimento
tra stazioni giacenti sulla stessa catena risulta essere trascurabile
Viene poi mostrato il percorso migliore, il quale dev'essere letto dal basso verso
l'alto. In questo caso, il percorso migliore è situato tutto sulla catena 0.
18
3.2.4
Test 3
In questo test invece, viene mostrato l'output relativo all'esecuzione dell'algoritmo
su 3 catene di montaggio, ciascuna delle quali con 4 stazioni.
Figure 8: Catena di montaggio, test 3a
N.B: Per problemi di spazio, le immagini si trovano su pagine dierenti,
ma fanno riferimento allo stesso test.
19
Figure 9: Catena di montaggio, test 3b
Com'è possibile vedere dalle immagini, stavolta il percorso migliore attraversa
le prime tre stazioni nella catena 0, viene poi eettuato un trasferimento alla
catena 2 nella quale il telaio viene lavorato dalla quarta stazione, ed inne esce
dallo stabilimento.
20
4
Coda di max priorità: Cenni teorici
Cosi come descritto nel capitolo 1, paragrafo 2 della stessa relazione, una coda
di max priorità è un insieme di
n
elementi a cui sono associate delle chiavi, che
ne rappresentano la priorità, e sono denite le funzioni di:
•
Insert(A,x) inserisce un elemento
•
Maximum(A) restituisce l'elemento di
•
x
nell'insieme
A
Extract-Max(A) restituisce l'elemento di
ina da
•
A
con chiave massima
A
con chiave massima e lo elim-
A
Increase-Key(A,x,k) incrementa il valore della chiave dell'elemento x dell'insieme
A
ad un valore
k
La coda di max priorità però essendo una struttura astratta, sarà soltanto
l'applicazione che sfrutterà in background una struttura dati più complessa,
ovvero un albero Red-Black. A sua volta l'albero Red-Black è un'ottimizzazione
di un Binary Search Tree, altra struttura dati meno complessa. Quindi, al ne
di spiegare esaustivamente il funzionamento della coda di max priorità, è bene
introdurre brevemente anche gli alberi binari di ricerca e gli alberi Red-Black.
4.1 Alberi binari di ricerca
Un albero binario di ricerca (ABR oppure BST ) è un particolare albero binario,
ovvero un albero in cui ogni nodo ha al più due gli, su cui è denito un particolare ordinamento: per ogni nodo
sinistro di
di
n
n
n
dell'albero si ha che la chiave del glio
è strettamente minore della chiave di
è strettamente maggiore della chiave di
n.
n,
e la chiave del glio destro
Ovviamente, si presuppone che
non ci possano essere due nodi con la stessa chiave. Le operazioni più comuni
su un ABR contenente
n
elementi sono:
1. Visita ordinata (Inorder), la quale viene eettuata con un algoritmo ricorsivo che, sfruttando le proprietà dell'ABR, visita prima il sottoalbero
sinistro, poi la radice ed inne il sottoalbero destro. Poichè vengono visitati tutti i nodi una sola volta, la complessità è pari a
O(n).
2. Ricerca di un elemento, la quale anche in questo caso avviene mediante un
algoritmo ricorsivo che sfrutta le proprietà dell'ABR. La ricerca è svolta
confrontando il valore da ricercare con la radice; qualora tali valori non
coincidano, ci si sposta sul sottoalbero sinistro o destro, a seconda del fatto
che l'elemento da ricercare sia rispettivamente più piccolo o più grande
della radice. Ad ogni passo, tale algoritmo, scende di un livello l'albero,
quindi la complessità dell'algoritmo sarà
O(h),
dove
h
è la profondità
9
dell'albero.
9 La
radice r ha profondità 0, i gli destro e sinistro hanno profondità 1, e cosi via. Quindi
se un nodo ha profondità p, i suoi gli non vuoti hanno profondità p + 1
21
3. Inserimento di un elemento, eettuato in modo tale da preservare le proprietà degli ABR. L'algoritmo, partendo dalla radice, confronta la chiave
del nodo da inserire con il nodo preso in esame. Ci si sposta poi verso il
sottoalbero sinistro o verso il sottoalbero destro. Questo avviene ntanto
che non si esce dall'albero. L'ultimo nodo preso in esame viene poi confrontato con quello da inserire, il quale diverrà glio sinistro o destro di
tale nodo. Anche in questo caso la complessità sarà
O(h).
4. Eliminazione di un elemento, che distingue tre casi, e anche in questa
operazione la complessità sarà pari a
O(h):
(a) Se il nodo da eliminare è senza gli, basta cancellarlo dall'albero
(b) Se il nodo da eliminare ha un solo glio, si elimina sostituendolo nella
struttura dell'albero con il suo unico glio
(c) Se il nodo da eliminare ha entrambi i gli, si cerca il suo successore, e
si scambiano i valori del nodo da cancellare con quelli del successore
trovato, cancellando poi quest'ultimo (il quale avrà al più un glio).
h = log(n),
O(h), avranno come costo reale O(log(n)).
Nel caso in cui l'albero sia bilanciato, l'altezza dell'albero è pari a
quindi, le operazioni che hanno costo
Purtroppo però, non è possibile garantire che gli ABR siano bilanciati. Motivo
per il quale, si è cercato di trovare un modo per bilanciare automaticamente
l'albero dopo aver eettuato operazioni che ne modicano la struttura, ovvero
inserimento ed eliminazione di un nodo: nascono così gli
alberi Red-Black.
4.2 Alberi Red-Black
Un albero Red-Black (RBT ) è un particolare ABR bilanciato.
Questa par-
ticolare struttura dati fu inventata nel 1972 da Rudolf Bayer, che la chiamò
B-alberi binari simmetrici,
e fu ribattezzata con l'attuale nome da Robert
Sedgewick e Leo J. Guibas mediante un articolo pubblicato nel 1978.
La particolarità che presentano gli alberi Red-Black, è il fatto di poter offrire un'ottima complessità di tempo anche nel caso peggiore delle operazioni di
ricerca, inserimento e cancellazione: ad ogni operazione che modica l'albero,
infatti, lo stesso si auto-bilancia, mantenendo cosi la sua altezza
h = log(n).
Ne
consegue quindi, che le operazioni descritte avranno come complessità di tempo,
al più
O(log(n)).
Viene allora da domandarsi, come fa l'albero Red-Black a bi-
lanciarsi dopo ogni operazione che ne modica la struttura. Per rispondere a
questo quesito, forniamo una denizione più formale.
4.2.1 Proprietà
Iniziamo col dire che in un RBT, a dierenza degli ABR, nei nodi è presente
un ulteriore campo, il colore.
Inoltre, per essere denito tale, un RBT deve
soddisfare alcune proprietà:
1. ogni nodo può essere rosso o nero
22
2. il nodo radice è nero
3. i nodi NIL sono neri
4. i gli di un nodo rosso sono neri
5. ogni percorso da un nodo ad una foglia, contiene lo stesso numero di nodi
neri
Visto che no ad ora non ne è stato discusso, portiamo la nostra attenzione sul
punto 3: i nodi NIL sono neri.
I nodi NIL sono nodi sentinella, messi li con lo scopo di evitare di trattare
diversamente i puntatori ai nodi dai puntatori NULL. In pratica, al posto di un
puntatore NULL, si utilizza un puntatore ad un nodi NIL. Altra cosa importante
è che, visto che i nodi NIL sono tutti uguali tra loro, se ne utilizza soltanto uno
(al quale puntano tutte le foglie e la radice) al ne di risparmiare memoria.
Le operazioni degli ABR che non modicano la struttura dell'albero (visita,
ricerca, successore, minimo, massimo) restano invariate nei RBT, ed hanno
complessità pari a
O(log(n)).
Le operazioni che invece cambiano, sono quelle di
inserimento ed eliminazione: andiamo ad analizzarle.
4.2.2
Inserimento di un elemento
L'inserimento di un elemento all'interno di un RBT si compone di due fasi:
1. viene eettivamente inserito in nodo nell'albero. Ciò avviene come in un
normale ABR, con l'unica dierenza che il nodo appena inserito viene
colorato di rosso.
2. vengono ripristinate le proprietà dell'ABR richiamando una funzione InsertFixUp.
In particolare, l'inserimento potrebbe andare a violare le proprietà 2 e 4:
•
la 2 qualora il nodo inserito sia la radice
•
la 4 qualora il padre del nodo inserito sia rosso
A causa di queste violazioni, occorre considerare ben 6 casi, di cui però 3 sono
simmetrici rispetto agli altri 3, quindi, considereremo solo questi.
Deniamo come
Z
il nodo inserito e
Y
lo zio di
Z
(ovvero il fratello del
padre).
•
Caso 1:
Y
è rosso.
In questo caso, la soluzione è quella di cambiare il
colore di alcuni nodi, preservando la proprietà 4, per poi continuare verso
l'alto facendo del nonno di
Z
il nuovo
Colorare di nero il padre di
Colorare di nero
Z
Y
Colorare di rosso il nonno di
Z
23
Z.
Le operazioni da compiere sono:
Spostare il puntatore di
nuovo
•
Caso 2:
Y
Z
verso l'alto, facendo del nonno di
Z
il
Z
è nero e
Z
è glio destro: in questo caso, la soluzione è quella
di trasformare, mediante una rotazione a sinistra del nodo
Z,
il caso 2 nel
caso 3, facendolo così diventare glio sinistro.
•
Caso 3:
Y
è nero e
Z
è glio sinistro: la soluzione in questo caso è quella
di cambiare il colore di alcuni nodi ed eettuare una rotazione a destra.
Nello specico:
Colorare di nero il padre di
Z
Colorare di rosso il nonno di
Z
Eettuare una rotazione a destra del nonno di
Z
Di seguito, l'algoritmo relativo alla procedura di Insert-FixUp:
Algorithm 3 Insert-FixUp
E ancora, l'algoritmo relativo alla rotazione a sinistra
24
Algorithm 4 LEFT_ROTATE
4.2.3
Eliminazione di un elemento
Cosi come l'inserimento, anche l'eliminazione si compone di due fasi:
1. Viene eettivamente eliminato il nodo dall'albero, come succede in un
normale ABR
2. Si stabilisce se devono essere ripristinate le proprietà dei RBT, ed eventualmente viene richiamata la funzione Delete-FixUp che ha proprio tale
scopo.
Nello specico, la Delete-FixUp dev'essere richiamata solo se il
nodo eliminato è nero in quanto, in caso contrario, non verrebbero meno
le proprietà dell'albero Red-Black.
In particolare, potrebbero essere violate le proprietà 2, la 4 e la 5:
•
la 2 qualora il nodo cancellato fosse la radice, e il glio che lo sostituisce
fosse rosso
•
la 4 qualora il padre del nodo elimnato, e il glio del nodo eliminato che
lo sostituisce, fossero entrambi rossi
•
la proprietà 5 viene violata in quanto dopo la cancellazione si avrà un
nodo nero in meno.
25
A causa di queste violazioni, occorrerebbe considerare 8 casi, di cui 4 sono
simmetrici rispetto agli altri 4, quindi andremo a considerare solo questi. Indicheremo con
•
Caso 1:
di
Z
W
W
il fratello del nodo eliminato
Z
è rosso: in questo caso, si cambiano i colori di
W
e del padre
per poi eettuare una rotazione a sinistra. Si procede poi passando
ad un altro caso. Nello specico:
•
Colorare di nero
Eettuare una rotazione a sinistra
Aggiornare
W
il colore di
•
Z
Colorare di rosso il padre di
Caso 2:
W
W
è nero ed entrambi i gli di
W
Colorare di rosso
Aggiornare
Caso 3:
W
W
sono neri: si procede cambiando
ed aggiornando Z
W
Z
è nero, il glio sinistro di
W
è rosso, il destro è nero: si procede
W , cambiando il colore
W e il suo glio destro,
cambiando il colore del glio sinistro di
eettuando una rotazione a destra tra
•
Colorare di nero il glio sinistro di
Colorare di rosso
di
W
ed
W
W
Eettuare una rotazione a destra
Aggiornare
Caso 4:
W
W
è nero, il glio destro di
W
è rosso: in questo caso la soluzione
consiste nel cambiare il colore ad alcuni nodi per poi eettuare una rotazione a sinistra. Nello specico:
Settare il colore di
W
come quello del padre
Colorare di nero il padre di
Z
Colorare di nero il glio destro di
W
Eettuare una rotazione a sinistra
Di seguito quindi, l'algoritmo relativo alla procedura di Delete-FixUp:
26
Algorithm 5 Delete-FixUp
5
Coda di max priorità: implementazione
Cosi come è stato fatto per quanto riguarda la catena di montaggio, anche in
questo caso al ne di implementare la coda di max priorità, ci si è avvalsi del
linguaggio Object Oriented
C + +.
Stavolta però, non si è fatto uso di strutture
dati particolari al ne dell'implementazione: è stato infatti implementato tutto
da zero, seguendo una modalità di sviluppo del tipo bottom-up, a partire dal
singolo nodo per nire con la vera e propria coda di priorità. Vediamo quindi,
come è stato implementato il tutto.
27
5.1 Diagramma delle classi
Figure 10: Coda di max priorità: UML
Com'è possibile notare dall'immagine, sono state implementate precisamente
cinque classi. Vediamole nello specico.
28
5.1.1
Classe Color
Siccome è stato detto che negli alberi Red-Black, viene utilizzato un campo
aggiuntivo nel nodo anchè se ne possa distinguere il colore, si è pensato di
partire dall'implementazione di questo.
Figure 11: Classe Color
La classe è molto banale: nell'interfaccia privata presenta un singolo attributo, di tipo string, che verrà settato e restituito dai metodi presenti all'interno
dell'interfaccia pubblica GetColor() e SetColor(string).
5.1.2
Classe Node
Altra classe implementata, è stata la classe Node: si tratta di una classe che
fa parte di un'aggregazione (è composta anche da un attributo di tipo Color)
e oltretutto è aggregazione di se stessa: presenta infatti tre campi puntatori a
oggetti di tipo Node, che serviranno per conoscere rispettivamente il padre, il
glio sinistro e il glio destro del nodo.
Figure 12: Classe Node
29
Nell'interfaccia privata della classe abbiamo:
•
p_parent, di tipo Node*: puntatore al padre del nodo
•
p_left, di tipo Node*: puntatore al glio sinistro del nodo
•
p_right, di tipo Node*: puntatore al glio destro del nodo
•
key, di tipo int: contiene la chiave del nodo
•
data, di tipo string: contiene i dati aggiuntivi del nodo
•
color, di tipo Color: servirà a conoscere il colore del nodo
Nell'interfaccia pubblica della classe, abbiamo gli ormai noti set e get, che ci
permetteranno di accedere o modicare gli attributi privati, dichiarati tali al
ne di garantire l'incapsulamento.
5.1.3
Classe BST
Come il nome stesso suggerisce, è stato implementato un ABR. Siccome tale
classe ci servirà per essere poi estesa, non conterrà un'interfaccia privata, bensì
una protetta. E' possibile inoltre notare, che fa parte di un'aggregazione: conterrà infatti due campi, costituiti da oggetti della classe Node.
Figure 13: Classe BST
30
Vediamo nel particolare gli attributi e i metodi.
•
root, di tipo Node*: attributo appartenente all'interfaccia protetta della
classe che conterrà, come il nome stesso suggerisce, il puntatore alla radice
dell'albero.
•
sentinel, di tipo Node*:
attributo appartenente all'interfaccia protetta
della classe che conterrà il puntatore al nodo NIL
•
Search(int) : metodo appartenente all'interfaccia protetta della classe che
permette di ricercare un elemento nell'albero
•
Search(Node*,int) : overload del metodo procedente appartenente all'interfaccia
protetta della classe
•
GetMax(Node*) : metodo appartenente all'interfaccia protetta della classe
che restituisce il nodo con chiave massima presente nell'albero
•
GetMin(Node*) : metodo appartenente all'interfaccia protetta della classe
che restituisce il nodo con chiave minima presente nell'albero
•
Inorder(Node*,bool) :
metodo appartenente all'interfaccia protetta della
classe che permette di visitare l'albero attraverso l'algoritmo di visita Inorder
•
Delete(Node*) : metodo appartenente all'interfaccia protetta della classe
che, simulando il funzionamento dell'algoritmo di visita postorder, permetterà di deallocare i nodi dell'albero
•
Delete() : overload del metodo precedente, appartenente all'interfaccia protetta della classe, che verrà richiamato dal distruttore della classe e richiamerà il metodo precedente
•
IntToString(int): metodo appartenente all'interfaccia protetta della classe
che permette di trasformare un intero in una stringa.
•
Successor(Node*) : metodo appartenente all'interfaccia protetta della classe
che permette di trovare il nodo con chiave successiva rispetto a quella del
nodo preso in input
•
IntToString(int) : metodo appartenente all'interfaccia protetta della classe
che prende in input un intero e lo restituisce sottoforma di stringa
•
Insert(int,string) : metodo appartenente all'interfaccia protetta della classe
che permette di inserire un nuovo nodo all'interno dell'albero
•
Delete(Node*) : metodo appartenente all'interfaccia protetta della classe
che permette di eliminare un nodo dall'albero
•
InsertNode(int,string) : metodo appartenente all'interfaccia pubblica della
classe che richiama il metodo Insert dell'interfaccia protetta
31
•
DeleteNode(int) : metodo appartenente all'interfaccia pubblica della classe
che richiama il metodo Delete dell'interfaccia protetta
•
SearchKey(int) : metodo appartenente all'interfaccia pubblica della classe
che permette di ricercare un nodo all'interno dell'albero
•
GetMin(bool) : metodo appartenente all'interfaccia pubblica della classe
che richiama l'omonimo metodo dell'interfaccia protetta
•
GetMin(): overload del metodo precedente
•
GetMax(bool): metodo appartenente all'interfaccia pubblica della classe
che richiama l'omonimo metodo dell'interfaccia protetta
•
GetMax() : overload del metodo precedente
•
Inorder(bool) : metodo appartenente all'interfaccia pubblica della classe
che richiama l'omonimo metodo dell'interfaccia protetta
•
Successor(int, bool) : metodo appartenente all'interfaccia pubblica della
classe che richiama l'omonimo metodo dell'interfaccia protetta
N.B: la variabile booleana presa in input da alcuni dei sopracitati metodi, serve
anchè venga considerato o meno il campo color del nodo. Nel caso specico
degli ABR, sarà impostato su false.
5.1.4
Classe RedBlackTree
Eccoci nalmente giunti alla struttura dati che servirà per implementare la coda
di priorità. Si tratta della classe RedBlackTree che, com'è intuibile dal nome,
implementa la classe degli alberi Red-Black. Si può notare dalla gura 10, come
questa sia una classe glia di BST: ne eredita quindi l'interfaccia protetta e
quella pubblica, permettendo di aggiungere cosi funzionalità a tale classe.
Figure 14: Classe RedBlackTree
La classe, oltre ai metodi e agli attributi ereditati dalla classe BST, presenta
anch'essa svariati metodi nelle interfacce privata e pubblica. Nello specico:
32
•
LeftRotation(Node*) :
metodo appartenente all'interfaccia privata della
classe che implementa l'algoritmo LEFT-ROTATE descritto in precedenza
•
RightRotation(Node*): metodo appartenente all'interfaccia privata della
classe che implementa l'algoritmo RIGHT-ROTATE descritto in precedenza
•
InsertFixUP(Node*) :
metodo appartenente all'interfaccia privata della
classe che implementa l'algoritmo Insert-FixUP descritto in precedenza
•
DeleteFixUP(Node*):
metodo appartenente all'interfaccia privata della
classe che implementa l'algoritmo Delete-FixUP descritto in precedenza
•
Delete(Node*,Node*&,Node*&): override (appartenente all'interfaccia privata della classe) del metodo ereditato da BST anchè tenga traccia di
altri nodi aggiuntivi utili per l'esecuzione del metodo DeleteFixUP(Node*)
•
InsertNode(int,string): override (appartenente all'interfaccia pubblica della
classe) del metodo ereditato da BST anchè, una volta inserito il nodo,
richiami il metodo di InsertFixUP(Node*)
•
DeleteNode(int): override (appartenente all'interfaccia pubblica della classe)
del metodo ereditato da BST anchè, una volta eliminato il nodo, richiami
eventualmente il metodo di DeleteFixUP(Node*)
•
UpdateNode(int,int): metodo appartenente all'interfaccia pubblica della
classe che è stato implementato al ne di permettere l'aggiornamento della
priorità di un elemento all'interno della coda di max-priorità.
5.1.5
Classe MaxPriorityQueue
Si tratta della classe che sfrutterà in background la struttura dati fornita dall'albero
Red-Black, richiamandone opportunamente i metodi.
Fa anch'essa parte di
un'aggregazione: è infatti composta da un oggetto del tipo RedBlackTree.
Figure 15: Classe MaxPriorityQueue
Nello specico abbiamo:
•
tree : attributo privato del tipo RedBlackTree.
33
•
Insert(int,string): metodo pubblico che permette di inserire un elemento
all'interno della coda di priorità
•
Maximum(): metodo pubblico che restituisce l'elemento con chiave massima all'interno della coda di priorità
•
ExtractMax(): metodo pubblico che restituisce l'elemento con chiave massima, e lo elimina dalla coda di priorità
•
IncreasePriority() : metodo pubblico che permette di incrementare la priorità di un elemento all'interno della coda di priorità.
5.2 Test di esecuzione
Al ne di dimostrare la bontà del codice implementato, si riportano di seguito,
alcuni test di esecuzione del software prodotto.
N.B:
I test fanno riferimento ad una singola esecuzione del programma,
nella quale vengono mostrate le funzionalità del prodotto.
5.2.1
Note per la compilazione e l'esecuzione
Il codice sorgente allegato alla relazione, è stato compilato, eseguito e testato in
ambiente Linux x64, e nello specico su ElementaryOS (Ubuntu based). Al ne
di poter compilare correttamente il codice, spostarsi nella cartella CodaMax-
Priorita . Saranno presenti:
•
color.h, contenente la classe Color
•
color-methods.cpp, contenente l'implementazione dei metodi della classe
Color
•
node.h, contenente la classe Node
•
node-methods.cpp, contenente l'implementazione dei metodi della classe
Node
•
bst.h, contenente la classe BST
•
bst-methods.cpp, contenente l'implementazione dei metodi della classe BST
•
redblacktree.h, contenente la classe RedBlackTree
•
redblacktree-methods.cpp, contenente l'implementazione dei metodi della
classe RedBlackTree
•
maxpriorityqueue.h, contenente la classe MaxPriorityQueue
•
maxpriorityqueue-methods.cpp, contenente l'implementazione dei metodi
della classe MaxPriorityQueue
•
main.cpp, contenente il main del programma
34
Per compilare, in ambiente Linux utilizzare:
g++
−o
MaxPriorityQueue
c o l o r −methods . cpp
redblacktree .h
bst . h
main . cpp
b s t −methods . cpp
node . h
r e d b l a c k t r e e −methods . cpp
m a x p r i o r i t y q u e u e −methods . cpp
maxpriorityqueue . h
−Wall − p e d a n t i c
Per eseguire, in ambiente Linux utilizzare:
. / MaxPriorityQueue
35
color .h
node −methods . cpp
5.2.2
Test 1
In questo test viene mostrato il primo inserimento all'interno della coda, e come
questo risulti essere quindi l'elemento con priorità massima.
Ovviamente, es-
sendo il primo elemento inserito nella coda di priorità, lo sarà anche all'interno
dell'albero Red-Black, quindi il suo colore sarà nero, in quanto radice.
Figure 16: Coda di max-priorità: test 1
36
5.2.3
Test 2
In questo secondo test, viene inserito un nuovo elemento con priorità maggiore
rispetto al primo, e viene mostrato come richiedendo il massimo, ci venga restituito tale elemento. Si noti, che essendo il secondo elemento all'interno della coda
di priorità, questo lo è anche per quanto riguarda l'albero Red-Black. Quindi,
essendo tale elemento inserito in un nodo glio della radice, è normale che sia
rosso.
Figure 17: Coda di max-priorità: test 2
37
5.2.4
Test 3
In questo test viene illustrato il funzionamento del metodo ExtractMax()
Figure 18: Coda di max-priorità: test 3
38
5.2.5
Test 4
In quest'ultimo test viene invece mostrato un esempio di aggiornamento della
priorità.
Figure 19: Coda di max-priorità: test 4
39
6
Risorse utilizzate
Di seguito vengono riportate le risorse utilizzate al ne della realizzazione del
progetto e della relazione ad esso associata.
1.
Sistema operativo:
2.
Editor di testo:
3.
Compilatore:
4.
Word/document processor:
ElementaryOS Luna 0.2 x64
Sublime Text
g++
(a) Apache OpenOce Writer - per la realizzazione della copertina
(b) LYX - per la realizzazione della relazione
5. Dispense di teoria e laboratorio del corso di Algoritmi e Strutture Dati
6. C++ Fondamenti di programmazione (Deitel)
7. Wikipedia
40