Università degli studi di Messina – Facoltà di Ingegneria Corso di Laurea in Ingegneria Informatica e delle Telecomunicazioni Fondamenti di Informatica II Prof. D. Bruneo Algoritmi di Ordinamento e di Ricerca Introduzione Ordinare una sequenza di informazioni significa effettuare una permutazione in modo da rispettare una relazione d’ordine tra gli elementi della sequenza (p.e. minore o uguale ovvero non decrescente) Input: una sequenza di n numeri < a1 , a2 ,..., an > Output: una permutazione degli n elementi < a1' , a2' ,..., an' > tale che, data una funzione di ordinamento f: f ( a1' ) ≤ f ( a2' ) ≤ ... ≤ f ( an' ) Fondamenti di Informatica II Prof. D. Bruneo 2 Importanza dell’ordinamento Uno dei maggiori problemi a cui fare fronte quando si manipolano grosse quantità di informazioni è quello relativo all’ordinamento ed al reperimento delle stesse Un buon ordinamento garantisce una maggiore facilità di ricerca di tali informazioni Sia il sistema operativo che i software applicativi devono continuamente effettuare ricerche su insiemi di informazioni e quindi l’efficienza degli algoritmi di ordinamento usati è un fattore critico per garantire le buone prestazioni del sistema Fondamenti di Informatica II Prof. D. Bruneo 3 Elemento di Informazione In genere tutti gli elementi di informazione della sequenza hanno la stessa struttura Le struttura dell’elemento è in genere complessa e viene vista come un insieme di campi di informazione Per esempio la struttura di un elemento della sequenza di elementi di una rubrica telefonica è: Struttura: nome - cognome - numero Fondamenti di Informatica II Prof. D. Bruneo 4 Campi chiave L’ordinamento di una sequenza viene fatto scegliendo almeno un campo, definito chiave, che è quello utilizzato per la ricerca nella sequenza. In pratica ricerchiamo le informazioni di tutto l’elemento utilizzando una parte nota di esso, la chiave È molto comune la ricerca per più di un campo (chiavi multiple) Le chiavi vanno scelte in modo da ridurre le possibili omonimie Ad esempio nella rubrica cerchiamo principalmente per cognome e poi per nome L’ordinamento è quindi spesso effettuato su più di un campo: chiave primaria, secondaria, ecc. Fondamenti di Informatica II Prof. D. Bruneo 5 Esempio 1. Rossi Paolo 090456789 2. Rossi Carlo 090435612 3. Bianchi Agata 090353678 Considerando lo scopo applicativo, la sequenza va ordinata per cognome e nome, in ordine non decrescente. Si ottiene così: 1. Bianchi Agata 090353678 2. Rossi Carlo 090435612 3. Rossi Paolo 090456789 Fondamenti di Informatica II Prof. D. Bruneo 6 Operazioni Elementari Si nota come siano necessarie operazioni di: Confronto Scambio Risulta inoltre intuitivo come possa essere necessario scandire più volte, magari su sottoinsiemi via via più piccoli la sequenza informativa Fondamenti di Informatica II Prof. D. Bruneo 7 Valutazione degli algoritmi di ordinamento I criteri generali per valutare un algoritmo di ordinamento sono: Complessità computazionale •Caso migliore •Caso medio •Caso peggiore Esibizione di un comportamento naturale Comportamento nel caso di elementi con chiave uguale (stabilità) Fondamenti di Informatica II Prof. D. Bruneo 8 Complessità computazionale È importante avere un indicatore di confronto tra i vari algoritmi possibili di ordinamento, indipendentemente dalla piattaforma hw/sw e dalla struttura dell’elemento informativo La complessità computazionale si basa sul numero di operazioni elementari necessarie Si misura come funzione del numero n di elementi della sequenza Gli algoritmi di ordinamento interno si dividono in: • Algoritmi semplici - complessità O(n2) • Algoritmi evoluti - complessità O(n*log(n)) Fondamenti di Informatica II Prof. D. Bruneo 9 Performance di esecuzione È sempre indipendente dalla piattaforma hw/sw, ma dipende dalla struttura dell’elemento informativo e dal numero di chiavi usate: ➔ ➔ Scambiare tra loro due integer a 32 bit è molto meno oneroso che scambiare due struct complesse Confrontare solo una chiave è meno oneroso che confrontare due chiavi Fondamenti di Informatica II Prof. D. Bruneo 10 Indici delle sequenze Per migliorare la performance di esecuzione è utile costruire un vettore ausiliare (indice) che contiene i puntatori agli elementi della sequenza. I confronti verranno fatti sempre sugli elementi della sequenza ma lo scambio viene fatto sulla sequenza dei puntatori Fondamenti di Informatica II Prof. D. Bruneo 11 Ordinamenti interni ed esterni Vi sono due diverse categorie di algoritmi di ordinamento: algoritmi che ordinano oggetti ad accesso casuale, come gli array, e algoritmi che ordinano oggetti sequenziali, quali file su disco. Si possono, quindi, distinguere: Ordinamenti interni: sono fatti su sequenze in memoria centrale Ordinamenti esterni: sono fatti su sequenze in memoria di massa Fondamenti di Informatica II Prof. D. Bruneo 12 Ipotesi semplificativa Supporremo che la sequenza di informazioni sia rappresentabile come vettore di n elementi, ovvero ogni elemento sia individuabile tramite un indice variabile da 0 a n-1. Gli elementi del vettore potranno essere tipi scalari (integrali o virgola mobile) o aggregati (struct) Il vettore può essere allocato staticamente o dinamicamente Fondamenti di Informatica II Prof. D. Bruneo 13 Classi di algoritmi di ordinamento Vi sono tre metodi generali per ordinare i vettori: scambio (bubble sort, quick sort) selezione (selection sort) inserimento (insertion sort, shell sort) Fondamenti di Informatica II Prof. D. Bruneo 14 Bubble Sort Si tratta di un algoritmo semplice. È un algoritmo di scambio. Il nome deriva dalla analogia dei successivi spostamenti che compiono gli elementi dalla posizione di partenza a quella ordinata simile alla risalita delle bolle di aria in un liquido. Il bubbling si può realizzare in molte versioni basate sullo stesso principio. Fondamenti di Informatica II Prof. D. Bruneo 15 Esempio passo 1 passo 2 3 1 9 3 5 9 Ad ogni passo si confronta l’ultimo REGOLA elemento con i precedenti scambiandolo nel caso in cui risulti minore 7 5 2 7 1 Si confronta il numero 1 con i precedenti. Essendo il più piccolo risalirà fino alla prima posizione 2 Si confronta il numero 2 con i precedenti (escluso il primo elemento) risalendo fino alla seconda posizione Si confronta il 7 con l’elemento precedente (5): essendo il 7>5 non viene effettuato lo scambio. Sarà invece il 5 a risalire fino alla quarta posizione passo 3 1 2 3 9 5 7 passo 4 1 2 3 5 9 7 passo 5 1 2 3 5 7 9 Fondamenti di Informatica II Si confronta il 7 con il 9 scambiando gli elementi A questo punto il vettore risulta ordinato Prof. D. Bruneo 16 Descrizione informale Si consideri un vettore di n elementi. Si vuole ordinare in ordine non decrescente Facciamo “risalire le bolle dal fondo” Sono necessarie diverse scansioni del vettore (iterazioni) Inizializziamo a 0 il flag ordinato (ipotizziamo il vettore disordinato) Scriviamo un ciclo for che controlla le n-1 iterazioni necessarie ma che termina se il flag ordinato è 1, con ciò indicando che la precedente iterazione intermedia ha già ordinato il vettore Fondamenti di Informatica II Prof. D. Bruneo 17 Descrizione informale (cont.) La prima iterazione (i=0) si applica a tutto il vettore (n elementi) e posiziona correttamente il primo elemento. La seconda iterazione si applica a tutto il vettore escluso il primo elemento (n-1 elementi). L’i-esima iterazione si applica al sottovettore residuo, in quanto i primi i elementi sono già stati ordinati. L’ultima iterazione (i=n-2) si applica agli ultimi due elementi del vettore. Se durante la generica iterazione c’è uno scambio, settiamo a 0 il flag ordinato, in modo che il for esterno che controlla le iterazioni sia informato che il vettore non può ancora essere considerato ordinato. Fondamenti di Informatica II Prof. D. Bruneo 18 Descrizione informale (cont.) In ogni scansione, iniziamo puntando l’indice all’ultimo elemento del vettore e lo confrontiamo col precedente. Se l’ultimo elemento è minore dobbiamo scambiarlo con il penultimo. Se c’è lo scambio, poniamo a 0 il flag ordinato (indichiamo così che c’e’ stato uno scambio ed il vettore non potrà essere considerato ordinato alla fine della iterazione corrente). Quindi il for interno di controllo verifica se deve fare un successivo confronto; in tal caso l’indice risale di una posizione. Per esempio nel secondo ciclo si confronta il penultimo con il terzultimo. Fondamenti di Informatica II Prof. D. Bruneo 19 Codice del Bubble Sort #include <stdio.h> #include <alloc.h> void scambia(int ve[], int i, int j) { int tmp=ve[i]; ve[i]=ve[j]; ve[j]=tmp; } Fondamenti di Informatica II void BubbleSort(int v[], int n) { int ordinato,i,j; ordinato=0; for (j=0;j<n-1 && !ordinato;j++) { ordinato=1; for (i=n-1;i>j;i--) { if (v[i]<v[i-1]) { scambia(v,i,i-1); ordinato=0; } } } } Prof. D. Bruneo 20 Codice del Bubble Sort (cont.) void main() { //algoritmo bubble sort //con allocazione dinamica di un vettore di //interi int n,i, *p; //acquisizione da tastiera del numero degli //elementi del vettore do { printf("Quanti elementi deve avere il vettore?:"); scanf("%d",&n); } while (n<2 || n>50); //allocazione degli n elementi del vettore p=(int*)malloc(n*sizeof(int)); //acquisizione degli elementi del vettore Fondamenti di Informatica II for (i=0;i<n;i++) { printf("Immetti il valore dell'elemento %d del vettore. V[%d]=",i,i); scanf("%d",p+i); } BubbleSort (p,n); //visualizza il vettore ordinato for (i=0;i<n;i++) printf("V[%d]=%d\n",i,*(p+i)); getchar(); } Prof. D. Bruneo 21 Complessità del Bubble Sort L’algoritmo BubbleSort esegue alla prima iterazione al più n-1 confronti/scambi. Alla seconda iterazione n-2 confronti/scambi Le iterazioni sono in totale al più n-1 Il numero totale al più di confronti/scambi è: (n-1)+(n-2)+…+1 ovvero: n−1 n−1∗n Kn=∑ i= 2 i=1 Fondamenti di Informatica II e quindi la complessità risulta: T n=O n2 Prof. D. Bruneo 22 Selection Sort Si tratta di un algoritmo semplice È un algoritmo di selezione Si seleziona l’elemento con il valore più basso e lo si scambia con il primo elemento Fra i rimanenti n-1 elementi si trova l’elemento con la chiave più piccola e lo si scambia con il secondo Si procede fino allo scambio degli ultimi due elementi Fondamenti di Informatica II Prof. D. Bruneo 23 Esempio Ad ogni passo si seleziona l’elemento REGOLA minore e lo si scambia con il primo elemento non ordinato passo 1 3 9 5 7 2 1 passo 2 1 9 5 7 2 3 passo 3 1 2 5 7 9 3 passo 4 1 2 3 7 9 5 Si seleziona l’elemento minore (il sesto che ha valore 1) e lo si scambia con l’elemento nella prima posizione Si seleziona (tra tutti gli elementi escluso il primo) l’elemento minore (il 2) e lo si scambia con l’elemento in seconda posizione Si seleziona tra i 4 elementi rimasti il più piccolo (il 3) e lo si scambia con l’elemento in terza posizione Si seleziona il 5 e lo si scambia con il 7 passo 5 1 2 3 5 9 7 Si scambiano gli ultimi due elementi passo 6 1 2 Fondamenti di Informatica II 3 5 7 9 A questo punto il vettore risulta ordinato Prof. D. Bruneo 24 Codice del Selection Sort #include <stdio.h> #include <alloc.h> void main() { int n,i, *p; //acquisizione da tastiera del numero degli //elementi del vettore do { printf("Quanti elementi deve avere il vettore?:"); scanf("%d",&n); } while (n<2 || n>50); //allocazione degli n elementi del vettore dall'heap p=(int*)malloc(n*sizeof(int)); //acquisizione degli elementi del vettore void SelectionSort(int *v, int dim) { int i,j,k,elem; int scambia; for (i=0;i<dim-1;i++) { scambia=0; k=i; elem=v[i]; for (j=i+1;j<dim;j++) { if (v[j]<elem) { k=j; elem=v[j]; scambia=1; } } if(scambia){ v[k]=v[i]; v[i]=elem; }}} Fondamenti di Informatica II for (i=0;i<n;i++) { printf("Immetti il valore dell'elemento %d del vettore. V[%d]=",i,i); scanf("%d",p+i); } SelectionSort (p,n); //visualizza il vettore ordinato for (i=0;i<n;i++) printf("V[%d]=%d\n",i,*(p+i)); getchar(); } Prof. D. Bruneo 25 Complessità del Selection Sort Il ciclo esterno verrà eseguito n-1 volte Il ciclo interno viene eseguito una media di ½ n volte Il risultato è che l’algoritmo di selezione richiede ½ (n2-n) selezioni/scambi quindi: T n=O n2 Il tempo di esecuzione dipende solo in modo modesto dal grado di ordinamento della struttura Nonostante il numero di confronti sia uguale al numero di confronti effettuati nel Bubble Sort, il numero di scambi dell’algoritmo Selection Sort risulta essere molto inferiore; ciò lo rende preferibile nel caso di ordinamento di strutture estremamente grandi con chiavi molto piccole. Fondamenti di Informatica II Prof. D. Bruneo 26 Insertion Sort Si tratta di un algoritmo semplice È un algoritmo di inserimento L’algoritmo ordina innanzitutto i primi due elementi dell’array Quindi si inserisce il terzo elemento nella posizione corretta rispetto ai primi due elementi Il processo continua fino all’inserimento (e quindi all’ordinamento) di tutti gli elementi Fondamenti di Informatica II Prof. D. Bruneo 27 Esempio Si ordinano i primi due elementi REGOLA dopodiché si inseriscono ad uno ad uno gli altri in maniera ordinata passo 1 3 9 5 7 2 1 passo 2 3 9 5 7 2 1 passo 3 3 5 9 7 2 1 3 5 7 9 2 1 passo 4 Si ordinano i primi due elementi che in tal caso risultano già ordinati Si seleziona il terzo elemento (il 5) e lo si inserisce in maniera ordinata nel vettore composto dai primi due elementi Si seleziona il quarto elemento (il 4) e lo si inserisce in maniera ordinata nel vettore composto dai primi tre elementi Si inserisce il quinto elemento passo 5 2 3 5 7 9 1 Si inserisce l’ultimo elemento passo 6 1 2 Fondamenti di Informatica II 3 5 7 9 A questo punto il vettore risulta ordinato Prof. D. Bruneo 28 Codice dell’Insertion Sort void main() { int n,i, *p; //acquisizione da tastiera del numero degli //elementi del vettore do { printf("Quanti elementi deve avere il vettore?:"); scanf("%d",&n); } while (n<2 || n>50); //allocazione degli n elementi del vettore dall'heap p=(int*)malloc(n*sizeof(int)); //acquisizione degli elementi del vettore #include <stdio.h> #include <alloc.h> void InsertionSort(int *v, int dim) { int i,j,elem; for (i=1;i<dim;i++) { elem=v[i]; for (j=i-1;(j>=0) && (elem<v[j]);j--) v[j+1]=v[j]; v[j+1]=elem; } } Fondamenti di Informatica II for (i=0;i<n;i++) { printf("Immetti il valore dell'elemento %d del vettore. V[%d]=",i,i); scanf("%d",p+i); } InsertionSort (p,n); //visualizza il vettore ordinato for (i=0;i<n;i++) printf("V[%d]=%d\n",i,*(p+i)); getchar(); } Prof. D. Bruneo 29 Complessità dell’Insertion Sort A differenza del Bubble Sort e del Selection Sort, il numero di confronti che avvengono con l’Insertion Sort dipende dal livello di ordinamento iniziale del vettore. Se il vettore è ordinato, il numero di confronti è pari a n-1, altrimenti i confronti sono dell’ordine di n2 In generale, nei casi peggiori, l’Insertion Sort, non è più efficiente del Bubble Sort e del Selection Sort, mentre nei casi medi è solo leggermente più veloce Nonostante il numero di confronti (in alcuni casi) sia molto basso gli elementi del vettore devono essere traslati ogniqualvolta che un elemento viene inserito nella posizione corretta. Ciò rende il numero di spostamenti molto alto quindi: T n=O n2 Fondamenti di Informatica II I vantaggi dell’Insertion Sort sono dovuti al fatto che esso si comporta in maniera naturale (manipola di più i vettori disordinati e di meno quelli ordinati). Esso va quindi usato nel caso di elenchi quasi ordinati. Prof. D. Bruneo 30 Shell Sort Si tratta di un algoritmo evoluto Deve il suo nome al suo ideatore D. L. Shell È un algoritmo di inserimento Il metodo di ordinamento si basa sulla riduzione degli incrementi Si confrontano tutti gli elementi che si trovano ad una distanza d e si continua riducendo il valore di d fino ad arrivare agli elementi adiacenti (d=1) Fondamenti di Informatica II Prof. D. Bruneo 31 Esempio REGOLA confronti passo 1 3 9 5 7 2 1 scambi Si confrontano gli elementi distanti d, scambiandoli nel caso non siano ordinati. Quindi vengono ordinati gli elementi diminuendo il valore di d fino ad arrivare ad 1. In questo esempio si sono scelti valori di d pari a: 3,2,1 Si confrontano gli elementi distanti tre posizioni scambiandoli nel caso il primo sia maggiore del secondo passo 2 3 2 1 7 9 5 Si confrontano gli elementi distanti 2 posizioni (3 - 1 - 9 e 2 - 7 - 5) riordinandoli (1 - 3 - 9 e 2 - 5 - 7) passo 3 1 2 3 5 9 7 Adesso si riduce la distanza ad uno e si confrontano gli elementi adiacenti, eventualmente scambiandoli passo 4 1 2 3 5 7 9 A questo punto il vettore risulta ordinato Fondamenti di Informatica II Prof. D. Bruneo 32 Considerazioni Sebbene lo Shell Sort sia facile da capire intuitivamente, una sua analisi formale risulta difficile In particolare, la valutazione dei valori ottimali della distanza d (detta spaziatura) sfugge ai teorici Si possono usare diverse spaziature per implementare lo Shell Sort. Di solito si ordina l’array con una spaziatura grande, si riduce la spaziatura, e si riordina l’array L’unico vincolo da rispettare è che nell’ultimo passo la spaziatura valga uno Ad esempio, la sequenza 9,5,3,2,1 funziona molto bene Sono da evitare le sequenze formate dalle potenze di 2 che, per complessi motivi matematici, riducono l’efficienza dell’algoritmo (pur conservandone l’efficacia) Fondamenti di Informatica II Prof. D. Bruneo 33 Codice dello Shell Sort #include <stdio.h> #include <alloc.h> void ShellSort(int * vett, int dim) { int i,j,gap,k; int x, a[5]; a[0]=9;a[1]=5;a[2]=3;a[3]=2;a[4]=1; for (k=0;k<5;k++){ gap=a[k]; for(i=gap;i<dim;i++){ x=vett[i]; for(j=i-gap;(x<vett[j]) && (j>=0); j=j-gap) vett[j+gap]=vett[j]; vett[j+gap]=x; } } } Fondamenti di Informatica II void main() { int n,i, *p; //acquisizione da tastiera del numero degli //elementi del vettore do { printf("Quanti elementi deve avere il vettore?:"); scanf("%d",&n); } while (n<2 || n>50); //allocazione degli n elementi del vettore dall'heap p=(int*)malloc(n*sizeof(int)); //acquisizione degli elementi del vettore for (i=0;i<n;i++) { printf("Immetti il valore dell'elemento %d del vettore. V[%d]=",i,i); scanf("%d",p+i); } ShellSort (p,n); //visualizza il vettore ordinato for (i=0;i<n;i++) printf("V[%d]=%d\n",i,*(p+i)); getchar(); } Prof. D. Bruneo 34 Complessità dello Shell Sort L’algoritmo Shell Sort risulta essere migliore, in termini di prestazioni, degli algoritmi semplici (Bubble Sort, Selection Sort, Insertion Sort) Intuitivamente, tale miglioramento deriva dal fatto che lo Shell Sort sposta velocemente gli elementi nelle loro destinazioni La complessità media è O(n1.25), mentre quella del caso peggiore diventa O(n1.5) quindi: Fondamenti di Informatica II T n=O n1,2 mediamente T n=O n1,5 caso peggiore Prof. D. Bruneo 35 Quick Sort Si tratta di un algoritmo evoluto che ha complessità computazionale O(n)=n*log(n) È un algoritmo di scambio È un algoritmo ricorsivo Ricordiamo che la ricorsione consiste nell’esprimere F(n) in funzione di F(n-1) ed inoltre nel conoscere il valore iniziale F(0) Gli algoritmi ricorsivi sono più semplici ed eleganti, ma la loro esecuzione comporta, a causa della annidarsi della funzione che si richiama da se un uso a volte esagerato dello stack È anche disponibile un’implementazione in ANSI-C di qsort, una funzione C standard di libreria che viene tipicamente implementata con il quicksort. Le chiamate ricorsive sono state sostituite da operazioni dirette sullo stack Fondamenti di Informatica II Prof. D. Bruneo 36 Approccio informale Si consideri un vettore di n elementi e lo si ordini con algoritmi semplici, con un tempo di calcolo proporzionale a n2. Si supponga, invece di dividere il vettore da ordinare in due sottovettori di n/2 elementi ciascuno e di ordinare le due metà separatamente. Applicando sempre gli algoritmi non evoluti, si avrebbe un tempo di calcolo pari a (n/2)2 + (n/2)2=n2/2. Se riunendo i due sottovettori ordinati si potesse riottenere il vettore originario tutto ordinato avremmo dimezzato il tempo di calcolo Se questo ragionamento si potesse applicare anche immaginando una decomposizione del vettore originario in quattro, si avrebbe un tempo di calcolo totale pari a: (n/4)2+(n/4)2+(n/4)2+(n/4)2=n2/4 Se si potesse dividere in 8, si avrebbe un tempo ancora più basso, e così via dicendo. Fondamenti di Informatica II Prof. D. Bruneo 37 Descrizione L’algoritmo Quick Sort si basa sull’idea delle partizioni. La procedura generale consiste nella selezione di un valore (detto pivot) e nella suddivisione del vettore in due sezioni. Tutti gli elementi maggiori o uguali al valore del pivot andranno da una parte e tutti i valori minori dall’altra. Questo processo viene ripetuto per ognuna delle sezioni rimanenti fino all’ordinamento dell’intero vettore. Fondamenti di Informatica II Prof. D. Bruneo 38 Esempio REGOLA pivot i 3 passo 1 7 pivot i passo 2 5 3 2 4 j 1 j 9 9 sezione 1 passo 3 1 2 j 7 5 sezione 2 3 4 5 7 Si sceglie il quarto elemento (valore 4 come elemento pivot 2 pivot i 4 1 9 Si seleziona l’elemento pivot e si spostano gli elementi più piccoli alla sua sinistra e i più grandi alla sua destra. Si suddivide, quindi, il vettore in due sezioni e si procede ricorsivamente Si seleziona, partendo dall’estremità sinistra, il primo elemento maggiore o uguale del pivot e, partendo dall’estremità destra, il primo elemento minore o uguale del pivot. Dopodiché si scambiano e si continua fino alla scansione di tutti gli elementi (i<=J) Si divide il vettore in due sezioni e si procede ricorsivamente sulle due sezioni scegliendo gli elementi pivot Si scorrono gli elementi delle due sezioni selezionando e scambiando gli elementi che risultano maggiori (da sinistra) e minori (da destra) dei rispettivi pivot A questo punto il vettore risulta ordinato Fondamenti di Informatica II Prof. D. Bruneo 39 Considerazioni L’esempio precedente si riferisce al caso migliore che avviene quando la scelta dell’elemento pivot ricade sull’elemento mediano del vettore comportando una suddivisione del vettore in sezioni di pari dimensioni Il caso peggiore avviene quando il vettore viene decomposto in due sottovettori, di cui il primo ha dimensione uguale alla dimensione originaria meno 1, e l’altro ha una dimensione unitaria. Il pivot coincide con l’elemento massimo del vettore La scelta dell’elemento pivot risulta, quindi, essere determinante Se si fosse in grado di risalire all’elemento mediano la scelta ricadrebbe su di esso. Normalmente tale operazione comporta una conoscenza a priori sul vettore o un’analisi opportuna il cui tempo deve essere preso in considerazione Il metodo più usato rimane quello della scelta casuale dell’elemento pivot, selezionando, ad esempio, l’elemento che occupa la posizione centrale Fondamenti di Informatica II Prof. D. Bruneo 40 Esempio - caso peggiore i Se scegliamo come pivot l’elemento di posto centrale (indice m=(inf+sup)/2), ovvero il 34, questo, casualmente, coincide con l’elemento maggiore del vettore. pivot 13 20 1 15 34 28 21 14 29 3 pivot 13 20 1 15 3 28 i 21 14 29 34 j L’indice i viene incrementato fino a quando non viene trovato un elemento più grande o uguale al pivot. Nel nostro esempio l’indice i si arresta in corrispondenza del pivot. L’esempio mette in evidenza il motivo di incrementare l’indice i fino a quando si trova un elemento più grande o uguale al pivot. Se non ci fosse la condizione uguale, nel nostro esempio l’indice i verrebbe continuamente incrementato oltre la dimensione del vettore. Per quanto riguarda l’indice j esso non viene spostato in quanto l’elemento j-esimo è inferiore al pivot. Gli elementi di indice i e j vengono scambiati, e l’indice i viene incrementato, mentre j viene decrementato. L’indice i viene quindi fatto incrementare fino a quando arriva all’elemento 34, che è pari al pivot. L’indice j non viene fatto decrementare perché si riferisce ad un elemento già inferiore al pivot. 13 20 Siccome i > j, la prima passata è finita: otteniamo le seguenti sezioni Fondamenti di Informatica II 1 15 3 28 sezione 1 21 14 29 34 sezione 2 Prof. D. Bruneo 41 Esempio - caso peggiore (cont.) Come si vede l’esempio considerato rappresenta un caso peggiore, perché il vettore originario è stato decomposto in due vettori di cui il primo (quello compreso tra inf e j) ha dimensione quasi uguale a quella originaria. E’ chiaro che la complessità di riordino del primo sottovettore è praticamente la stessa di quella relativa al riordino del vettore originario. Dunque non si è avuto alcun vantaggio nel suddividere il vettore. Fondamenti di Informatica II Prof. D. Bruneo 42 Codice del Quick Sort int main(){ int partition(int v[], int l, int r){ int i=l-1,j=r; int pivot=v[r]; //si piglia come elemento pivot // l'ultimo elemento for(;;){ while(v[++i]<pivot) ; while(v[--j]>pivot) if(j==l) break; if(i>=j) break; scambia(v,i,j); } scambia(v,i,r); //mette l'elemento pivot // nella giusta posizione return i; } int n,i, *p; //acquisizione da tastiera del numero degli //elementi del vettore do{ printf("Quanti elementi deve avere il vettore?:"); scanf("%d",&n); } while (n<2 || n>50); //allocazione degli n elementi del vettore dall'heap p=(int*)malloc(n*sizeof(int)); //acquisizione degli elementi del vettore for (i=0;i<n;i++){ printf("Immetti il valore dell'elemento %d del vettore. V[%d]=",i,i); scanf("%d",p+i); } quickSort (p,0,n-1); void quickSort(int v[], int l, int r){ int i; if(r<=l) return; i=partition(v,l,r); quickSort(v,l,i-1); quickSort(v,i+1,r); } Fondamenti di Informatica II //visualizza il vettore ordinato for (i=0;i<n;i++) printf("V[%d]=%d\n",i,*(p+i)); getchar(); } Prof. D. Bruneo 43 Complessità del Quick Sort Nel caso migliore, siccome l’array viene diviso in due ad ogni passo, e l’algoritmo deve comunque esaminare tutti gli n elementi, il tempo di esecuzione risulta O(n log(n)). Nel caso peggiore ogni chiamata ricorsiva a quicksort ridurrebbe solo di un’unità la dimensione dell’array da ordinare. Sarebbero quindi necessarie n chiamate ricorsive per effettuare l’ordinamento, portando a un tempo di esecuzione di O(n2). Una soluzione a questo problema si può ottenere scegliendo a caso un elemento come pivot. Questo renderebbe estremamente improbabile il verificarsi del caso peggiore. quindi: T n=O nlog 2 n T n=O n2 Fondamenti di Informatica II caso migliore e caso medio caso peggiore (estremamente raro) Prof. D. Bruneo 44 Quick Sort -analisi rigorosa L’algoritmo è costituito da alcune assegnazioni, un ciclo for e due chiamate ricorsive. Il ciclo for viene eseguito n +1 volte, quindi con un costo O(n). Se n=1 la funzione costo è una costante. Se n>1 bisogna considerare il costo delle chiamate ricorsive. O (1) T( n ) = O(n) + T(k) + T(n - k) Fondamenti di Informatica II n =1 n >1 Prof. D. Bruneo 45 Quick Sort -analisi rigorosa (cont.) Si ha quando il pivot divide l’insieme degli elementi in due parti: una composta da un solo elemento e l'altra dagli n-1 restanti. Caso peggiore T( n ) = O(n) + T (1) + T( n − 1) = = O( n ) + O (1) + T (n-1) = = O(n) + O(1) + O(n - 1) + O (1) + T (n- 2) = = O ( n) + O(1) + O ( n − 1) + O(1) + O(n - 2) + O (1) + T( n-3) generalizz ando : k T( n) = T(n - k) + ∑ O(n - i + 1) i =1 La ricorsione si chiude quando k=n-1. In questo caso, infatti, l'argomento di T() sarà pari ad uno e arriveremo al caso banale T(1)=O(1), quindi: n -1 T( n ) = T(1) + ∑ O(n - i + 1) = i =1 n = O ∑ (n - i + 1) = i =1 1 = O n (n + 1) = O( n 2 ) 2 Fondamenti di Informatica II Prof. D. Bruneo 46 Quick Sort -analisi rigorosa (cont.) Caso migliore Si ha quando il pivot divide l’insieme degli elementi in due parti uguali. n n T( n ) = O(n) + T + T = 2 2 n n = O( n ) + 2O + 2T = 4 2 n n n = O(n) + 2O + 2 O + 2T = 8 4 2 n = O( n ) + O ( n ) + O ( n) + 8T 8 generalizz ando : k n T( n) = 2 T k + ∑ O(n) 2 i =1 La ricorsione si chiude quando n=2k. In questo caso, infatti, l'argomento di T() sarà pari ad uno e arriveremo al caso banale T(1)=O(1), quindi: k T( n ) = nT(1) + log2 n ∑ O(n) = i =1 = O( n ) + O ( n log 2 n ) = O ( n log 2 n ) Fondamenti di Informatica II Prof. D. Bruneo 47 Quick Sort -analisi rigorosa (cont.) Tutti gli elementi possono essere presi come pivot con probabilità 1/n. Anche la generica suddivisione i, n-i avviene con probabilità 1/n. Caso medio 1 n −1 1 n −1 T( n ) = O(n) + ∑ T(i ) + ∑ T( n − i ) n i =1 n i =1 1 n −1 = O( n ) + ∑ [ T(i ) + T (n − i) ] = n i =1 sottraendo membro a membro: nT(n) = (n + 1)T (n − 1) + 2O(n ) dividendo entrambi i membri per n(n+1): 2 n −1 = O( n ) + ∑ T(i ) n i =1 T(n) T(n - 1) 2 = + = n +1 n O(n + 1) T(n - 2) 2 2 + + = n -1 O( n) O( n + 1) [...] moltiplicando entrambi i membri per n si ottiene: = n −1 nT (n ) = nO(n) + 2∑ T (i ) i =1 n T(2) n 2 1 n1 = +∑ ≅ 2∑ ≅ 2 ∫ dx = 2 ln( n) 3 i= 3 i + 1 i =1 i 1 x che scritta per n-1 diventa: n −2 (n - 1)T ( n - 1) = (n −1) O(n - 1) + 2∑ T (i ) quindi si ottiene: i =1 Fondamenti di Informatica II T (n ) = O(n ln(n )) Prof. D. Bruneo 48 Merge Sort Si tratta di un algoritmo evoluto che ha complessità computazionale O(n)=n*log(n) anche nel caso peggiore A differenza del Quick Sort è un algoritmo stabile È un algoritmo ricorsivo Si basa sul principio “divide et impera” sfruttando il concetto di fusione (merging) di array ordinati Fondamenti di Informatica II Prof. D. Bruneo 49 Il merging a 2 vie - esempio A(N) 3 B(M) 5 7 9 7 9 1 4 8 4 8 REGOLA Ad ogni passo si seleziona l'elemento più piccolo tra i due elementi di posto inferiore degli array e si inserisce nell'array di uscita 5 7 9 4 8 1 3 5 7 1 3 4 9 Fondamenti di Informatica II 8 1 3 7 9 4 5 8 9 1 3 4 5 passo 7 1 passo 4 5 passo 5 3 passo 6 passo 3 passo 2 passo 1 C(N+M) 1 3 4 5 7 8 9 8 7 9 1 3 4 5 7 8 Prof. D. Bruneo 50 Il merging a 2 vie – codice Tale implementazione necessita di un terzo array (di dimensione pari alla somma delle dimensioni degli array di partenza) per contenere l'output. void mergeAB(int c[], int a[], int N, int b[], int M){ int i,j,k; for(i=0,j=0,k=0;k<N+M;k++){ if(i==N){ c[k]=b[j++]; continue; } if(j==M){ c[k]=a[i++]; continue; } c[k] = (a[i]<b[j]) ? a[i++] : b[j++]; } } Fondamenti di Informatica II Prof. D. Bruneo 51 Merging astratto sul posto Tale implementazione utilizza ancora un array ausiliario di dimensione proporzionale all'output, ma è più efficiente perchè evita di effettuare i test sulla fine degli array. Per fare ciò il secondo array viene trascritto in maniera inversa alla fine del primo. void merge(int a[], int l, int m, int r){ int i,j,k,*aux; aux=(int*)malloc((r-l+1)*sizeof(int)); for(i=m+1;i>l;i--) aux[i-1]=a[i-1]; for(j=m;j<r;j++) aux[r+m-j]=a[j+1]; for(k=l;k<=r;k++) if(aux[j]<aux[i]) a[k]=aux[j--]; else a[k]=aux[i++]; } Fondamenti di Informatica II Prof. D. Bruneo 52 Merge Sort - descrizione REGOLA Per ordinare un dato array è sufficiente dividerlo in due, ordinare (ricorsivamente) le due metà e fondere le sequenze ordinate risultanti. La condizione di uscita della ricorsione si ha quando gli array hanno una dimensione pari a uno. 3 9 3 9 3 3 9 5 5 7 7 2 3 9 5 1 8 4 9 3 5 1 5 5 7 3 7 7 7 9 4 2 2 2 1 1 5 1 1 1 2 8 4 8 4 8 2 4 8 8 4 4 divisione Fondamenti di Informatica II 2 7 8 9 fusione Prof. D. Bruneo 53 Codice del Merge Sort int main(){ int n,i, *p; //acquisizione da tastiera del numero degli //elementi del vettore do{ printf("Quanti elementi deve avere il vettore?:"); scanf("%d",&n); } while (n<2 || n>50); //allocazione degli n elementi del vettore dall'heap p=(int*)malloc(n*sizeof(int)); //acquisizione degli elementi del vettore for (i=0;i<n;i++){ printf("Immetti il valore dell'elemento %d del vettore. V[%d]=",i,i); scanf("%d",p+i); } mergeSort (p,0,n-1); void mergeSort(int a[], int l, int r){ if(r<=l) return; int m=(r+l)/2; mergeSort(a,l,m); mergeSort(a,m+1,r); merge(a,l,m,r); } //visualizza il vettore ordinato for (i=0;i<n;i++) printf("V[%d]=%d\n",i,*(p+i)); getchar(); } Fondamenti di Informatica II Prof. D. Bruneo 54 Proprietà del Merge Sort Il Merge Sort richiede all'incirca Nlog2N confronti per ordinare un qualunque file di N elementi Il Merge Sort utilizza uno spazio ausiliario proporzionale a N Il Merge Sort è stabile, se il merging su cui si basa è stabile Le risorse di tempo e spazio impiegate dal Merge Sort non dipendono dall'ordinamento iniziale del file di input Fondamenti di Informatica II Prof. D. Bruneo 55 Ordinamento di strutture complesse Finora si è parlato solo dell’ordinamento di array di interi. Ovviamente è possibile ordinare array di un qualunque tipo di dati, semplicemente cambiando il tipo dei parametri e delle variabili della funzione di ordinamento I programmi applicativi che richiedono un ordinamento, in genere, organizzano gruppi di dati più complessi Ad esempio gli elenchi di indirizzi, gli archivi per inventari e le registrazioni contengono raccolte di dati che, nei programmi C, vengono normalmente raccolte all’interno di strutture Anche se in genere una struttura contiene numerosi membri, deve essere ordinata sulla base di un solo membro utilizzato come chiave dell’ordinamento Ad eccezione della scelta della chiave, anche per l’ordinamento di strutture si impiegano le tecniche già viste per gli altri tipi di dati Fondamenti di Informatica II Prof. D. Bruneo 56 Algoritmi di ordinamento esterno L’algoritmo di ordinamento si complica notevolmente quando Memoria centrale si trattano strutture dati Alg. ord. complesse e articolate, quali file o archivi. Il problema è legato alla File f dimensione, in termini di occupazione di memoria, della struttura in questione: il metodo f ordinato f non ordinato più semplice, efficace e veloce per ordinare tale struttura è trasferirla interamente in File f memoria e ivi ordinarla, ma spesso le dimensioni non consentono questo tipo di Memoria di massa operazione. Fondamenti di Informatica II Prof. D. Bruneo 57 KeySort Una tecnica che consente, in alcuni casi, di superare il problema è quella del keysort. Essa consiste nel creare una struttura in memoria, tipicamente un vettore, contenente il campo chiave del record che costituisce l’unità di informazione. Inoltre bisogna memorizzare la posizione iniziale del record all’interno del file. L’ordinamento verrà fatto in memoria su tale struttura ed infine le modifiche verranno riportate nel file. Key Pos 1 2 3 4 5 6 7 8 9 10 File f disordinato Key KeySort Pos 3 7 5 8 1 9 2 4 6 10 File f ordinato Memoria di massa Fondamenti di Informatica II Memoria centrale Prof. D. Bruneo 58 KeySort: valutazioni Non sempre questa tecnica risolve il problema: ➔ ➔ ➔ nei casi in cui il record è composto dalla sola chiave, non si trae alcun vantaggio utilizzando il keysort, anzi, la struttura in memoria centrale è più pesante di quella in memoria di massa, dovendo memorizzare l’informazione supplementare relativa alla posizione del record nel file; la tecnica si rivela insufficiente anche quando, pur trattandosi di record complessi e strutturati, il vettore chiavi-indici assume una dimensione tale da non poter essere contenuta in memoria; altro problema è relativo alla scrittura del file ordinato: il metodo più semplice implica la creazione di un nuovo file nel quale scrivere gli elementi secondo l’ordine specificato nel vettore; ciò non sempre è possibile limitatamente alle capacità del dispositivo di memorizzazione di massa. L’alternativa consiste nel leggere un dato file, ricercarlo nel vettore in memoria centrale, risalire alla nuova posizione attraverso il campo pos, leggere dal file l’elemento nella posizione in cui andrà scritto il primo dato (pos) e dunque riscriverlo nella nuova posizione. Tutto ciò si traduce in un notevole dilatamento dei tempi di esecuzione. Fondamenti di Informatica II Prof. D. Bruneo 59 Sort Merge La soluzione ai problemi elencati, è, come anticipato, quella di scomporre il file in un certo numero di parti, da ordinare in memoria centrale, e dunque fondere tali parti ordinate in un unico file ordinato. La tecnica utilizzata è nota in letteratura col nome Sort Merge, che, non a caso, richiama alla memoria l’algoritmo di ordinamento Merge Sort, dal quale si ispira: la differenza è che nel secondo caso si suddivide il vettore fino ad arrivare a vettori di un solo elemento e solo allora comincerà l’operazione di fusione tra questi, mentre nell’algoritmo Sort Merge la suddivisione del file produrrà un certo numero di piccoli sottoinsiemi di n elementi detti run, che verranno ordinati in memoria centrale e dunque fusi. file run Fondamenti di Informatica II Prof. D. Bruneo 60 Sort Merge bilanciato a P vie Si supponga di avere: N record da ordinare su un dispositivo esterno Spazio in memoria centrale per memorizzare M record 2P dispositivi esterni a disposizione durante l'ordinamento Assegniamo l'etichetta 0 al dispositivo esterno contenente l'input e le etichette 1, 2, ..., 2P-1agli altri dispositivi. L'obiettivo dell'algoritmo è quello di riscrivere i record nel dispositivo 0, in modo ordinato. Fondamenti di Informatica II Prof. D. Bruneo 61 L’algoritmo 1. Il file iniziale viene suddiviso fra i dispositivi di input P, P+1, ..., 2P -1, in blocchi ordinati di M record ciascuno (tranne eventualmente il blocco finale, che sarà più piccolo se N non è multiplo di M). 2. Dopo questa fase di distribuzione, il numero di blocchi ordinati su ciascun dispositivo è pari a N/(MP) arrotondato all'intero precedente o successivo. 3. Nel primo passaggio si considerano i dispositivi da P a 2P-1 come dispositivi di input e quelli da 0 a P-1come dispositivi di output. 4. Si esegue un merging a P vie per fondere i blocchi ordinati di dimensione M sui dispositivi di input in blocchi ordinati di dimensione PM, e quindi si distribuiscono fra i dispositivi di output. 5. Dopo questa fase, il numero di blocchi ordinati su ciascun dispositivo sarà N/(P2 M) 6. Si itera il processo eseguendo un secondo passaggio di merging considerando i dispositivi da 0 a P-1 come dispositivi di input e quelli da P a 2P-1 come dispositivi di output. 7. Continuando in questo modo, andando avanti e indietro fra i dispositivi 0, ..., P-1 e i dispositivi P, ..., 2P-1, si aumenta la dimensione dei blocchi di un fattore P fino a ottenere, prima o poi, un solo blocco ordinato sul dispositivo 0 o sul dispositivo P. Fondamenti di Informatica II Prof. D. Bruneo 62 Esempio 0 3 4 5 0 1 2 P=3 M=3 N=45 asortingandmergingexamplewithfortyfiverecords aos dmn aex fht erv irt egr lmp ort ceo 3 aadeeegggiiilmmnnnoprrstwx 4 cdeeffhioorrrsttvy agn gin eiw fiy drs aaginorst ffhiortty 0 aacddeeeeeffggghiiiilmmnnnoooprrrrrsstttvwxy deggimnnr cdeeorrsv aeeilmpwx Fondamenti di Informatica II Prof. D. Bruneo 63 Caso ideale Ciascun file (dispositivo esterno) contiene un run È sufficiente solo una merge phase Sfortunatamente è di difficile realizzazione • Ci vorrebbero tanti file quanti sono i run, ma poiché il numero di file gestibili da programma è limitato, la condizione non sempre è realizzabile. Fondamenti di Informatica II Prof. D. Bruneo 64 Complessità Al fine di calcolare la complessità degli algoritmi di ordinamento esterno si assume che il costo delle operazioni di read e write sui dispositivi esterni sia molto maggiore rispetto alle operazioni primitive eseguite in memoria centrale. Quindi viene totalmente ignorato il costo di un ordinamento se è eseguito interamente nella memoria centrale. Avendo 2P dispositivi esterni e memoria centrale sufficiente a ospitare M record, un Sort Merge basato su un merge bilanciato a P vie richiede all'incirca un numero di passaggi pari a: 1log p N / M Un passaggio è richiesto per la distribuzione sui dispositivi. Se N=MPK, i blocchi sono tutti di dimensione MP dopo la prima fusione , MP2 dopo la seconda, MP3 dopo la terza, e così via. L'ordinamento si completa dopo k=logP(N/M) passaggi. Altrimenti, se MPK-1<N<MPK , l'effetto di blocchi incompleti o vuoti rende i blocchi di dimensione molto variabile verso la fine del processo. Comunque, il processo termina sempre dopo k=logP(N/M) passaggi. Fondamenti di Informatica II Prof. D. Bruneo 65 Complessità (cont.) Ad esempio, se vogliamo ordinare 1 miliardo di record usando 6 dispositivi e memoria interna sufficiente a contenere 1 milione di record, possiamo eseguire un Sort Merge a 3 vie per un totale di 8 passaggi sui dati (1 per la distribuzione iniziale e log31000=7 per il merging). Avremo sequenze ordinate di 1 milione di record dopo il passo di distribuzione iniziale, di 3 milioni di record dopo la prima fusione, di 9 milioni di record dopo la seconda fusione, di 27 milioni di record dopo la terza fusione, ecc. In pratica la decisione più importante da prendere nel Sort Merge riguarda la scelta del valore P, cioè il numero di vie del merging. Accesso sequenziale -> P deve essere pari alla metà dei dispositivi Accesso non sequenziale -> è possibile aumentare P diminuendo il numero di passi, ma ciò farà crescere il numero di accessi Fondamenti di Informatica II Prof. D. Bruneo 66 Sort Merge polifase Svantaggio del merging bilanciato a P vie: usa attivamente solo circa la metà dei dispositivi durante il merging ➔ L'idea di base del Sort Merg polifase è quella di distribuire i blocchi ordinati prodotti dalla selezione con sostituzione in modo un pò disuguale fra i dispositivi a disposizione (lasciandone uno vuoto), e quindi di applicare una strategia del tipo “fondi finchè non è vuoto” 0 1 2 3 4*1 6*1 2*1 17*1 7*1 3*1 1*1 4*3 2*3 1*3 2*5 1*5 1*9 1*17 Fondamenti di Informatica II Prof. D. Bruneo 67 Sort Merge polifase (cont.) Si dimostra che l'efficienza dell'algoritmo è maggiore se la distribuzione dei blocchi ordinati avviene secondo la distribuzione di Fibonacci: 1,1,2,3,5,8,13,21, ... Tale metodo consente di eseguire lo stesso lavoro con circa la metà dell'hardware. Se il numero di dispositivi esterni è fissato, il merging polifase risulta sempre più efficiente del merging bilanciato. ➔ Fondamenti di Informatica II Prof. D. Bruneo 68 Ricerca I database consentono ad un utente di ricercare un record sulla base di una chiave Per ricercare le informazioni in una struttura dati (ad esempio un array) esistono due metodi a seconda che la struttura dati sia ordinata o no Ricerca sequenziale: opera su strutture dati non ordinate Ricerca binaria : opera su strutture dati ordinate I compilatori C forniscono la funzione bsearch() nell’ambito delle funzioni di libreria standard Fondamenti di Informatica II Prof. D. Bruneo 69 Ricerca sequenziale Per trovare le informazioni in un array non ordinato è necessario eseguire una ricerca sequenziale che parte dal primo elemento e termina nel momento in cui viene trovata una corrispondenza o alla fine dell’array Questo metodo deve essere necessariamente utilizzato su tutti i dati non ordinati ma può essere impiegato anche quando i dati sono ordinati int sequential_search (int * v, int dim, int key){ int i; for(int i=0;i<dim;i++) if (key==v[i]) return i; return -1; /*elemento non trovato*/ } Fondamenti di Informatica II Prof. D. Bruneo 70 Tempo di Ricerca della Ricerca Sequenziale Nel caso migliore, la ricerca sequenziale, deve verificare un solo elemento e nel caso peggiore deve controllare tutti gli n elementi È facile comprendere che una ricerca sequenziale richiederà, in media, il controllo di n/2 elementi. quindi: n T n=O 2 Fondamenti di Informatica II mediamente Prof. D. Bruneo 71 Ricerca Binaria Se i dati sono ordinati la ricerca può essere eseguita impiegando un metodo migliore Si controlla l’elemento centrale Se è maggiore rispetto alla chiave si eseguirà la ricerca sulla prima metà del vettore se no sulla seconda Si deve ripetere questa procedura fino a trovare l’elemento o finché non vi saranno più elementi da cercare Esempio Si vuole trovare il 4 nell’array seguente 1 2 3 4 1 2 3 4 4 Fondamenti di Informatica II 5 6 7 8 9 Si legge il valore centrale (5) e poiché risulta maggiore della chiave (4) si continua la ricerca sulla prima metà Ora l’elemento centrale è 3 che risulta minore della chiave e quindi la prima metà viene scartata La ricerca continua e viene trovato l’elemento cercato Prof. D. Bruneo 72 Codifica della Ricerca Binaria int binary_search (int * v, int dim, int key){ int low,high,mid; low=0; high=dim-1; while(low<=high){ mid=(low+high)/2; if(key<v[mid]) high=mid-1; else if (key>v[mid]) low=mid+1; else return mid; /*trovato*/ } return -1; /*elemento non trovato*/ } Per applicare questa funzione ad altre strutture di dati basta modificare la parte di confronto della routine Fondamenti di Informatica II Prof. D. Bruneo 73 Tempo di Ricerca della Ricerca Binaria Nella ricerca binaria il numero di confronti nel caso peggiore è pari a: log2n In un caso medio il numero di confronti sarà minore Nel caso migliore è richiesto un solo confronto quindi: T n=O log 2 n Fondamenti di Informatica II caso peggiore Prof. D. Bruneo 74