INFORMATICA 3 Prof.ssa Sara Comai ESERCIZI SESSIONE LIVE 3 Complessità, liste e alberi Ing. Paola Spoletini, Sara Comai 1. Complessità Si determini l’ordine di grandezza Q della complessità temporale di tale frammento in funzione di n i = i*i; while ( i <= n) { b[j] = a[i]; j++; i = i*i; } Si determini l’ordine di grandezza Q della complessità temporale di tale frammento in funzione di n SOLUZIONE Simuliamolo: 2 Æ 2*2 Æ 4*4Æ16*16 Æ … Cioè 2Æ 22Æ22*22Æ24*24Æ… Che è 2Æ22Æ24Æ28Æ… Che si può vedere come 2Æ22Æ22^2Æ22^3Æ…Ælog(log n) 2. Alberi binari In un albero binario la numerazione per livelli assegna a ogni nodo v dell’albero un valore intero positivo p(v) in accordo alle seguenti regole: • se v è la radice allora p(v) = 1 • se v è figlio sinistro di u allora p(v) = 2 * p(u) • se v è figlio destro di u allora p(v) = 2 * p(u) + 1 In figura è riportato un esempio di tale numerazione. 1 2 3 4 5 7 10 8 11 22 23 DOMANDA 1 Indicare qual è il valore massimo p(v) che può essere assegnato a un nodo v di un albero binario che contiene n nodi, giustificando la risposta. [Suggerimento: considerare, per un albero fissato, qual è il nodo cui viene assegnato il valore massimo.] DOMANDA 2 Disegnare un albero, con 4 nodi, in cui il limite indicato in precedenza viene raggiunto dal p(x) di un nodo x dell’albero. SOLUZIONE DOMANDA 1 1 2 4 3 5 7 10 8 11 22 23 Il valore massimo nell’albero dell’esempio è assegnato al nodo più a dx del livello più basso. 1 3 7 15 31 Proviamo a sviluppare un albero che si sviluppa solo a destra 31 è il nodo n (n=5) −−> 2n-1 DOMANDA 2 1 3 7 15 3. Alberi binari Per un dato albero binario T, si definisce Lunghezza dei Cammini Interni, indicata con LCI(T), la somma delle lunghezze dei cammini che vanno dalla radice ai nodi interni dell’albero; si definisce Lunghezza dei Cammini Esterni, indicata con LCE(T), la somma delle lunghezze dei cammini che vanno dalla radice alle foglie dell’albero. 1. Indicare la relazione esistente, in un albero binario T pieno e con n nodi interni, tra LCE(T), LCI(T) ed n. Dimostrare tale relazione (suggerimento: operare per induzione) SOLUZIONE 1. In un albero T binario pieno LCE(T) = LCI(T) + 2n 2. Dimostrazione per induzione sul numero n dei nodi interni. Caso Base: Un albero con la sola radice ha n=0, LCI=LCE=0. Induzione: In un albero T pieno con k nodi interni, sia LCI(T)=h ed LCE(T)=h+2k. Otteniamo un albero T’ pieno con k+1 nodi interni aggiungendo due figli a una delle foglie, che supponiamo (senza perdere in generalità) stia a profondità j. Nel nuovo albero un “cammino esterno” di lunghezza j è diventato un “cammino interno”, e ci sono due nuovi “cammini esterni” di lunghezza j+1. Valgono allora le seguenti relazioni. LCI(T’) = LCI(T) + j = h + j LCE(T’) = LCE(T) – j + 2 * (j+1) = = h + 2*k – j + 2*j + 2 = = h + 2*k + j + 2 = = h + j + 2*(k + 1) = = LCI(T’) + 2*(#nodi interni) 4. Algoritmi e complessità Siano dati due insiemi di record: S1 = {<k1, i1>, <k2, i2>, …. <kn, in>}, S2 = {<h1, j1>, <h2, j2>, …. <hn, jn>}, dove kr e hr denotano le chiavi dei record e ir, jr i contenuti informativi di tipo generico. Le chiavi sono costituite da stringhe di al più 30 caratteri alfanumerici. Si descriva brevemente, senza necessariamente codificarlo in un preciso linguaggio di programmazione, un algoritmo per costruire l’intersezione S di S1 e S2 e se ne valuti l’ordine di grandezza della complessità temporale. Si discuta brevemente se la complessità ottenuta sia ottima o se sia possibile migliorarne l’ordine di grandezza mediante un algoritmo più sofisticato. NB1. Per semplicità si può assumere che i due insiemi abbiano la stessa cardinalità, oppure fare riferimento alla cardinalità del maggiore dei due. NB2. I due insiemi non sono ordinati rispetto al valore delle loro chiavi né dei campi informativi. SOLUZIONE Un algoritmo banale che calcola S è il seguente: for x in S1 for y in S2 if key(x)=key(y) then put x in S Che è chiaramente Θ(n2). Però sappiamo che, se S1 e S2 sono ordinati, si può scrivere un algoritmo banale che costruisce S, con complessità Θ(n). Sappiamo che il problema dell’ordinamento basato su confronto di chiavi è limitato inferiormente da Ω(n log n) nel caso peggiore (es. QuickSort è Θ(n log n) in ogni caso), dunque possiamo risolvere il problema con un algoritmo che ordina i due insiemi e ne sfrutta dunque l’ordinamento, ottenendo una complessità Θ(n log n). 5. Pile e code Utilizzando i seguenti ADT per le pile e per le code // Stack abtract class template <class Elem> class Stack { public: // Reinitialize the stack virtual void clear() = 0; // Push an element onto the top of the stack. virtual bool push(const Elem&) = 0; // Remove the element at the top of the stack. virtual bool pop(Elem&) = 0; // Get a copy of the top element in the stack virtual bool topValue(Elem&) const = 0; // Return the number of elements in the stack. virtual int length() const = 0; }; // Abstract queue class template <class Elem> class Queue { public: // Reinitialize the queue. The user is responsible for // reclaiming the storage used by the stack elements. virtual void clear() = 0; // Place an element at the rear of the queue. Return // true if successful, false if not (if queue is full). virtual bool enqueue(const Elem&) = 0; // Remove the element at the front of the queue. Return // true if succesful, false if queue is empty. // The element removed is returned in the first parameter. virtual bool dequeue(Elem&) = 0; // Remove Elem from front // Return in first parameter a copy of the front element. // Return true if succesful, false if queue is empty. virtual bool frontValue(Elem&) const = 0; // Return the number of elements in the queue. virtual int length() const = 0; }; Si specifichi il codice o pseudocodice per realizzare le seguenti operazioni 1) ConfrontoPile: date due pile P1 e P2 si verifichi se contengono le stesse sequenze 2) PilaPalindrome: data una pila P si determini se la sequenza contenuta nella pila è palindrome 3) ConfrontoCode: date due code C1 e C2 si verifichi se contengono le stesse sequenze 4) CodaPalindrome: data una coda C si determini se la sequenza contenuta nella coda è palindrome SOLUZIONE 1) ConfrontoPile(P1,P2) if(P1.length() != P2.length()) return FALSE; while (P1.length()){ P1.pop(elem1); P2.pop(elem2); if (elem1 != elem2) return FALSE; } return TRUE; 2) PilaPalindrome(P) Stack S; //pila vuota lung = P.length() for (i=1; i<(lung/2); i++)()){ P.pop(elem); S.push(elem); } if (lung%2) P.pop(elem); return ConfrontoPile(P,S); 3) ConfrontoCode(C1,C2) if(C1.length() != C2.length()) return FALSE; while (C1.length()){ C1.dequeue(elem1); C2.dequeue(elem2); if (elem1 != elem2) return FALSE; } return TRUE; 4) CodaPalindrome(C) Stack S; //pila vuota lung = C.length() for (i=1; i<(lung/2); i++)()){ C.dequeue(elem); S.push(elem); } if (lung%2) C.dequeue(elem); while (C.length()){ C.dequeue(elem1); S.pop(elem2); if (elem1 != elem2) return FALSE; } return TRUE;