Esercizio Dato un albero binario, definiamo altezza minimale di un nodo v la minima distanza di v da una delle foglie del suo sottoalbero, definiamo invece altezza massimale di un nodo v la massima distanza di v da una delle foglie del suo sottoalbero. Supponiamo di avere un albero T che contiene in ogni nodo anche un numero intero m. Diciamo che l’albero è k-equilibrato se tutti i nodi (eccetto al più k) contengono un valore m che è compreso tra l’altezza minimale e l’altezza massimale del nodo stesso. Definire un algoritmo che riceve in input l’albero T e un intero k e restituisce vero se l’albero T è k-equilibrato, falso altrimenti. Calcolare la complessità dell’algoritmo proposto.
int maxheight ( tree t ) { int D, S; if (t == NULL) return 0; S = maxheigth( t->left ); D = maxheigth( t->right ); if ( S > D ) return S + 1; else return D + 1; } int minheight ( tree t ) { int D, S; if (t == NULL) return 0; S = minheigth( t->left ); D = minheigth( t->right ); if(S==0) return D+1; if(D==0) return S+1; if ( S < D ) return S + 1; else return D + 1; }
int contaEcc ( tree t ) { int n=0; if(t->valore > maxheigth( t ) || t->valore < minheigth( tb )) n++; n+=contEcc(t->left); n+=contEcc(t->right); return n; } int kequilibrato(tree t,int k) { if(contaEcc(t)<=k) return 1; return 0;
int contaEcc ( tree t,int M,int m ) { int n=0; if(t->valore > M || t->valore < m ) n++; n+=contEcc(t->left,M-1,m-1); n+=contEcc(t->right,M-1,m-1); return n; } int kequilibrato(tree t,int k) { int M,m; M= maxheigth( t ); m=minheigth( t )) if(contaEcc(t,M,m)<=k) return 1; return 0;
Esercizio Costruire l'albero di Huffman necessario per codificare la seguente frase: “a nice way of encoding”
Esercizio Determinare la complessità computazionale del seguente frammento di codice C in funzione della lunghezza della stringa A int foo(char A[], int n, int m) { int i, a=0; if (n>=m) return 0; for(i=n; i<m; i++) a+=A[i]; return a + foo(A, n*2, m/2); } int bar(char A[]) { return foo(A,1,strlen(A));
Esercizio Determinare i bound di complessità asintotica più stretti per la seguente ricorrenza: T(n) = 4T(n/3) + n5
Esercizio Si consideri un array bidimensionale A di m righe e n colonne, in cui ogni riga è ordinata in ordine crescente. Descrivere un algoritmo in grado di riunire le m righe di A in un unico array ordinato B di nm elementi in tempo O(n m log m) Suggerimento: mantenere il primo elemento non ancora copiato in B di ciascuna riga in uno heap H di m elementi
Esercizio Sia dato un array A di n elementi interi. Sia dato un algoritmo che esegue in sequenza le due operazioni: Inserisci(i,x): assegna il valore x all’elemento A[i]; Somma(l,m): calcola la somma degli elementi di A con indice compreso tra l e m. La prima operazione ha costo costante, mentre la seconda, nel caso peggiore, ha un costo O(n). Si discuta come l’uso di una struttura dati aggiuntiva permette di ridurre la complessità dell’algoritmo a O(log n). Data l’organizzazione dei dati individuata, si definisca in pseudocodice la specifica delle due operazioni di inserimento e di somma e se ne discuta la complessità.
Esercizio Si risolva l'equazione ricorsiva T(n) = 2T(n/3) + n4 Si specifichi in pseudocodice un’ipotetica funzione foo che abbia una complessità pari all’equazione ricorsiva (non è necessario che la funzione faccia qualcosa di significativo). Si proponga una macchina RAM che abbia una complessità pari all’equazione ricorsiva (non è necessario che la macchina faccia qualcosa di significativo).
Esercizio Si consideri il seguente problema: Data una n-pla di numeri interi a1, a2, . . . , an, n ≥ 1 si calcoli la somma a1 + a2 + · · · + an. a) Descrivere ad alto livello una procedura per risolvere il problema. b) Assumendo il criterio di costo uniforme, determinare l’ordine di grandezza del tempo di calcolo e dello spazio di memoria richiesti dalla procedura in funzione di n. c) Supponendo che ogni ai sia un intero di k bit, e assumendo il criterio di costo logaritmico, determinare l’ordine di grandezza del tempo e dello spazio richiesti dalla procedura in funzione dei parametri n e k.
Esercizio Dato un grafo diretto rappresentato mediante liste di adiacenza, per ogni nodo v si vuole calcolare il numero dei nodi raggiungibili da v (ovvero il numero dei nodi w per i quali esiste un cammino orientato da v a w). a) Definire un algoritmo che risolva il precedente problema; b) Discutere la complessità dell’algoritmo definito.
Esercizio Una società deve progettare un sistema informativo per gestire i propri progetti. Ogni progetto ha una scadenza ed è composto da diversi task. Ogni task ha una durata e un numero di persone associato. Alcuni task hanno delle dipendenze: ad esempio nel progetto P1 non posso completare il task T3 se non ho completato prima il task T1. 1) Si progetti una struttura dati per rappresentare le informazioni e si progetti un algoritmo che assegna ad ogni progetto una data d'inizio limite oltre cui non sarà possibile iniziare il progetto. 2) Si implementi anche un algoritmo che calcoli quante persone sono necessarie per eseguire tutti i task nel momento in cui c'è il maggior numero di risorse richieste.
Esercizio Si consideri la seguente definizione di un albero binario in un linguaggio C-like: struct ET { int dato; struct ET * left, right; } treeNode; typedef treeNode * tree; Definiamo grado di un livello di un albero la somma degli elementi appartenenti al livello stesso. Una coppia di alberi t1 e t2 si dice k-similare se esistono almeno k livelli in t1 e in t2 di pari grado. Nota: non è necessario che i livelli di pari grado siano lo stesso livello nei due alberi. Si codifichi, in pseudocodice o in un linguaggio di programmazione a scelta, la funzione int ksimilare(tree t1, tree t2, int k) che restituisce 1 se t1 e t2 sono k-similari, 0 altrimenti.
Esercizio Dati due insiemi di interi A={a1, a2, …, an} e B={b1, b2, …, bm}, sia C la loro intersezione, ovvero l’insieme degli elementi contenuti sia in A che in B. Quale è la complessità minima di un algoritmo che calcola C? Spiegare come funzionerebbe.
Esercizio L’algoritmo Insertion-Sort può essere espresso come una procedura ricorsiva nel modo seguente: per ordinare A[1], …, A[n] si ordinano in modo ricorsivo i primi n-1 elementi A[1], …A[ n − 1] e poi si inserisce A[n] nell’array ordinato A[1], …, A[n − 1] Scrivere una ricorrenza che esprima il tempo di esecuzione di questa versione ricorsiva di Insertion-Sort