Algoritmi e basi di dati – modulo Algoritmi e Strutture dati – a.a. 2012/2013 27 febbraio 2013 Cognome Nome 1 2 3 Matricola 4 5 Esercizio 1 Sia data una struttura hash memorizzata su un array di 100 posizioni che memorizza un insieme di al massimo 80 elementi. Indicare il contenuto delle prime 4 celle dell’array, inizialmente vuoto, dopo le operazioni seguenti (indirizzamento con il metodo dello hash modulare, scansione lineare): a) Inserimento dell’elemento 100 b) Inserimento dell’elemento 300 c) Inserimento dell’elemento 200 d) Cancellazione dell’elemento 300 e) Inserimento dell’elemento 400 Indirizzo Inizio Dopo a) Dopo b) Dopo c) Dopo d) Dopo e) 0 -1 100 100 100 100 100 1 -1 -1 300 300 -2 400 2 -1 -1 -1 200 200 200 3 -1 -1 -1 -1 -1 -1 Esercizio 2 Dato il grafo orientato in figura, trovare i cammini minimi dal nodo A a tutti gli altri nodi. Per ogni passo dell'algoritmo, indicare l'insieme Q, le distanze minime stimate e i nodi precedenti nel cammino minimo stimato. A 2 B 3 4 C 9 9 4 1 D 3 E F Q A B C D E F dist pred dist pred dist pred dist pred dist pred dist pred ABCDEF 0 - inf - inf - inf - inf - inf - BCDEF 0 - 2 A 4 A 3 A inf - inf - CDEF 0 - 2 A 4 A 3 A inf - 11 B CEF 0 - 2 A 4 A 3 A 12 D 11 B EF 0 - 2 A 4 A 3 A 8 C 11 B F 0 - 2 A 4 A 3 A 8 C 9 E Esercizio 3 Calcolare la complessità del for in funzione di n>0. for (int i=0; i <= g(g(n))+f(n); i++) cout << i; con le funzioni f e g definite come segue. Indicare per esteso le relazioni di ricorrenza e, per ogni comando ripetitivo, il numero di iterazioni e la complessità della singola iterazione. int g(int x){ int f(int x){ if (x<=0) return 1; if (x<=0) return 1; int a = 0; int a = g(x); for (int i=0; i <= x; i++) int b = a + 2*f(x/2); a+=i; for (int i=0; i <= x*x; i++) for (int j=a; j >= 0; j--) cout << i; cout << a; return b + 2*f(x/2); return a*a + g(x-1); } } Funzione g Primo for: Complessità della singola iterazione: O(1) Numero di iterazioni: O(n) Complessità del for: O(n) Secondo for: Complessità della singola iterazione: O(1) Numero di iterazioni: O(n^2) Complessità del for: O(n^2) Tg(0)= d Tg(n)= cn^2 + Tg(n-1) Tg(n) è O(n^3) Rg(0)= d Rg(n)= cn^4 + Rf(n-1) Rg(n) è O(n^5) Funzione f for: Complessità della singola iterazione: O(1) Numero di iterazioni: O(n^2) Complessità del for: O(n^2) Tf(0)= d Tf(n)= cn^3+ 2Tf(n/2) Tf(n) è O(n^3) Rf(0)= d Rf(n)= cn^5+ 4Rf(n/2) Rf(n) è O(n^5) Calcolo for del blocco: numero iterazioni: g(g(n)) + f(n)= g(n^5) + O(n^5)= O(n^25) Complessità della singola iterazione: Tg(n) + Tg(n^5) + Tf(n) = O(n^3) + O(n^15) + O(n^3) = O(n^15) Complessità del for: O(n^40) Esercizio 4 Scrivere una funzione booleana che, dati due alberi binari t1 e t2 ad etichette intere, controlli che siano speculari. bool speculari(Node* t1, Node* t2){ if (!t1 && !t2) return true; if (!t1) return false; if (!t2) return false; if (t1->label != t2->label) return false; return speculari(t1->left, t2->right) && speculari(t1->right, t2->left); } Esercizio 5 Scrivere una funzione che, dato un albero generico t ad etichette intere, conta i nodi dell'albero che hanno più figli che fratelli successivi. int conta(Node* t) { if (!t) return 0; return (fratelli(t->left) > fratelli(t->right)) + conta(t->left) + conta(t->right); } int fratelli(Node* t) { if (!t) return 0; return 1 + fratelli(t->right); } O(n): int conta2(Node* t, int& fratelli) { if (!t) {fratelli = 0; return 0;} int figli; int ret = conta2(t->left, figli) + conta2(t->right, fratelli); if (figli > fratelli) ret++; fratelli++; return ret; }