booble bubble
Transcript
booble bubble
2 Algoritmi di ordinamento Algoritmi Ver. 2.4 Lo scopo è ordinare in senso [de]crescente il contenuto di un vettore di N elementi senza utilizzare un secondo vettore Esiste molta letteratura scientifica a riguardo e molti metodi adatti a vari casi, ma qui si considerano tre semplici algoritmi di esempio molto per l’ordinamento in senso crescente (o meglio, non-decrescente): Selection sort Bubble sort Insertion sort © 2010 - Claudio Fornaro - Corso di programmazione in C 3 Selection sort semplificato - I Si confronta il primo elemento del vettore con tutti gli altri, man mano che si trova un valore minore del primo, lo si scambia con il primo. Dopo questa operazione il valore minimo è nella prima posizione è il successivo a 0 (pos. 0) del vettore for (j= 1; j<N; j++) if (v[j] < v[0]) 5 7 5 4 2 6 { tmp = v[j]; v[j] = v[0]; 4 7 5 5 2 6 v[0] = tmp; } 2 7 5 5 4 6 4 Selection sort semplificato - II Se si ripete lo stesso identico procedimento per tutti gli elementi a partire dal secondo, si determina il secondo valore più piccolo e lo si colloca al secondo posto è il successivo a 1 for (j= 2; j<N; j++) if (v[j] < v[1]) 2 7 5 5 4 6 { tmp = v[j]; v[j] = v[1]; 2 5 7 5 4 6 v[1] = tmp; } 2 4 7 5 5 6 5 Selection sort semplificato - III Se si ripete lo stesso identico procedimento per tutti gli elementi a partire dall’i-esimo, si determina l’i-esimo valore più piccolo e lo si colloca all’i-esimo posto 6 Selection sort semplificato -IV è il successivo a i Se si ripete questo procedimento per tutti i valori di i da 0 fino al penultimo (l’ultimo va a posto da sé) si ottiene l’ordinamento in senso crescente di tutto il vettore for (i=0; i<N-1; i++) for (j=i+1; j<N; j++) if (v[j] < v[i]) { tmp = v[j]; v[j] = v[i]; v[i] = tmp; } for (j=i+1; j<N; j++) if (v[j] < v[i]) { tmp = v[j]; v[j] = v[i]; v[i] = tmp; } 7 Selection sort - I 8 Selection sort - II Il primo passo è quello di individuare il minimo tra gli elementi del vettore e scambiarlo con quello nella prima posizione, il primo valore è ora al posto giusto è il successivo a 0 jmin = 0; for (j= 1; j<N; j++) if (v[j] < v[jmin]) jmin = j; 5 7 5 1 4 3 tmp = v[jmin]; v[jmin] = v[0]; v[0] = tmp; 1 7 5 5 4 3 Se si ripete lo stesso identico procedimento per tutti gli elementi a partire dal secondo, si determina il secondo valore più piccolo e lo si colloca al secondo posto è il successivo a 1 jmin = 1; for (j= 2; j<N; j++) if (v[j] < v[jmin]) jmin = j; 1 7 5 5 4 3 tmp = v[jmin]; v[jmin] = v[1]; v[1] = tmp; 1 3 5 5 4 7 9 Selection sort - III 10 Selection sort - IV Se si ripete lo stesso identico procedimento per tutti gli elementi a partire dall’i-esimo, si determina l’i-esimo valore più piccolo e lo si colloca all’i-esimo posto è il successivo a i jmin = i; for (j=i+1; j<N; j++) if (v[j] < v[jmin]) jmin = j; tmp = v[jmin]; v[jmin] = v[i]; v[i] = tmp; Se si ripete questo procedimento per tutti i valori di i da 0 fino al penultimo (l’ultimo va a posto da sé) si ottiene l’ordinamento in senso crescente di tutto il vettore for (i=0; i<N-1; i++) { jmin = i; for (j=i+1; j<N; j++) if (v[j] < v[jmin]) jmin = j; tmp = v[jmin]; v[jmin] = v[i]; v[i] = tmp; } 11 Bubble sort - I 12 Bubble sort - II Se si scorrono tutti gli elementi di un vettore e ogni volta che si trovano due valori ADIACENTI non in ordine (il più piccolo dei 2 a destra del più grande) li si scambia: il più grande di tutti risale a destra 3 1 5 7 4 3 for (j=0; j<N-1; j++) if (v[j] > v[j+1]) 1 3 5 7 4 3 { tmp = v[j]; 1 3 5 4 7 3 v[j] = v[j+1]; v[j+1] = tmp; } 1 3 5 4 3 7 Ripetendo N-1 volte questa operazione, tutti i valori risalgono verso destra fino ad occupare la posizione corretta e quindi vengono ordinati in senso crescente for (i=0 ; i<N-1; i++) for (j=0; j<N-1; j++) if (v[j] > v[j+1]) { tmp = v[j]; v[j] = v[j+1]; v[j+1] = tmp; } 13 Bubble sort - III 14 Bubble sort - IV Inefficienza: gli ultimi valori vengono in ogni caso confrontati, anche quando sono già stati collocati; per evitare perdita di tempo in questi controlli inutili si ferma prima della fine il ciclo interno, sfruttando il ciclo esterno for (i=N-1; i>0 ; i--) for (j=0; j<i ; j++) if (v[j] > v[j+1]) { tmp = v[j]; v[j] = v[j+1]; v[j+1] = tmp; } Inefficienza: se pochi valori sono fuori posto e l’ordinamento si ottiene prima delle N-1 passate, i cicli continuano ad essere eseguiti. Lo si fa terminare se non ci sono stati scambi scambi = SI; for (i=N-1; i>0 && scambi ;i--) { scambi = NO; for (j=0; j<i ; j++) continua solo if (v[j] > v[j+1]) se ci sono { scambi = SI; stati scambi tmp = v[j]; v[j] = v[j+1]; v[j+1] = tmp; } } 15 Insertion sort - I Insertion sort - II Per ciascuno degli elementi a partire dal 2o (l’elemento da sistemare si chiama chiave): si copia il valore della chiave in una variabile (key) si scalano a destra di una posizione tutti gli elementi precedenti alla chiave finché non ne viene trovato uno con valore inferiore a key 4. al posto di quest’ultimo viene messo key Notare che gli elementi a sinistra della chiave sono sempre già ordinati in senso crescente grazie alle passate precedenti 3 2 1. 2-3. 1 5 7 3 4 8 key 4 3 1 16 1 3 5 7 4 8 ordinati for (j=1; j<N; j++) { key = v[j]; for (i=j-1; i>=0 && v[i]>key; i--) v[i+1] = v[i]; v[i+1] = key; } 17 Esercizi 1. 2. 3. 18 Algoritmi di ricerca Per ciascuno degli algoritmi di ordinamento precedentemente descritti (variazioni incluse), si scriva un programma completo che ordini in senso crescente (o meglio, non-decrescente) un vettore di N numeri interi. Si misurino i tempi di esecuzione usando la funzione clock() in <time.h> Si vuole cercare un dato valore val in un vettore vett di N elementi Si possono considerare i due casi: vettore non ordinato vettore ordinato Per ciascuno degli algoritmi di ordinamento precedentemente descritti (variazioni incluse), si scriva un programma completo che ordini in senso decrescente (o meglio, noncrescente) un vettore di N numeri interi. 19 20 Ricerca in vettore non ordinato Ricerca in vettore non ordinato Si deve scorrere tutto il vettore in quanto val può essere in qualsiasi posizione for (i=0; i<N && vett[i]!=val; i++) ; if (i == N) printf("Non trovato\n"); else printf("Trovato\n"); Il ciclo termina in 2 casi: Deve stabilire per quale motivo il ciclo è finito Finché non lo trova, continua a cercare è stato trovato il valore ha finito di cercare (invano) in tutti gli elementi se trova: i < N se non lo trova: i = N Non si deve controllare se val è stato trovato verificando la condizione vett[i]=val perché se non lo trova i vale N e vett[N] identifica un elemento inesistente Al massimo (nel caso peggiore) fa N controlli Ricerca in vettore ordinato 21 Ricerca lineare left=0; right=N-1; while (right>=left) { m=(left+right)/2; if (val==vett[m]) break; if (val<vett[m]) right=m-1; elimina la metà destra else left=m+1; elimina la metà sinistra } if (val==vett[m]) printf("Trovato\n"); else printf("Non trovato\n"); 23 Dicotomica (o binaria) 22 Ricerca dicotomica (o binaria) Non serve scorrere tutto il vettore, ci si ferma non appena si supera il valore cercato for (i=0; i<N && vett[i]<val; i++) ; if (i<N && val == vett[i]) printf("Trovato\n"); else printf("Non trovato\n"); Quando vett[i] >= val il ciclo viene interrotto e si controlla se val è stato trovato Al massimo fa N controlli Ricerca in vettore ordinato Ricerca in vettore ordinato Inizializza due indici left e right al primo e all’ultimo indice del vettore (0 e N-1) Calcola l’indice del valore centrale: m Se vett[m] è il valore cercato, termina Altrimenti se val è minore del valore centrale, arretra l’indice destro right al centro m (così dimezza il numero di valori in cui cercare) Altrimenti se val è maggiore del valore centrale, avanza l’indice sinistro left al centro Ripetendo questa operazione, si dimezza ogni volta il vettore Veloce: al massimo fa log2(N+1) controlli 24 Programmazione a stati Per stato si intende la situazione del programma in un dato istante (es. “sta leggendo i caratteri di una parola”) Mentre il programma viene eseguito esso cambia di stato in seguito al verificarsi di eventi (es. lettura di un carattere da analizzare), la transizione può portare allo stesso stato di partenza (anello) 25 Programmazione a stati Programmazione a stati Graficamente: gli stati sono disegnati come cerchi o ovali le transizioni sono disegnate come archi orientati nei punti di partenza degli archi si indicano gli eventi che causano le transizioni di stato se appropriato (c’è spazio, non sono troppe informazioni) sugli archi si indicano anche le azioni da intraprendere nelle transizioni azione evento azione Stato1 evento 26 evento Stato2 azione Nel codice l’informazione sullo stato viene mantenuta tramite una variabile di stato, in genere di tipo enum o int Tipicamente i valori che la variabile di stato può assumere sono definiti da enum o con #define Se i valori sono costanti e dagli stati partono diverse possibili transizioni, lo switch è spesso il costrutto di elezione evento azione 27 Programmazione a stati Esempio (es. 4 sui file) Si scriva un programma che chieda il nome di un file contenente un testo qualsiasi e di questo conti quante sono le parole che iniziano con ciascuna lettera dell’alfabeto. Esempio di output: Parole che iniziano con A: 45 Parole che iniziano con B: 12 Parole che iniziano con C: 27 … Parole che iniziano con Z: 3 28 Programmazione a stati La variabile di stato indicherà se si stanno leggendo i caratteri di una parola (si è “dentro” una parola) o no (si è “fuori” da una parola) e quindi assumerà 2 possibili valori: DENTRO – FUORI L’evento che può causare il cambiamento di stato è la lettura del carattere successivo In questo esempio ci sono solo 4 casi: stato stato stato stato FUORI e si legge un carattere alfabetico DENTRO e si legge un carattere alfabetico DENTRO e si legge un carattere non-alfabetico FUORI e si legge un carattere non-alfabetico 29 Programmazione a stati Programmazione a stati Più in dettaglio, se: 1. stato FUORI e si legge un carattere alfabetico: entra DENTRO e incrementa il contatore di quel car. 2. stato DENTRO e si legge un carattere alfabetico: resta DENTRO e non fa nulla stato DENTRO e si legge un carattere non-alfab.: va FUORI dalla parola e non fa nulla 3. 4. 30 Rappresentazione grafica corrispondente all’esempio (no-op=no operation): no-op 1.lettera stato FUORI e si legge un carattere non-alfabetico: resta FUORI e non fa nulla incrementa contatore lettera FUORI 4.non-lettera no-op 2.lettera DENTRO 3.non-lettera no-op 31 Esercizi 3. Homework 6 (Es. 4 sui file) Si scriva un programma che chieda il nome di un file contenente un testo qualsiasi e di questo conti quante sono le parole che iniziano con ciascuna lettera dell’alfabeto. Lo si risolva con una soluzione a stati. Esempio Parole Parole Parole … Parole 32 di output: che iniziano con A: 45 che iniziano con B: 12 che iniziano con C: 27 che iniziano con Z: 3 Si scriva un programma che per ciascuno degli algoritmi di ordinamento visti (bubble semplice e con variazioni, selection semplificato, selection, insertion) per M volte (es. 100) riempia un vettore di N valori interi casuali (es. 1000) e lo riordini. Il programma deve misurare i tempo impiegato per gli M ordinamenti per ciascuno degli algoritmi. Impostare M e N in modo da eseguire un numero significativo di prove con vettori di dimensioni grandi (1000-10000), medi (100-1000) e piccoli (100). Trarne le conclusioni. 33 Homework 6 Continuazione: Includendo <time.h> si possono usare le seguenti funzioni: time(NULL) restituisce un numero intero di tipo time_t che corrisponde all’istante attuale difftime(time_t t2, time_t t1) restituisce (come valore double) il numero di secondi intercorsi tra t1 e t2 Nota: il tipo time_t è in genere un sinonimo di long e si possono definire variabili di tale tipo: time_t ora, t1, t2; t1=time(NULL);
Documenti analoghi
Algoritmi di Ordinamento - Dipartimento di Ingegneria dell
ordinamento in cui si trova il file. La ricerca del minimo elemento
durante una scansione del file non fornisce informazioni circa la
posizione del prossimo minimo nella scansione successiva.
V...