









Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
esercizi di algoritmica da fare
Tipologia: Esercizi
1 / 16
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!










16. Esercizi sugli array Il Teorema 8.1 stabilisce che non esiste alcun algoritmo di ordinamento generale, basato su confronti, con complessità minore di Ω( n log n ). È però possibile ordinare un array senza basarsi sui confronti ma usando direttamente i valori degli elementi da ordinare. Per esempio se il dominio dei valori degli elementi dell’ array è finito e piccolo al confronto della dimensione dell’ array esistono algoritmi di ordinamento di complessità lineare. Gli esercizi che seguono sono basati sull’idea di contare le frequenze degli elementi dell’array per poi ricostruirlo ordinato. ESERCIZIO 16.1 Dare un programma che dato un array A contenente solo 0 e 1, per esempio A = [0,0,1,1,0,1,0,0], lo ordina in tempo lineare, senza usare array o liste di appoggio. SOLUZIONE def ordina(A): v0 = 0 for a in A: if a==0: v0=v0+ for i in range(v0): A[i]= for i in range(len(A)-v0): A[v0+i]= return A ESERCIZIO 1 6. 2 Scrivere un programma che dato un array A contenente solo i valori
for a in A: if a==-1: v1=v1+ if a==35: v2=v2+ for i in range(v1): A[i]=- 1 for i in range(v2): A[v1+i]= for i in range(len(A)-v1-v2): A[v1+v2+i]= 27685 return A ESERCIZIO 1 6. 3 Dare un programma che dato un array A contenente interi compresi tra 0 e m - 1 (con m piccolo rispetto alla dimensione di A) lo ordina in tempo lineare. SOLUZIONE def ordina(A, m): v = [0]*m for a in A: v[a]=v[a]+ k= for i in range(m): for j in range(v[i]): A[k]=i k=k+ return A ESERCIZIO 1 6. 4 Dare un programma che dato un array A di numeri restituisce la somma di quelli di posto pari. SOLUZIONE def sommaPari(A): s= for i in range(len(A)): if i%2==0: s=s+A[i] return s
while i<n and j<n: if A[i]==B[j]: k=k+ i=i+ j=j+ elif A[i]<B[j]: i=i+ else : j=j+ return k Una sequenza, monotona, non decrescente, di interi non negativi
può essere codificata in una sequenza B = encode ( A ) nel modo seguente
tale codifica è conveniente dal punto di vista dello spazio occupato se am è molto minore di m. ESERCIZIO 1 6. 8 Scrivere
for i in range(len(B)): for j in range(B[i]): A[k]=i+ k=k+ return A A=[1,1,1,2,3,3,5,6,7] B=encode(A) C=decode(B) print("A =",A) print("B =",B) print("C =",C) A = [1, 1, 1, 2, 3, 3, 5, 6, 7] B = [3, 1, 2, 0, 1, 1, 1] C = [1, 1, 1, 2, 3, 3, 5, 6, 7] La definizione matematica di encode e decode può essere banalmente estesa a sequenze infinite. La sequenza autodefinente di Solomon Golomb è l’unica sequenza A, infinita, monotona, non decrescente, di interi non negativi, per cui vale: A = encode ( A ). Si vede facilmente che a 1 può essere solo 1, infatti la sequenza contiene numeri interi positivi e se fosse a 1 > 1 vi dovrebbero essere a 1 valori uguali a 1, cosa impossibile se a 1 non è 1. Inoltre a 2 può essere solo 2, infatti essendovi un solo 1 nella sequenza allora a 2 > 1 e se fosse a 2 > 2 allora nella sequenza non vi sarebbero 2 e dovrebbe essere a 2 = 0. L’inizio della sequenza è quindi 12… ma poiché vi sono 2 valori 2 allora l’inizio della sequenza è 122… e quindi 12233… e quindi 122333444555… e così via. ESERCIZIO 1 6. 9 Scrivere un programma solomon(m) che rende un array A, di lunghezza m +1, contenente i primi m elementi della sequenza di Solomon Golomb a partire dalla posizione 1 (ovvero A[i] = ai , i >0). SOLUZIONE def solomon(m): A = [0]*(m+1) A[0]='' A[ 1 ]= 1 A[2]= h=
def radice(A): return A[0] def sinistro(A): return A[1] def destro(A): return A[2] def isVuoto(A): return A is None def isFoglia(A): return isVuoto(sinistro(A)) and isVuoto(destro(A)) La funzione stampa(A) offre un rudimentale modo di stampare un albero binario. def stampaAlbero(A): print(" ") stampaAlbero1(A," ") print(" ") def stampaAlbero1(A, s): if not isVuoto(A): stampaAlbero1(destro(A),s+" ") print(s,radice(A)) stampaAlbero1(sinistro(A),s+" ") Proviamo stampa costruendo e stampando il seguente albero. a b d e c f La cui rappresentazione interna è: ['a',['b',['d', None , None ],['e', None , None ]],['c', None ,['f', None , None ]]
B = nodo('b', foglia('d'), foglia('e')) C = nodo('c', vuoto(), foglia('f')) A = nodo('a', B, C) stampaAlbero(A) f c a e b d 18. Esercizi sugli alberi binari Vengono ora presentati alcuni semplici esempi di programmi che operano su alberi binari. I programmi fanno uso delle funzioni base definite nel paragrafo precedente. Si noti che gli stessi programmi sono compatibili con qualunque altra implementazione degli alberi binari che implementi lo stesso insieme di funzioni base. ESERCIZIO 1 8 .1 Scrivere un programma ricorsivo che dato un albero binario con valori numerici ai nodi calcola la somma degli elementi non foglia. SOLUZIONE def sommaNF(A): if isVuoto(A): return 0 if isFoglia(A): return 0 return radice(A)+sommaNF(sinistro(A))+sommaNF(destro(A)) ESERCIZIO 1 8. 2 Scrivere un programma ricorsivo che dato un albero binario con valori numerici ai nodi calcola la somma degli elementi al livello k. SOLUZIONE
def maxD(A): if isVuoto(A): return 0 return max(maxP(sinistro(A)), maxP(destro(A))) 19. Esercizi sulla ricorsione Gli esercizi che seguono sono orientati alla comprensione di semplici programmi ricorsivi. La mancanza dell’obbligo di dichiarazioni in Phyton fa sì che uno stesso programma possa implementare algoritmi diversi a seconda dei tipi dei dati con cui viene chiamato. ESERCIZIO 19 .1 Dato il programma ricorsivo def f(M, i): if i == 0: return M[0] return M[i] + f(M, i-1) dire
ESERCIZIO 19. 2 Dato il programma ricorsivo def f(M, i): if i == 0: return M[0] return f(M, i-1) + M[i] dire
In base al Lemma 5.1 si ha u = 3, v = 2, α = log 3 /log 2, β = 1. Poiché α è un numero compreso tra 1 e 2 la complessità è O( n α ). Se si dispone di una calcolatrice si può determinare α con maggiore precisione, ovvero α = 1.58496… OSSERVAZIONE. Questa relazione si usa per determinare la complessità in termini di operazioni su bit di un algoritmo di moltiplicazione ricorsiva di numeri interi. ESERCIZIO 20. 4 Data la ricorrenza f ( i ) = 2 f (⎡ i / 2 ⎤) + c i , i > k determinare l’ordine di crescita di f ( n ). SOLUZIONE In base al Lemma 5.1 si ha u = 2, v = 2, α = 1, β = 1. La complessità è O( n log n ). OSSERVAZIONE. Questa relazione si usa, tra l’altro, per determinare la complessità di algoritmi come Quicksort , Mergesort e Heapsort. ESERCIZIO 20. 5 Data la ricorrenza f ( i ) = 2 f (⎡ i / 2 ⎤) + c , i > k determinare l’ordine di crescita di f ( n ). SOLUZIONE In base al Lemma 5.1 si ha u = 2, v = 2, α = 1, β = 0. La complessità è O( n ). ESERCIZIO 20. 6 Data la ricorrenza f ( i ) = f (⎡ i / 2 ⎤) + c , i > k determinare l’ordine di crescita di f ( n ). SOLUZIONE In base al Lemma 5.1 si ha u = 1, v = 2, α = 0, β = 0. La complessità è O(log n ). OSSERVAZIONE. Questa relazione si usa, tra l’altro, per determinare la complessità della ricerca binaria. ESERCIZIO 20. 7 Data la ricorrenza f (1) = 1, f (2) = 2, f (3) = 3, f(4) = 4, f ( i ) = 2 f( i - 1), i > 4
determinare l’ordine di crescita di f ( n ) e trovare l’espressione esatta del generico termine per n grande. SOLUZIONE Ignorando i valori dell’argomento minori di 4 si prendono in considerazione i valori successivi f (4) = 4, f (5) = 8, f (6) = 16, f (7) = 32, da cui si evince che f ( n ) = 2 n , per n ≥ 4 e quindi che l’ordine di crescita è esponenziale. Si noti che l’espressione del valore esatto può essere dimostrata rigorosamente per induzione. ESERCIZIO 20. 8 Data la ricorrenza f (1) = 10, f (2) = 20, f (3) = 30, f(4) = 16, f ( i ) = f( i - 1) + 2 i - 1, i > 4 determinare l’ordine di crescita di f ( n ) e trovare l’espressione esatta del generico termine per n grande. SOLUZIONE Ignorando i valori dell’argomento minori di 4 si prendono in considerazione i valori successivi f (4) = 16, f (5) = 25, f (6) = 36, f (7) = 49, da cui si evince che f ( n ) = n 2 , per n ≥ 4 e quindi che l’ordine di crescita è quadratico. Si noti che l’espressione del valore esatto può essere dimostrata rigorosamente per induzione. ESERCIZIO 20. 9 Data la ricorrenza f (1) = 1, f (2) = 2, f (3) = 3, f(4) = 4, f ( i ) = f( i - 1) + 2, i > 4 determinare l’ordine di crescita di f ( n ) e trovare l’espressione esatta del generico termine per n grande. SOLUZIONE Ignorando i valori dell’argomento minori di 4 si prendono in considerazione i valori successivi f (4) = 4, f (5) = 6, f (6) = 8,