Ordinare F. Bombi
2 Liste ordinate Una lista di n oggetti confrontabili (a 0, a 1, a 2, … a n-1 ) si dice ordinata quando a i <= a i+1 per ogni i=0,… n-2 Per ordinare una lista si deve costruire una nuova lista permutando gli elementi in modo che sia soddisfatta la condizione indicata
Ordinare un array Considereremo inizialmente algoritmi che operano su dati contenuti in un array di n elementi oppure sui prima n elementi di un array di dimensioni maggiori L’algoritmo più semplice che si può proporre consiste nell’esaminare successivamente le n-1 coppie di elementi contigui e scambiarli quando il primo non sia inferiore o uguale al secondo L’intero processo deve essere ripetuto n-1 volte oppure sino a quando non è più necessario effettuare scambi Si può osservare che dopo la prima serie di scambi l’elemento più grande presente nell’array sarà con certezza all’ultimo posto, ad ogni successiva passata si può diminuire di 1 il numero di confronti
Analisi di bubblesort L’algoritmo appena descritto viene indicato come ordinamento per galleggiamento o bubblesort. Il numero di confronti necessari per ordinare un array di n elementi è pari a: (n-1)+(n-2)+…+2+1 = i=1,n-1 i= n(n-1)/2 Nel caso peggiore (quando si parte di un array ordinato in senso inverso) ad ogni confronto corrisponde uno scambio, questo rende l’algoritmo inutilmente inefficiente
Ordinamento per selezione Supponiamo di saper estrarre da un vettore l’elemento più piccolo presente (o il primo degli elementi più piccoli presenti) Possiamo utilizzare la selezione del minimo per realizzare un algoritmo di ordinamento pensando di utilizzare due vettori, il primo contiene i dati disordinati, nel secondo costruiamo la permutazione ordinata – Fino a che il primo vettore non è vuoto Selezionare il minimo Togliere il minimo dal primo vettore Inserire il minimo nel secondo vettore
Selezione 0 n Dati disordinati Vettore ordinato
Selezione sul posto In pratica non è necessario utilizzare due vettori. Al passo i-esimo si assume che il vettore sia diviso in due parti: una ordinata e l’altra disordinata; si assume inoltre che gli elementi nella parte ordinata siano minori o uguali degli elementi nella parte disordinata. La parte ordinata comprende i elementi, i restanti n-i elementi sono nella parte del vettore da ordinare Al passo i-esimo si seleziona l’elemento più piccolo nella parte disordinata dell’array e lo si inserisce alla fine della parte disordinata L’algoritmo termina quando i = n-1 All’inizio si avrà i = 0 in quanto la parte ordinata non contiene nessun elemento
Selezione sul posto 0 n-1 ordinatodisordinato v[k] <= v[j] i
Analisi di selezione int i = 0;1 while (i < (n-1))n { int piccolo = i;n-1 int j = i+1n-1 while(j < n)n-1, n-2,… 1 { if (v[j] < v[piccolo])n-2, n-3,… 0 piccolo = j; 0 x j++;n-2, n-3,… 0 } int temp = v[piccolo];n-1 v[piccolo] = v[i];n-1 v[i] = temp;n-1 i++n-1 }
Analisi di selezione Assumiamo che ogni istruzione venga eseguita in un tempo costante (indipendente da n). Abbiamo allora che, nel caso peggiore: t(n) = a + bn + c(n-1) + d i=1,n-1 i + e i=0,n-2 i = a+bn + c(n-1) + dn(n-1)/2 + e(n-1)(n-2)/2 = k 1 n 2 + k 2 n + k 3 Dove a, b, c, d, e sono costanti e K 1, k 2, k 3 sono costanti combinazione delle precedenti
Analisi di selezione Per ordinare n elementi – Si devono effettuare n-1 cicli, ogni ciclo comprende un confronto e uno scambio – Si devono effettuare n(n-1)/2 confronti – La sola istruzione piccolo = j; Viene eseguita un numero di volte dipendente dall’ordinamento iniziale dei dati Il tempo di esecuzione dipende asintoticamente da n 2 fatto che porta a dire che l’algoritmo ha una complessità temporale O(n 2 )
Notazione O-grande Siano f(n) e g(n) funzioni che mappano gli interi non negativi in numeri reali. Si dice che f(n) è O(g(n)) se esistono una costante reale c e un numero intero n 0 1 tali per cui sia f(n) cg(n) per ogni intero n n 0. Quando f(n) è O(g(n)) spesso si scrive impropriamente f(n) = O(g(n)) espressione che va letta “ f(n) è O-grande di g(n) ”
Un esempio n f(n) cg(n) n0n0 g(n) f(n) = O(g(n)) f(n) = a + bn g(n) = n