Sei sulla pagina 1di 10

Algoritmi e Strutture Dati

Ora si che ci incazziamo

Salvatore De Simone 23 ottobre 2013

Indice
1 Iterazione e Ricorsione 1.1 Insertion Sort . . . . . . . . . . . . . . 1.2 Complessit` a e correttezza . . . . . . . 1.3 Mergesort . . . . . . . . . . . . . . . . 1.3.1 Approccio divide et impera . . 1.3.2 Procedura di MERGE . . . . . 1.3.3 Dimostrazione della correttezza 1.3.4 Mergesort . . . . . . . . . . . . 5 5 6 7 7 7 9 9

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

INDICE

Capitolo 1

Iterazione e Ricorsione
In questo capitolo sar` a arontato il problema dellordinamento di chiavi allinterno di una lista di elementi. In generale tale problema pu` o essere denito come segue: Input: Dato una sequenza di n elementi; Outuput: si ottiene una riorganizzazione degli elementi della sequenza tale che sia rispettata la relazione a1 a2 ... an (1.1)

1.1

Insertion Sort

Il primo aloritmo di ordinamento presentato ` e quello di insertion sort, eciente per ordinare piccole seqeunze di elementi. Lalgoritmo opera cosi come opera un giocatore di carte che ordinal le carte nella propria mano sinistra. Si parte con una mano vuota e linsieme delle carte sul tavolo e ad ogni inserimento la carta viene direttamente inserita nella giusta posizione confrontando le carte che sono presenti nella propria mano. Lalgoritmo termina quando sono terminte le carte da porre in mano. Lalgoritmo di insertion sorto ordina tutti gli elementi sul posto: un certo numero di elementi sono risistemati allinterno dellarray mantenendo esternamente un certo numero di elementi. Al termine della procedura per` o abbiamo una seqeunza A ordinata correttamente. Analizziamo il seguente pseudocodice che illustra la logica dellalgoritmo:

CAPITOLO 1. ITERAZIONE E RICORSIONE

f u n c t i o n INSERTIONSORT(A) f o r j = 2 t o A. l e n g h t : key = A[ j ] i = j 1 // s p o s t a t u t t i g l i e l e m e n t i a d e s t r a d e l l a p o s i z i o n e dove i n s e r i r e key w h i l e i > 0 && A[ i ] > key : A[ i +1] = A[ i ] i = i 1 // i n s e r i s c e key A[ i +1] = key

1.2

Complessit` a e correttezza

Lalgoritmo di insertion sort considera con j lindice che contrassegna lelemento corrente da ordinare allinterno dellinsieme di elementi. In particolare si ha che alla j-esimo elemento tutti gli elementi precedenti, ossia quelli in A[1...j-1] sono gi` a ordinati e sono gli stessi elementi che erano contenuti tra la posizione 1 e la posizione j-1. Si formula dunque quella che viene chiamata invariante di ciclo dellalgoritmo: Tutti glie elementi A[1...j-1] sono ordinati e sono gli elementi che originariamente occupavano le posizioni da [1,j-1] Per validare la correttezza dellalgoritmo dobbiamo dimostrare tre cose sullinvariante dellalgoritmo: Inizializzazione: linvariante di ciclo risulta essere sempre vera per ogni iterazione iniziale del ciclo; Conservazione: se un invariante vale prima di una generica iterazione di ciclo, allora varr` a anche per literazione successiva Conclusione: viene sfruttata la combinazione tra linvariante e la condizione di terminazione dellalgoritmo per denire un importante propriet` a che dimostra la correttezza dellalgoritmo La dimostrazione di queste tre propriet` a corrisponde a gorsse linee alla dimostrazione di correttezza che viene fatta applicando il principio di induzione. La propriet` a 1 e 2 dimostrano che un invariante di ciclo ` e corretta sempre prima di uniterazione. La terza propriet` a invece dimostra la correttezza, dato che combina la condizione di terminazione con linvariante di ciclo per dedurre una propriet` a che verica la correttezza. Dunque ` e analoga al principio di induzione, se non per un fattore:

1.3. MERGESORT

Con il metodo di invariante di ciclo la correttezza ` e dimostrata per eetto della terminazione del ciclo, invece con linduzione si applica innitamente il passo induttivo per raggiungere prima o poi il passo base. Dimostriamo dunque tali passi per il caso dellinsertion sort: Inizializzazione:Al primo ciclo j = 2 dunque gli elementi da 1 a j-1, ossia la lista di un solo elemento ` e per denizione gi` a una lista ordinata. Conservazione: alla generica iterazione di ciclo abbiamo che tutti gli elementi A[j-1], A[j-2], ... A[1] sono gi` a ordinati e shiftati verso destra per far posto allelemento j-simo. DUnque dopo il ciclo si verica ancora linvariante di ciclo, ossia che tutti gli elementi sono ordinati e i j-1 elementi erano gli stessi che erano gi` a presenti in A. Conclusione: alla ne delle iterazioni di ciclo j = n+1, per cui tutti gli elementi da 1 a A.lenght sono ordinati. Dunque la lista ` e completamente ordinata e lalgoritmo ` e corretto.

