Ricerche ed Ordinamenti Ricerca sequenziale Due fra i problemi classici dell'informatica sono: trovare il miglior metodo di ricerca di uno o più elementi all'interno di una successione di valori; disporre secondo un certo ordinamento (ascendente o discendente) una successione di elementi. Per risolvere questi problemi sono stati sviluppati molti algoritmi, divenuti di utilizzo comune e talvolta inclusi nelle stesse librerie dei linguaggi di programmazione. Ricerche-ordinamenti Prof. Paolo Michelini Ricerca sequenziale in un array Supponiamo di avere un array con N valori (es: N=7) A = [ 1, 5, -4, 34, 9, 9, 77 ] Vogliamo trovare l’algoritmo che ricerchi un certo valore all’interno dell’array assegnato. In questo caso il metodo consiste nello scorrere gli elementi dell’array (ad esempio partendo dal primo per arrivare all’ultimo o viceversa) e verificare ad ogni passo se il valore cercato coincide con quello dell’array (ricerca sequenziale) Nel caso peggiore sono necessari N passi per determinare se l’elemento è presente o meno nel vettore NB: il valore potrebbe essere presente più volte nell’array. L’algoritmo dato verifica solamente che il valore cercato sia presente almeno una volta. Ricerche-ordinamenti Prof. Paolo Michelini Programma di ricerca sequenziale Traduzione Matlab del DF precedente: dato l’array A con N valori ed un valore dato a terminale il programma si ferma al I valore trovato ( es: A = [ 1, 3, -6, 8, 7, 24 ]; ) N = length ( A ); % la funzione length(A) ritorna il numero di elementi i = 1; % del vettore A val = input ('dai il valore da cercare: '); %NB in Matlab non c'è l'iterazione di tipo "repeat" while ( i < N + 1 ) if ( A ( i ) == val ) disp ( 'trovato valore in posizione: '); disp ( i ); return; % fa uscire il programma al I valore trovato end; i = i + 1; end; disp ('non ho trovato il valore '); Ricerche-ordinamenti Prof. Paolo Michelini Ricerche-ordinamenti Prof. Paolo Michelini Altra ricerca nell’array Ricerca di quanti valori uguali a quello dato ci sono nel vettore. Altro programma di ricerca Utilizzo la metafora dell’ufficio dove sul modulo d’ingresso ho: • valore da cercare • numero elementi del vettore • i valori del vettore Traduzione Matlab del DF precedente: dato l’array A con N valori ed un valore da ricercare dato a terminale, il programma trova tutti i valori pari a quello dato ( es: A = [ 1, 3, -6, 8, 7, 7, 24 ]; ) i = 1; nval = 0; N = length ( A ); val = input ('dai il valore da cercare: '); %NB in Matlab non c'è l'iterazione di tipo "repeat" while ( i <= N ) if ( A ( i ) == val ) nval = nval + 1; end; i = i + 1; end; fprintf ('I valori trovati sono %d\n', nval); Ricerche-ordinamenti Prof. Paolo Michelini Ricerca binaria (o dicotomica) Ricerche-ordinamenti Prof. Paolo Michelini Ricerca binaria Supponiamo ora di avere un array ORDINATO (in modo crescente o decrescente). In questo caso l’algoritmo di ricerca può essere raffinato. Il metodo più semplice consiste dal cominciare la ricerca non dal primo valore, ma da quello centrale, cioè a metà del vettore. A questo punto si confronta l'elemento con quello della nostra ricerca. Se dobbiamo cercare un valore che sta nella seconda metà dell’array, si elimina dalla ricerca in maniera automatica la prima metà (e viceversa). La ricerca continua poi nello stesso modo, eliminando di volta in volta metà dell’array rimasto, fino all’ultimo confronto che ci darà l'informazione richiesta, o fino a scoprire che l'elemento non si trova nel vettore. Anche in questo caso, se il valore cercato è presente piu’ volte nell’array, l’algoritmo ne determina solo la sua presenza o meno. La ricerca binaria non usa mai più di logN + 1 confronti per determinare se un elemento è presente o meno nel vettore (complessità dell’algoritmo) La ricerca dicotomica richiede un accesso casuale ai dati in cui cercare. Ricerche-ordinamenti Prof. Paolo Michelini Ricerche-ordinamenti Prof. Paolo Michelini Programma di ricerca binaria Traduzione Matlab del DF precedente: ricerca in un vettore ordinato assegnato di “mx” valori (es: A = [ 2, 4, 8, 9, 15, 16 ];) mn = 1; mx = length ( A ); while ( mn <= mx ) m = ( mn + mx ) / 2 ; %prendo la parte intera del valore m tramite la funzione fix m = fix (m); if ( A ( m ) == val ) fprintf ( 'Trovato valore in posizione %d\n', m ); return; else if ( A ( m ) < val ) mn = m + 1; else mx = m - 1; end; end; end; Prof. Paolo Michelini Bubble sort i = 1; nval = 0; val = input ('dai il valore da cercare: '); Ricerche-ordinamenti Ordinamento (sort) Problema: dato un insieme di elementi, ordinarlo secondo una relazione d’ordine (tipicamente in modo crescente o decrescente). L’ordinamento (sort) semplifica gli algoritmi di ricerca, e la manipolazione dei dati nel loro complesso Esistono molti algoritmi d’ordinamento più o meno efficienti. In generale la bontà di un algoritmo è misurata attraverso un indice della sua complessità, normalmente indicato con Ω o O (big O) Si può dimostrare che: Il limite inferiore di complessità per qualsiasi algoritmo di ordinamento che si basa sul paragone di coppie di chiavi (per confronto) è pari a Ω(NlogN), dove N è il numero di elementi da ordinare. Ricerche-ordinamenti Bubble sort Il nome dell'algoritmo è dovuto al fatto che, durante l'applicazione del procedimento, i valori vengono spostati all'interno dell'array più o meno velocemente come le bolle (bubble) in un bicchiere Ha una complessità computazionale dell'ordine di O(n2) Esempio: ordinamento della serie 16 8 15 2 4 9 16 8 15 2 4 9 8 16 15 2 4 9 8 15 16 2 4 9 8 15 2 16 4 9 8 15 2 4 16 9 8 15 2 4 9 16 8 2 4 9 15 16 2 4 8 9 15 16 2 4 8 9 15 16 2 4 8 9 15 16 I=1 I=2 I=3 I=4 I=5 I=6 Prof. Paolo Michelini START MAX N I1 Prima passata 5 scambi F STOP MAX > 1 V F I < MAX V A(I) > A( I+ 1 ) Seconda passata n-2 confronti 3 scambi Terza passata n-3 confronti 2 scambi Quarta passata 0 scambi Quinta passata 0 scambi V TMP A ( I ) A ( I ) A( I+ 1 ) A ( I + 1 ) TMP F II+1 MAX MAX - 1 I 1 Ricerche-ordinamenti Prof. Paolo Michelini Ricerche-ordinamenti Prof. Paolo Michelini Programma di bubble sort Ordinamento di un vettore assegnato con “mx” elementi ( es: A = [ 16, 8, 15, 2, 4, 9, ]; ) mx = length ( A ); i = 1; while ( mx > 1 ) while ( i < mx ) if ( A ( i ) > A ( i + 1 ) ) tmp = A ( i ); A ( i ) = A ( i + 1 ); A ( i + 1 ) = tmp; end; i = i + 1; end; mx = mx - 1; i = 1; end; Ricorsione La ricorsione è una tecnica di programmazione molto potente ed è particolarmente efficace per eseguire dei compiti ripetitivi su un set di variabili. Un algoritmo ricorsivo richiama sé stesso generando una sequenza di chiamate che ha termine al verificarsi di una condizione particolare che viene chiamata condizione di terminazione, che in genere si ha con particolari valori di ingresso. L’esempio più classico è il calcolo del fattoriale di un numero in cui: 0! = 1 n! = n*(n-1)*…*2*1 per n>0 Quindi per n>1 si avrà: Fatt (n) = n * Fatt (n-1) disp ( A ); Ricerche-ordinamenti Prof. Paolo Michelini Merge sort I Fase: dividi Prof. Paolo Michelini Merge sort in pratica Il merge sort è un algoritmo di ordinamento che consiste nella suddivisione del problema in sottoproblemi via via più piccoli. Il merge sort opera quindi dividendo l'insieme da ordinare in due metà e procedendo all'ordinamento delle medesime ricorsivamente. Quando si sono divise tutte le metà si procede alla loro fusione (merge appunto) costruendo un insieme ordinato L’ordinamento semplifica gli algoritmi di ricerca, e la manipolazione dei dati nel loro complesso Ha una complessità computazionale dell'ordine di O(n log n) Ricerche-ordinamenti L'insieme di elementi viene diviso in 2 metà. Se l'insieme è composto da un numero dispari di elementi, viene diviso in 2 sottogruppi dei quali il secondo ha un elemento in meno del primo (Es. 7 => 5 e 6) II Fase: impera Supponendo di avere due sequenze già ordinate. Per unirle, l'algoritmo merge sort estrae ripetutamente il minimo delle due sequenze in ingresso e lo pone in una sequenza in uscita Ricerche-ordinamenti Prof. Paolo Michelini Ricerche-ordinamenti Prof. Paolo Michelini Merge sort (pseudocodice) Merge ( VETT_A, p, q, r) i = p; j = q + 1; k = 0; while ( I <=q && j <= r ) if ( VETT_A ( i ) < VETT_A ( j ) ) VETT_B ( k ) = VETT_A ( i ); i = i + 1; else VETT_B ( k ) = VETT_A ( j ); j = j + 1; end; k = k + 1; end; while ( i <= q ) VETT_B ( k ) = VETT_A ( i ); i = i + 1; k = k + 1; end; while ( j <= r ) VETT_B ( k ) = VETT_A ( j ); j = j + 1; k = k + 1; end; for k=p:k <= r VETT_A ( k ) = VETT_B ( k - p ); end; Ricerche-ordinamenti * * Funzione ricorsiva MergeSort. */ MergeSort ( vett_A, p, r ) if ( p < r ) / q = ( p + r ) / 2; MergeSort ( vett_A, p, q ); MergeSort ( vett_A, q + 1, r ); Merge ( vett_A, p, q, r ); end; /* * Funzione principale */ main leggi_array ( V ); MergeSort ( V, 1, n ); end; Prof. Paolo Michelini