Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


algoritmica esercizi, Esercizi di Progettazione e analisi di algoritmi

esercizi di algoritmica da fare

Tipologia: Esercizi

2018/2019

Caricato il 28/10/2019

serena_di_leo
serena_di_leo 🇮🇹

8 documenti

1 / 16

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
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). È pe 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+1
for i in range(v0):
A[i]=0
for i in range(len(A)-v0):
A[v0+i]=1
return A
ESERCIZIO 16.2 Scrivere un programma che dato un array A contenente solo i valori
-1, 35 e 27685, per esempio A = [35, 35, 35, -1, 27685, -1, lo ordina in tempo
lineare, senza usare array o liste di appoggio.
SOLUZIONE
def ordina(A):
v1 = 0
v2 = 0
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Anteprima parziale del testo

Scarica algoritmica esercizi e più Esercizi in PDF di Progettazione e analisi di algoritmi solo su Docsity!

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

  • 1, 35 e 27685, per esempio A = [35, 35, 35, - 1, 27685, - 1 , lo ordina in tempo lineare, senza usare array o liste di appoggio. SOLUZIONE def ordina(A): v1 = 0 v2 = 0

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

A = { a j }, j = 1 , 2 ,... m

può essere codificata in una sequenza B = encode ( A ) nel modo seguente

B = { b j }, j = 1 , 2 ,... am

bj = numero di j presenti in A

tale codifica è conveniente dal punto di vista dello spazio occupato se am è molto minore di m. ESERCIZIO 1 6. 8 Scrivere

  • un programma encode(A) che riceve in input un array A contenente gli elementi di A a partire dalla posizione 0 (ovvero A[i- 1 ] = ai ) e restituisce un array B contenente gli elementi di B a partire dalla posizione 0 (ovvero B[i- 1 ] = bi )
  • un programma decode(B) che riceve in input un array B contenente gli elementi di B a partire dalla posizione 0 e rende un array A contenente gli elementi di A a partire dalla posizione 0_. SOLUZIONE_ def encode(A): B =[0]A[-1] for x in A: B[x-1]=B[x-1]+ return B def decode(B): m= for x in B: m = m+x A = [0]m k=

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

  • cosa restituisce f(M,i) se M è un array contenente numeri,
  • cosa restituisce f(M,i) se M è un array contenente caratteri. SOLUZIONE
  • Se M è un array contenente numeri, l’operatore + va inteso come somma e il risultato è la somma delle prime i +1 componenti di M.
  • Se M è un array contenente caratteri, l’operatore + va inteso come concatenazione tra stringhe alfanumeriche e il risultato è la giustapposizione invertita delle prime i +1 componenti di M. N.B. in entrambi i casi se M ha meno di i +1 componenti il programma si produce un errore a runtime. Esempio
  • Se M = [1,2,3,4,5] allora f(M, 3 ) = 10.
  • Se M = ['1','2','3','4',' 5 '] allora f(M, 3 ) = "4321".

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

  • cosa restituisce f(M,i) se M è un array contenente numeri,
  • cosa restituisce f(M,i) se M è un array contenente caratteri. SOLUZIONE
  • Se M è un array contenente numeri, l’operatore + va inteso come somma e il risultato è la somma delle prime i +1 componenti di M.
  • Se M è un array contenente caratteri, l’operatore + va inteso come concatenazione tra stringhe alfanumeriche e il risultato è la giustapposizione delle prime i + componenti di M. N.B. in entrambi i casi se M ha meno di i +1 componenti il programma si produce un errore a runtime. Esempio
  • Se M = [1,2,3,4,5] allora f(M, 3 ) = 10.
  • Se M = ['1','2','3','4',' 5 '] allora f(M, 3 ) = " 1234 ". ESERCIZIO 19. 3 Dato il programma ricorsivo def f(M, i): if i == 0: return M[0] return f(M, i-1) * M[i] dire
  • cosa restituisce f(M,i) se M è un array contenente numeri,
  • cosa restituisce f(M,i) se M è un array contenente caratteri. SOLUZIONE

SOLUZIONE

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,