Algoritmi di ordinamento q Selection Sort q Quick

  • Slides: 25
Download presentation
Algoritmi di ordinamento q Selection Sort q Quick Sort q Lower bound alla complessità

Algoritmi di ordinamento q Selection Sort q Quick Sort q Lower bound alla complessità degli algoritmi di ordinamento Ordinamento 1

Selection Sort Selection. Sort(dati[]) { for (i=0; i<dati. length-1; i++) { min = <Seleziona

Selection Sort Selection. Sort(dati[]) { for (i=0; i<dati. length-1; i++) { min = <Seleziona min. in dati[i], …. , dati[dati. length-1]> <Scambia min con dati[i]; } } q L’elemento minimo viene messo in posizione 0 q Si itera il procedimento sulle posizioni successive Ordinamento 2

Selection Sort/2 Selection. Sort(dati[], i) { min = <Seleziona min. in dati[i], …. ,

Selection Sort/2 Selection. Sort(dati[], i) { min = <Seleziona min. in dati[i], …. , dati[dati. length-1]> <Scambia min con dati[i]; Selection. Sort(dati[], i+1) ; } …… Selection. Sort(dati[], 0) ; q Versione ricorsiva Ordinamento 3

Selection Sort/3 Ordinamento del vettore di interi {5, 2, 3, 8, 1} Ordinamento 4

Selection Sort/3 Ordinamento del vettore di interi {5, 2, 3, 8, 1} Ordinamento 4

Come ordinare oggetti diversi da numeri q Ordinare un vettore i cui elementi sono

Come ordinare oggetti diversi da numeri q Ordinare un vettore i cui elementi sono oggetti complessi. Es. oggetti della classe: class Persona { String cognome; String CF; public Persona (String cognome, String CF) { this. cognome = cognome; this. CF = CF; } } q Come ordinare un array di tali oggetti rispetto al cognome ? Ordinamento 5

Come ordinare oggetti diversi da numeri/2 q Occorre: 1. Dichiarare che tra gli oggetti

Come ordinare oggetti diversi da numeri/2 q Occorre: 1. Dichiarare che tra gli oggetti della classe (Persona nell’esempio) è definito un ordinamento 2. Dichiarare rispetto a quale o a quali membri della classe è definito l’ordinamento (il cognome nel nostro caso) 3. Definire la regola che stabilisce l’ordinamento tra due oggetti della classe (nel nostro caso: due oggetti di tipo persona sono ordinati alfabeticamente secondo i rispettivi cognomi) q In C++ si possono sovraccaricare gli operatori q In Java si può dichiarare che la classe (Persona) implementa l’interfaccia Comparable (non è la sola possibilità) Ordinamento 6

Come ordinare oggetti diversi da numeri/3 q Il passo 1 si traduce così: class

Come ordinare oggetti diversi da numeri/3 q Il passo 1 si traduce così: class Persona implements Comparable { …… } q I passi 2 e 3 consistono nell’implementare l’unico metodo previsto dall’interfaccia Comparable: int compare. To(Object o) q compare. To definisce le regole che stabiliscono l’ordinamento tra oggetti della classe (nel nostro caso, l’ordinamento è quello alfabetico sui cognomi) Ordinamento 7

Come ordinare oggetti diversi da numeri/4 q Quindi: class Persona implements Comparable { String

Come ordinare oggetti diversi da numeri/4 q Quindi: class Persona implements Comparable { String cognome; String CF; public Persona (String cognome, String CF) { this. cognome = cognome; this. CF = CF; } public int compare. To (Object pers) { return cognome. compare. To(((Persona)pers). cognome); } } Nota: occorre fare il cast perché compare. To vuole un Object Ordinamento 8

Selection Sort/4 public void selectionsort(Comparable[] data) { int i, j, least; for (i =

Selection Sort/4 public void selectionsort(Comparable[] data) { int i, j, least; for (i = 0; i < data. length-1; i++) { for (j = i+1, least = i; j < data. length; j++) if (data[j]. compare. To(data[least]) < 0) least = j; swap(data, least, i); /* Scambia gli oggetti in pos. i e least */ } } Es. : versione ricorsiva Ordinamento 9

Quick Sort quicksort(array[]) { if (array. length>1) { Scegli bound; /* subarray 1 e

Quick Sort quicksort(array[]) { if (array. length>1) { Scegli bound; /* subarray 1 e subarray 2 */ while (ci sono elementi in array) if (generico elemento < bound) inserisci elemento in subarray 1; else inserisci elemento in subarray 2; quicksort(subarray 1); quicksort(subarray 2); } } Ordinamento 11

Quick Sort/2 Array < bound subarray 2 subarray 1 >= bound < bound 2

Quick Sort/2 Array < bound subarray 2 subarray 1 >= bound < bound 2 < bound 1 >= bound 2 Ordinamento 12

Partizionamento dell’array [8 5 4 7 6 1 6 3 8 12 10] con

Partizionamento dell’array [8 5 4 7 6 1 6 3 8 12 10] con quicksort Ordinamento 13

Partizionamento dell’array [8 5 4 7 6 1 6 3 8 12 10] con

Partizionamento dell’array [8 5 4 7 6 1 6 3 8 12 10] con quicksort Ordinamento 14

Quick Sort/3 void quicksort(Comparable[] data, int first, int last) { int lower = first

Quick Sort/3 void quicksort(Comparable[] data, int first, int last) { int lower = first + 1, upper = last; swap(data, first, (first+last)/2); /* Così, in pratica è spesso più veloce */ Comparable bound = data[first]; while (lower <= upper) { while (data[lower]. compare. To(bound) < 0) lower++; while (bound. compare. To(data[upper]) < 0) upper--; if (lower < upper) swap(data, lower++, upper--); else lower++; /* 1 */ } /* End while */ swap(data, upper, first); // Alla fine upper punta sempre a un elemento <= bound if (first < upper-1) /* se first == upper-1 il sottoarray ha solo 2 elementi ed è ordinato */ quicksort(data, first, upper-1); if (upper+1 < last) quicksort(data, upper+1, last); 15 Ordinamento }

Quick Sort/4 void quicksort(Comparable[] data) { if (data. length < 2) return; int max

Quick Sort/4 void quicksort(Comparable[] data) { if (data. length < 2) return; int max = 0; /* Trova max. e mettilo alla fine; serve per evitare che lower cresca oltre la dim. dell’ array (non è detto che accada ma può succedere) */ for (int i = 1; i < data. length; i++) if (data[max]. compare. To(data[i]) < 0) max = i; swap(data, data. length-1, max); // Elemento piu’ grande in posizione finale quicksort(data, 0, data. length-2); } Ordinamento 16

Analisi del Quick Sort q Costo = O(No. confronti) q Costo O(n 2) nel

Analisi del Quick Sort q Costo = O(No. confronti) q Costo O(n 2) nel caso peggiore q Costo O(n log n) nel caso migliore e medio q In pratica l’algoritmo è efficiente q Scelta pivot fondamentale Ordinamento 17

Quick Sort – Caso peggiore No. confronti per sotto-array n-1 n-2 Array n-1 volte

Quick Sort – Caso peggiore No. confronti per sotto-array n-1 n-2 Array n-1 volte 2 1 L’elemento di pivot è sempre il minimo Costo = O(n-1+n-2+. . . +2+1) = O(n 2) Ordinamento 18

Quick Sort – Caso migliore No. confronti per sotto-array n potenza di 2 per

Quick Sort – Caso migliore No. confronti per sotto-array n potenza di 2 per semplicità Array n-1 n/2 -1 n/4 -1 log n+1 volte 2 1 Costo = Ordinamento 19

Efficienza algoritmi di ordinamento q Merge Sort (e Heap Sort): O(n log n) q

Efficienza algoritmi di ordinamento q Merge Sort (e Heap Sort): O(n log n) q Quick Sort, Selection Sort, Insertion Sort: O(n 2) q Quick Sort: O(n log n) nel caso migliore q Selection Sort: O(n 2) in tutti i casi q Insertion Sort: O(n) nel caso migliore q Domanda: qual è l’efficienza massima (complessità minima) ottenibile nel caso peggiore -> Lower bound Ordinamento 20

Ordinamento – limiti inferiori q Osservazione fondamentale: tutti gli algoritmi devono q q confrontare

Ordinamento – limiti inferiori q Osservazione fondamentale: tutti gli algoritmi devono q q confrontare elementi Dati ai, ak, tre casi possibili: ai < ak, ai > ak, oppure ai=ak Si assume per semplicità che tutti gli elementi siano distinti Si assume dunque che tutti i confronti abbiano la forma ai < ak, e il risultato del confronto sia vero o falso Nota: se gli elementi possono avere lo stesso valore allora si considerano solo confronti del tipo ai <= ak Ordinamento 21

Alberi di decisione Albero di decisione per Insertion Sort sull’insieme {a 1, a 2,

Alberi di decisione Albero di decisione per Insertion Sort sull’insieme {a 1, a 2, a 3} a 1: a 2 < < a 2: a 3 > a 1, a 2, a 3 < a 1, a 3, a 2 > < a 1: a 3 > a 1: a 3 a 2, a 1, a 3, a 1, a 2 > < a 2: a 3 a 2, a 3, a 1 > a 3, a 2, a 1 q Un albero di decisione rappresenta i confronti eseguiti da un algoritmo su un dato input q Ogni foglia corrisponde ad una delle possibili permutazioni Ordinamento 22

Alberi di decisione/2 Albero di decisione per Insertion Sort sull’insieme {a 1, a 2,

Alberi di decisione/2 Albero di decisione per Insertion Sort sull’insieme {a 1, a 2, a 3} a 1: a 2 < < a 2: a 3 > a 1, a 2, a 3 < a 1, a 3, a 2 > < a 1: a 3 > a 1: a 3 a 2, a 1, a 3, a 1, a 2 > < a 2, a 3, a 1 a 2: a 3 > a 3, a 2, a 1 q Vi sono n! possibili permutazioni -> l’albero deve contenere n! foglie q L’esecuzione di un algoritmo corrisponde ad un cammino sull’albero di decisione corrispondente all’input considerato Ordinamento 23

Alberi di decisione/3 q Riassumendo: § Albero binario § Deve contenere n! foglie q

Alberi di decisione/3 q Riassumendo: § Albero binario § Deve contenere n! foglie q Il più lungo cammino dalla radice ad una foglia (altezza) rappresenta il No. confronti che l’algoritmo deve eseguire nel caso peggiore q Teorema: qualunque albero di decisione che ordina n elementi ha altezza Ω(n log n) q Corollario: nessun algoritmo di ordinamento ha complessità migliore di Ω(n log n) Nota: esistono algoritmi di ordinamento con complessità più bassa, ma richiedono informazioni aggiuntive Ordinamento 24

Dimostrazione teorema 1. Un albero di decisione è binario 2. Albero binario di altezza

Dimostrazione teorema 1. Un albero di decisione è binario 2. Albero binario di altezza h non ha più di 2 h foglie 1 1=21 -1 2 2= 22 -1 3 4= 23 -1 h 2 h-1 3. Dobbiamo avere: 2 h-1 > No. foglie = n! 4. h-1 > log(n!) Ordinamento 25

Dimostrazione teorema/2 5. n! > (n/e)n (approssimazione di Stirling) 6. h-1 > log(n/e)n =

Dimostrazione teorema/2 5. n! > (n/e)n (approssimazione di Stirling) 6. h-1 > log(n/e)n = n log(n/e) = n logn – n loge = Ω(n log n) q Corollario: gli algoritmi Merge Sort e Heap Sort hanno complessità asintotica ottima Ordinamento 26