Sei sulla pagina 1di 4

API IOL – III Prova in itinere 5 giugno 2020

Esercizio 1 (1.5 punti)


Si scriva una funzione C++ che riceve in input la radice di un albero generico e che restituisca
l’altezza dell’intero albero.

SOLUZIONE
Partendo dal codice per la visita di un albero generico presente nelle slide, è sufficiente
aggiungere la parte per il calcolo dell’altezza (calcolata dalle foglie e restituita al nodo padre) e
del suo massimo:

template <class Elem> int GenTree<Elem>::calcolaAltezza(GTNode<Elem>* subroot) {


if (subroot == NULL) return 0;
else {

int MaxAltezzaFigli=0, c;
for (GTNode<Elem>* temp = subroot->leftmost_child(); temp != NULL;
temp = temp->right_sibling()){
c=calcolaAltezza(temp);
if (c > MaxAltezzaFigli)
MaxAltezzaFigli=c;
}
return MaxAltezzaFigli + 1;
}

Esercizio 2 (1 punto)
Data la seguente sequenza di chiavi, si costruisca un albero B di ordine 4.
50, 19, 41, 10, 12, 71, 64, 73, 70, 11, 45, 5,
Oltre al risultato finale si riportino i risultati intermedi dopo aver inserito i valori evidenziati.
SOLUZIONE 1 (scegliendo come valore “centrale” da mandare verso l’alto il terzo valore di 4 –
l’importante è essere coerenti per tutto l’esercizio, perché l’implementazione di un algoritmo
non sceglierebbe a caso il valore “centrale”)
41

10,19 50

41,71

10,12,19 50,64 73

12,41,71

10,11 19 50,64,70 73

64

12,41 71

5,10,11 19 45,50 70 73

SOLUZIONE 2 (mandando verso l’alto il secondo valore di 4)


19

10 50,70

5 11,12 41,45 64 71,73


Esercizio 3 (1.5 punti)
Dato un array contenente numeri interi si progetti un algoritmo di ordinamento che ordini i
numeri dispari inserendoli nelle posizioni dispari dell’array e i numeri pari nelle posizioni pari
dell’array. Se i numeri pari (o dispari) superano i numeri dispari (pari), tutti i numeri rimanenti
vengono inseriti alla fine dell’array.
Si descriva l’algoritmo in modo chiaro e sufficientemente dettagliato e se ne analizzi la
complessità nel caso peggiore.
Si simuli l’algoritmo passo passo sul seguente array (la prima riga indica la posizione):

0 1 2 3 4 5 6 7 8 9
5 10 12 8 7 2 4 3 11 6

La valutazione terrà conto della complessità temporale e spaziale dell’algoritmo proposto e


della chiarezza/correttezza con cui viene descritto.
Si possono discutere più soluzioni per mostrare la soluzione finale scelta.

TRACCIA DELLA SOLUZIONE


Utilizzando uno o due array ausiliari le soluzioni sono numerose e avete scelto tutti soluzioni
ragionevoli. Tipicamente richiedono una complessità temporale Theta(n log n) e complessità
spaziale Theta(n) per gli array ausiliari.
- Si può prima ordinare e poi partizionare oppure
- Prima separare i numeri pari dai numeri dispari e poi ordinare i due gruppi
separatamente
Vanno bene entrambe le opzioni; le complessità temporale e spaziale non cambiano con le due
scelte.
La complessità temporale non si può migliorare (nel caso peggiore si possono avere solo numeri
pari o solo numeri dispari e quindi la complessità totale è data dalla complessità dell’algoritmo
di ordinamento).
DOMANDA: Si può migliorare la complessità spaziale, senza peggiorare la complessità
temporale? Si può applicare l’algoritmo sull’array iniziale senza utilizzare ulteriore memoria?
Alcuni hanno utilizzato solo l’array di partenza e ottenuto una complessità temporale
Theta(n^2): ad esempio, pensate ad un algoritmo che dopo aver partizionato l’array in pari e
dispari (vedi breve descrizione sotto) applichi un insertion sort per inserire i valori pari (e
dispari) spostando “indietro” il valore fino a quando non arriva nella posizione pari (o dispari)
corretta. In generale, tutti gli algoritmi Theta(n^2) che avete studiato sono algoritmi che
operano “sul posto” (in place) e non richiedono array ausiliari.
PARTIZIONAMENTO: si può effettuare un “partizionamento” in modo da mettere nelle posizioni
pari i numeri pari e nelle posizioni dispari i numeri dispari (tranne che per gli elementi in fondo
all’array)
- Si implementa in modo simile ai partizionamenti già visti con quicksort o in altri esercizi.
E’ sufficiente scorrere un indice per trovare i numeri dispari che stanno nelle posizioni
pari e che vanno pertanto cambiati di posizione ed un indice per i numeri pari che
stanno nelle posizioni dispari: ogni volta che si ha una coppia di questo tipo si effettua
uno scambio. Si trovano le coppie da scambiare fino a quando non si arriva alla fine
dell’array (Theta(n))
Una volta che si ha questo partizionamento è possibile effettuare un ordinamento con
complessità Theta(n log n) per ordinare i numeri pari e i numeri dispari direttamente “sul
posto”?
- Innanzitutto occorre sapere quanti sono i numeri pari e i numeri dispari, perché nella
parte finale dell’array potrebbero esserci solo numeri pari o dispari in tutte le posizioni;
si possono calcolare durante il partizionamento.
- Un esempio di algoritmo che opera sul posto è l’algoritmo di Heapsort: non richiede
array ausiliari ed è iterativo per cui non ci sono costi nascosti dovuti alla ricorsione.
L’algoritmo richiede di essere modificato in modo da prevedere incrementi di due
posizioni anziché di una posizione nella prima parte dell’array e incrementi di una
posizione per l’ultima parte dell’array nel caso in cui vi sia un eccesso di elementi
pari/dispari. Oppure si può pensare di ordinare separatamente la parte dove
l’incremento è 2 e la parte finale con incremento 1 e poi si applica un merge sul posto
delle due parti…
Vanno bene tutte le soluzioni che avete proposto, che possono essere più o meno ottimizzate
dal punto di vista spaziale e/o temporale. L’importante è imparare a conoscere meglio tutti gli
algoritmi di ordinamento e le loro caratteristiche, perché possono essere utili per scegliere la
soluzione migliore per i vincoli che potreste avere per il vostro problema.

Potrebbero piacerti anche