1.3
1.3.1

Mergesort
Approccio divide et impera

Un altro approccio utilizzato, diversamente da quello ricorsivo ` e lapproccio divideet impera che si basa sulla suddivisione del problema originario in sottoproblemi dello stesso tipo. Lapproccio divide et impera si basa su tre propriet` a: Divide: il problema originario viene diviso in un problema di dimensione pi` u piccola ma comunque dello stesso tipo; Conservazione: i sottoproblemi sono risolti mediante un approccio ricorsivo e i problemi pi` u piccoli sono direttamente risolvibili; Conclusione: vengono combinati i risultati dei sottoproblemi per ricavare la soluzione del problema principale.

1.3.2

Procedura di MERGE

La procedura di MERGE ` e una procedura che agisce su n elementi per cui possiamo direttamente di re che ha complessit` a lineare con linput per cui T (n) = (n) (1.2)

e permette di fondere in maniera ordinata due sottoliste, presupponendo che tali sottoliste siano a loro volta ordinate. ANalizziamo lo pseudocodice della funzione di MERGE(A,p,q,r)

CAPITOLO 1. ITERAZIONE E RICORSIONE

f u n t i o n MERGE(A, p , q , r ) n 1 = q p +1 n 2 = r q S i c r e a n o due l i s t e L [ n 1 +1] e R[ n 2 + 1 ] // Riempimento for i in n 1 L [ i ] = A[ i ] for j in n 2 R[ j ] = A[ q+j ] // Aggiunta d e l l e s e n t i n e l l e L [ n 1 +1] = \ i n f R[ n 2 +1] = \ i n f // I n i z i a l i z z o i c o n t a t o r i i = 1 j = 1 f o r k in p to r : i f L [ i ] <= R[ j ] A[ k ] = L [ i ] i = i +1 else A[ k ] = R[ j ] j =j +1

Alle righe 1-2 sono calcolate le dimensioni dei due sottoarray e vengnono inizializzati i nuovi array alla riga 4. Una volta create le liste vengono riempite con gli elementi con i due cicli di righe 6-7 e 9-10. Vengono aggiunte poi le sentinelle. Le sentinelle sono un valore molto grande in modo tale che il confronto tra un valore e la sentinella da come risultato del confronto per minoranza sempre il valore. Vengono poi fuse le lise sulla base del confronto di riga 21. Se L[i] ` e minore di R[j] allora viene inserito l[i] e aggiornato il contatore della lista sinistra. Altrimenti si fa lo stesso sullaltra lista. La presenza delle sentinelle e lordinamento delle sottoliste comporta un inserimento diretto di tutti gli elementi quando una sentinella viene raggiunta, in quanto il confronto tra un valore di L o R e la sentinella fa fallire il controllo.

1.3. MERGESORT

1.3.3

Dimostrazione della correttezza

Si stabilisce dunque la seguente invariante di ciclo: Allinizio di ogni ciclo for il sottoarray A[p ... k-1] contiene i k-p elementi pi` u piccoli di L e R e L[i] e R[j] sono ancora gli elementi pi` u piccoli che non sono ancora stati inseriti in A Consideriamo dunque i tre casi dellinvariante: Inizializzazione: alla prima iterazione k = p per cui linsieme A non contiene ancora alcun elemento e L[i] e R[j] sono ancora gli elementi che non ancora sono stati inseriti in A; Conservazione: ad una generica iterazione k larray A contiene ancora i k-1 elemnti pi` u piccoli di L e R. Se L[i] R[j] allora linserimento di un nuovo elemento in A comporta che A ora contiene i k-p+1 elementi pi` u piccoli, ma la successiva iterazione ripristina linvariante di ciclo scorrendo L o R per cui L[i] e R[j] sono ancora i pi` u piccoli elementi ancora da inserire in A; Conclusione: alla ultima iterazione k = r per cui sono stati inseriti in A r-p+1 elementi. Tuttavia se sommiamo n1 e n2 otteniamo che la somma da r-p+3, ossia 2 elementi in pi` u che non sono stati inseriti in A e questi non sono altro che le due sentinelle. Si osserva come la funzione di merge agisce su n elementi per cui la complessit` a temporale ` e T (n) = (n) (1.3) Per dimostrarlo si pu` o considerare che i cicli interni operano o su tutto n oppure su n1 e n2 per cui la complessit` a` e necessariamente un T (n) = (n) . (1.4)

1.3.4

Mergesort

Mediante la funzione di MERGE(A,p,q,r) possiamo costruire la funzione MERGESORT(A,p,r).

Algoritmo 1.1: Pseudocodice della funzione MERGESORT f u n c t i o n MERGESORT(A, p , r ) i f p <= r q = f l o o r ( p+r ) / 2

10

CAPITOLO 1. ITERAZIONE E RICORSIONE

MERGESORT(A, p , q ) MERGESORT(A, q+1, r ) MERGE(A, p , q , r )