PROGRAMMI DI RICERCA E ORDINAMENTO

Slides:



Advertisements
Presentazioni simili
Algoritmi di ordinamento
Advertisements

Introduzione al linguaggio C++
C++ Di Marco Cozzani.
INFORMATICA Altre Istruzioni di I/O
Gli Algoritmi di ordinamento
INFORMATICA Algoritmi fondamentali
Corso di Laurea Triennale in Ingegneria Gestionale Corso di Fondamenti di informatica A. A A.Pinto Algoritmi di ricerca 1.
Uso avanzato di C.
Nel C non esiste un dato primario di tipo stringa; queste sono rappresentate con un array monodimensionale di caratteri (tipo char). Così per definire.
Calcolo del minimo comune multiplo (m.c.m.) Luigi Sante
Unità G3 Algoritmi notevoli. Ordinamento Un insieme di dati {a0, a1, a2, …, an} si dice ordinato in ordine crescente se a0 a1 a2 a3 … an I dati sono generalmente.
Algoritmi notevoli.
Algoritmi notevoli In linguaggio C.
Informatica Generale Marzia Buscemi
Introduzione al linguaggio C
Algoritmi in C++ (1) da completare
La ricorsione Simulazione. Il Main /* Programma che usa una funzione ricorsiva*/ #include #define MAX_N 8 main() int valore, dato; printf(Introduci n:
ESERCITAZIONE N. 5 ESERCIZIO N. 1 Autore: Biagio Brattoli S I Corso.
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
FUNZIONI DI BIBLIOTECA
Caratteri e stringhe di caratteri
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Iterazione enumerativa (for)
Ambito delle variabili
Funzioni definite dall’utente
Informatica di base A.A. 2003/2004 Algoritmi e programmi
Informatica 2. Concetti fondamentali di programmazione Programmare vuol dire scrivere un algoritmo in un linguaggio che faccia funzionare un calcolatore.
1 Corso di Informatica (Programmazione) Lezione 11 (19 novembre 2008) Programmazione in Java: controllo del flusso (iterazione)
Introduzione alla programmazione lll
Procedure e funzioni nei linguaggi di alto livello Lab Programmazione - turno /2006.
Algoritmi.
QuickSort Quick-Sort(A,s,d) IF s < d THEN q = Partiziona(A,s,d) Quick-Sort(A,s,q-1) Quick-Sort(A,q + 1,d)
Esercizi FUNZIONI Passaggio di parametri per valore, variabili e tipi locali e globali, prototipo.
Strutture di controllo in C -- Flow Chart --
Esercizi di riepilogo sul linguaggio C: file, puntatori, liste
Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri per indirizzo, passaggio.
Esercizi C su array e matrici
Le liste dinamiche La ricorsione
Algebra Lineare Esercizi assegnati.
Le funzioni.
Lezione 2 Programmare in ASP
AN Fondam98 Sorting Ricerca in un vettore ordinato.
Calcolo del Massimo Comun Divisore
Problema dell’ordinamento di un array: Il metodo Bubble Sort.
1 ListaDiElem Cancella( ListaDiElem lista, TipoElemento elem ) { ListaDiElem puntTemp; if( ! ListaVuota(lista) ) if( lista–>info == elem ) { puntTemp =
I Metodi in Java Il termine "metodo" è sinonimo di "azione". Quindi, affinché un programma esegua qualche istruzione, deve contenere metodi.
Il linguaggio C Le funzioni C Language Il passaggio dei parametri
Cicli in Fortran I cicli consentono di eseguire una sequenza di istruzioni più di una volta due tipi: Cicli iterativi Cicli while.
void binario(int n); …………………
Programmazione di Calcolatori
Esercizi Liste.
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
Complessità di un algoritmo
Definizione di un algoritmo
L’iterazione while La sintassi è la seguente: while (condizione) {
Ripetizione La vera potenza dei programmi per computer risiede nella capacità di ripetere lo stesso calcolo o sequenza di istruzioni più volte, ogni volta.
#include void main() { int a,b,c,; float s, x,x1,x2,delta,alfa,beta; int num[3]; int i; printf("La forma classica dell'equazione di 2° grado è: a*x^2+b*x+c=0\n.
ALGORITMI DI RICERCA Nella programmazione s’incontra spesso la necessità di ricercare un elemento (chiave) in un elenco, oppure di ordinare gli elementi.
ALGORITMO Un algoritmo è un procedimento che risolve un determinato problema attraverso un numero finito di passi. Un formalismo che permette di rappresentare.
Vettori, indirizzi e puntatori Finora abbiamo usato gli indirizzi nel chiamare  la funzione scanf()  le altre funzioni per riferimento Tuttavia la vera.
Capitolo 6 Iterazione Lucidi relativi al volume: Java – Guida alla programmazione James Cohoon, Jack Davidson Copyright © The McGraw-Hill Companies.
Informatica 4 Funzioni. FUNZIONE: definizione MATEMATICA Relazione (o applicazione) binaria tra due insiemi A e B che associa a ogni elemento di A un.
Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini
Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini
L’ordinamento per Selezione seleziona l’elemento con valore maggiore e lo scambia con il primo elemento del vettore. Tra gli N-1 elementi rimanenti viene.
Problema dell’Ordinamento. Problema dell’ordinamento Formulazione del problema –Si vuole ordinare una lista di elementi secondo una data proprietà P Esempio:
Il C `e un linguaggio di programmazione di uso generale, originariamente sviluppato per la scrittura del sistema operativo Unix, ed oggi disponibile su.
Ordinamento. Introduzione Una delle operazioni che si possono eseguire sui vettori, è quella di ordinare gli elementi del vettore in ordine crescente.
Lezione n. Parole chiave: Corso di Laurea: Insegnamento: Docente: A.A Salvatore Cuomo La ricorsione 15 Approccio ricorsivo, esercizi sulla.
Transcript della presentazione:

PROGRAMMI DI RICERCA E ORDINAMENTO Ricerca lineare. Abbiamo già visto l’algoritmo che esegue la ricerca lineare di un elemento (detto chiave) in una lista o vettore, e il corrispondente diagramma di flusso:

Siamo ora in grado di tradurlo in una funzione di nome ricercaLin, che riceve in ingresso un vettore di interi, il numero dei suoi elementi e la chiave da ricercare ricercaLin(int elem[], int dim, int chiave) { int indice, trovato, i; trovato = FALSO; indice = -1; i = 0; while (i<dim && !trovato) if (elem[i] == chiave) trovato = VERO; indice = i; } i++; return(indice);

Osserviamo che il ciclo while è usato per accedere a ciascun elemento del vettore, dal primo all’ultimo, fino a che si trova una corrispondenza con la chiave desiderata. In tale caso la variabile trovato viene impostata a VERO, il che fa terminare il ciclo; altrimenti la ricerca continua fino a che s’incontra la fine del vettore. Per provare questa funzione, scriviamo una funzione pilota main() che chiami ricercaLin e visualizzi il risultato da essa fornito. Il programma completo è il seguente:

#include <stdio.h> #define VERO 1 #define FALSO 0 #define N 10 void main(void) { int a[N] = {5,10,22,32,45,67,73,98,99,101}; int voce, posto; int ricercaLin(int [], int, int); printf(“Scrivi la voce da cercare: “); scanf(“%d”, &voce); posto = ricercaLin(a, N, voce); if (posto > -1) printf(“La voce è stata trovata al posto n° %d\n”, posto+1); else printf(“La voce non è stata trovata”); } ricercaLin(int elem[], int dim, int chiave) { int indice, trovato, i; trovato = FALSO; indice = -1; i = 0; while (i<dim && !trovato) if (elem[i] == chiave) trovato = VERO; indice = i; } i++; return(indice);

Ricerca binaria. Ricordiamo che la ricerca binaria va eseguita su un vettore ordinato, e che la sua strategia è la seguente: a) si confronta la chiave con l’elemento centrale del vettore; a1) se la chiave è uguale all’elemento centrale, la ricerca termina con successo; a2) se la chiave è maggiore dell’elemento centrale essa, se è presente, si deve trovare nella parte superiore del vettore, e la ricerca continua in essa; a3) se la chiave è minore dell’elemento centrale essa, se è presente, si deve trovare nella parte inferiore del vettore, e la ricerca continua in essa.

Come abbiamo visto, lo pseudocodice che implementa questa strategia è: poni trovato = FALSO poni indice = -1 poni indice inferiore = 0 poni indice superiore = dimensione del vettore -1 comincia con il primo elemento while indice infer. <= indice super. AND non si è ancora trovata la chiave poni indice medio = media degli indici infer. e super. if la chiave è uguale all’elemento di indice medio la chiave è stata trovata altrimenti, se la chiave è > dell’elemento di indice medio poni indice inferiore = indice medio +1 altrimenti, se la chiave è < dell’elemento di indice medio poni indice superiore = indice medio -1 fine dell’if fine del while fornisci il valore di indice; Ed ecco la versione in C di questo pseudocodice:

ricercaBin(int elem[], int dim, int chiave) { int indice, trovato, inf, sup, medio; indice = -1; trovato = FALSO; inf = 0; sup = dim -1; while (inf <= sup && !trovato) medio = (int) ((inf + sup)/2); if (chiave == elem[medio]) trovato = VERO; indice = medio; } else if (chiave > elem[medio]) inf = medio + 1; else sup = medio - 1; return(indice);

La precedente funzione ricercaBin andrà poi scritta dopo la seguente funzione principale: #include <stdio.h> #define VERO 1 #define FALSO 0 #define N 10 void main(void) { int a[N] = {5,10,22,32,45,67,73,98,99,101}; int voce, posto; int ricercaBin(int [], int, int); printf(“Scrivi la voce da cercare: “); scanf(“%d”, &voce); posto = ricercaBin(a, N, voce); if (posto > -1) printf(“La voce è stata trovata al posto n° %d\n”, posto+1); else printf(“La voce non è stata trovata”); }

Osserviamo che questa funzione main() usata per la ricerca binaria è la stessa già usata per la ricerca lineare (a parte, ovviamente, il diverso nome di funzione usato nelle due istruzioni che dichiarano e chiamano la funzione).

Ordinamento a bolle. Traduciamo ora in programmi C i vari algoritmi di ordinamento già visti. Cominciamo da quello a bolle, che si basa sul seguente algoritmo: a) si confronta ciascun elemento, dal secondo all’ultimo, con il precedente, e si scambiano se necessario; b) si ripetono i confronti come prima, fermandosi la seconda volta al penultimo elemento, la terza volta al terz’ultimo, ... , l’ultima volta al secondo elemento. Perciò, nel caso di un vettore con 10 elementi, si inizia confrontando a[1] con a[0], poi a[2] con a[1], ... fino ad a[9] con a[8], eseguendo gli scambi necessari. A causa del modo con cui si effettuano i confronti e gli scambi, dopo la prima scansione del vettore (i = 0) il valore più grande sarà memorizzato nell’ultima componente del vettore (cioè in a[9]). Per questa ragione la seconda scansione (i = 1), partendo sempre dal confronto di a[1] con a[0], termina al confronto di a[8] con a[7], lasciando in a[8] il secondo valore più grande.

In tal modo saranno eseguite in tutto 9 scansioni, al termine delle quali il 9° valore in ordine di grandezza sarà memorizzato in a[1], mentre il più piccolo si troverà in a[0]. Pertanto, nel caso di un vettore a n dimensioni, questo algoritmo esegue n - 1 passate del vettore, mentre il numero di scambi eseguiti dipende dal grado di “disordine” del vettore (è 0 se il vettore è già ordinato). Lo pseudo codice è quindi il seguente: (in questa fase, le istruzioni indicate in colore non sono strettamente necessarie): poni un contatore di scambi = 0 for l’indice i che va dal 1° elemento al penultimo for l’indice j che va dal 2° elemento all’ultimo if num[j] < num[j-1] scambia num[j] con num[j-1] incrementa il contatore di scambi fine del for restituisci il contatore di scambi

Esso si traduce nella seguente funzione: int ord_bolle(int a[], int numel) { int i, j, temp, scambi = 0; for (i = 0; i < numel - 1; i++) for (j = 1; j < numel - i; j++) if (a[j] < a[j-1]) temp = a[j]; a[j] = a[j-1]; a[j-1] = temp; scambi++; } return(scambi);

che va scritta dopo la seguente funzione principale: #include <stdio.h> #define N 10 void main(void) { int a[N] = {22,5,67,98,45,32,101,99,73,10}; int i, passi; int ord_bolle(int [], int); /* prototipo */ passi = ord_bolle(a, N); /* chiamata */ printf("Il vettore ordinato in ordine crescente è:\n"); for (i = 0; i < N; ++i) printf("%d ", a[i]); printf(“\n Sono stati eseguiti %d scambi”, passi); }

Bolle migliorato. All’algoritmo a bolle si può apportare un sostanziale miglioramento modificandolo come segue: a) si confronta ciascun elemento, dal secondo all’ultimo, con il precedente, e si scambiano se necessario; b’) si ripete il procedimento fino a quando si esegue una scansione della lista senza effettuare alcuno scambio (perché in tale caso tutti gli elementi sono nell’ordine corretto). In tale modo il numero di passate da eseguire nel vettore non è più fisso (e uguale a n-1), ma varia da 1 (nel caso il vettore sia già ordinato) a n-1 (nel caso il vettore abbia il massimo grado di disordine, ossia sia ordinato in senso decrescente). La funzione che apporta questo miglioramento (e che va scritta dopo la funzione principale appena vista) è la seguente:

int ord_bolle(int a[], int numel) { int i, j, temp, passi; i = 0; do passi = 0; for (j=1; j<numel-i; j++) if (a[j] < a[j-1]) temp = a[j]; a[j] = a[j-1]; a[j-1] = temp; passi++; } i++; while (i < (numel-1) && passi != 0); return (i);

Ordinamento per selezione Vediamo ora il programma dell’ordinamento per selezione, che si basa sul seguente algoritmo: si seleziona inizialmente il più piccolo tra gli elementi a[1], ... , a[n] (o uno dei più piccoli, se ve ne sono più uguali) e lo si scambia con a[1]; 2. tra gli elementi a[2], ... , a[n] del vettore così modificato si seleziona il successivo elemento più piccolo e lo si scambia con a[2], e così si prosegue. 3. Si continua così fino alla iterazione n-1-esima, dopo la quale tutto il vettore a risulta ordinato. Ricordiamo che lo pseudo codice di questo algoritmo è il seguente:

for ogni elemento, dal primo al penultimo trova il più piccolo elemento, dal corrente all’ultimo: ponendo il valore minimo uguale all’elemento corrente; salvando l’indice dell’elemento corrente; for ogni elemento, dal corrente +1 fino all’ultimo if elemento[indice ciclo interno] < valore minimo poni valore minimo = elemento[indice ciclo interno] salva l’indice del nuovo valore minimo trovato fine dell’if fine del for scambia il valore corrente con il nuovo valore minimo Questo pseudo codice esegue l’ordinamento tramite due cicli for nidificati: Il ciclo esterno determina n – 1 passate attraverso il vettore; in ognuna di esse alla variabile min è inizialmente assegnato il valore num[i], dove i è la variabile contatore del ciclo for esterno. Dato che i comincia da 0 e termina a n - 1, ogni elemento del vettore, tranne l’ultimo, viene successivamente designato come quello corrente.

Il ciclo interno percorre ciclicamente gli elementi successivi a quello corrente per selezionare il prossimo valore più piccolo, cominciando dal valore dell’indice i+1 e continuando fino alla fine. Quando viene trovato un nuovo minimo, il suo valore e la sua posizione nel vettore sono memorizzati rispettivamente nelle variabili min e indmin. Una volta completato il ciclo interno, si effettua uno scambio solo se è stato trovato un valore minore di quello nella posizione corrente. Lo pseudo codice si traduce nella seguente funzione ordi_sele:

int ordi_sele(int num[], int dim) { int i, j, min, indmin, temp; for (i = 0; i < (dim-1); i++) min = num[i]; indmin = i; for (j = i+1; j < dim; j++) if (num[j] < min) min = num[j]; indmin = j; } if (min < num[i]) temp = num[i]; num[i] = min; num[indmin] = temp;

Essa si aspetta due argomenti: il vettore da ordinare (ossia l’indirizzo del suo primo elemento) il numero dei suoi elementi e va scritta dopo la seguente funzione principale: #include <stdio.h> #define N 10 void main(void) { int a[N] = {22,5,67,98,45,32,101,99,73,10}; int i; int ordi_sele(int [], int); ordi_sele(a, N); printf("Il vettore ordinato in ordine crescente è:\n"); for (i = 0; i < N; ++i) printf("%d ", a[i]); } Si tratta della stessa funzione impiegata per l’ordinamento a bolle (a parte l’ovvia differenza del nome della funzione chiamata).