Definizione di un algoritmo In informatica e matematica, il termine algoritmo indica un procedimento che risolve un determinato problema attraverso un numero finito di passi. Un problema risolvibile mediante un algoritmo si dice computabile. Un algoritmo è Un insieme ben ordinato di operazioni non ambigue ed effettivamente calcolabili che, eseguito, produce un risultato e termina in una quantità finita di tempo. Insieme ben ordinato Operazioni non ambigue e calcolabili Produce un risultato Termina in una quantità finita di tempo
DEFINIZIONE DI ALGORITMO DI ORDINAMENTO UN ALGORITMO DI ORDINAMENTO È UN ALGORITMO CHE VIENE UTILIZZATO PER ELENCARE GLI ELEMENTI DI UN INSIEME SECONDO UNA SEQUENZA STABILITA DA UNA RELAZIONE D'ORDINE, IN MODO CHE OGNI ELEMENTO SIA MINORE (O MAGGIORE) DI QUELLO CHE LO SEGUE. IN ASSENZA DI ALTRE SPECIFICHE, LA RELAZIONE D'ORDINE VIENE SEMPRE CONSIDERATA TOTALE (CIOÈ TALE DA RENDERE SEMPRE POSSIBILE IL CONFRONTO TRA DUE ELEMENTI DELL'INSIEME): LE RELAZIONI D'ORDINE PARZIALE DANNO ORIGINE AGLI ALGORITMI DI ORDINAMENTO TOPOLOGICO. A SECONDA DEL VERSO DELLA RELAZIONE CONSIDERATO, UN ORDINAMENTO PUÒ ESSERE ASCENDENTE O DISCENDENTE. PER ANALIZZARE E STUDIARE GLI ALGORITMI DI ORDINAMENTO SONO STATI DEFINITI DIFFERENTI CRITERI DI PARTIZIONAMENTO : ORDINAMENTO INTERNO E ORDINAMENTO ESTERNO ORDINAMENTO PER CONFRONTI-SCAMBI E DIGITALE ORDINAMENTO ADATTIVO STABILITÀ DI UN ALGORITMO ALGORITMI IN PLACE.
ORDINAMENTO INTERNO E ORDINAMENTO ESTERNO SE IL FILE DA ORDINARE, O LA STRUTTURA DATI, PUÒ ESSERE CONTENUTO IN MEMORIA, IL METODO VIENE DETTO INTERNO. L'ORDINAMENTO DI FILE RESIDENTI SU DISCO O SU NASTRO VIENE CHIAMATO ORDINAMENTO ESTERNO: LA DIFFERENZA PRINCIPALE TRA I DUE TIPI DI ORDINAMENTO STA NEL FATTO CHE MENTRE NEL PRIMO È POSSIBILE ACCEDERE DIRETTAMENTE A UN RECORD, NEL SECONDO I RECORD DEVONO ESSERE INDIRIZZATI IN MODO SEQUENZIALE O AL PIÙ PER GRANDI BLOCCHI. ORDINAMENTO PER CONFRONTI-SCAMBI E DIGITALI A SECONDA DEL TIPO DI OPERAZIONE CHE VIENE EFFETTUATA, SI HANNO DUE DIFFERENTI TIPI DI ORDINAMENTO. L'ORDINAMENTO CHE EFFETTUA CONFRONTI E SCAMBI E L'ALGORITMO DIGITALE CHE ACCEDE ALL'INFORMAZIONE TRAMITE UN GRUPPO DI BIT ALLA VOLTA. ORDINAMENTO ADATTIVO SOLITAMENTE UN ALGORITMO DI ORDINAMENTO SFRUTTA OPERAZIONI DI CONFRONTO E SCAMBIO. SE TALI OPERAZIONI VENGONO SVOLTE IN MODO INDIPENDENTE DAI DATI DI INPUT L'ALGORITMO VIENE DEFINITO NON ADATTIVO. MENTRE SE UN METODO DI ORDINAMENTO ESEGUE DIVERSE SEQUENZE DI OPERAZIONI IN FUNZIONE DEL RISULTATO DEI CONFRONTI SI HA UN ALGORITMO ADATTIVO.
STABILITA DI UN ALGORITMO UN METODO DI ORDINAMENTO SI DICE STABILE SE PRESERVA L'ORDINE RELATIVO DEI DATI CON CHIAVI UGUALI ALL'INTERNO DEL FILE DA ORDINARE. LA STABILITÀ PUÒ ESSERE FORZATA AGGIUNGENDO PRIMA DELL'ORDINAMENTO UN PICCOLO INDICE A CIASCUNA CHIAVE O ALLUNGANDO IN QUALCHE ALTRO MODO LE CHIAVI SULLE QUALI OPERARE, IN MODO DA RENDERLE UNIVOCHE PRESERVANDO L'INFORMAZIONE SULLA POSIZIONE RELATIVA DEGLI ELEMENTI. ALGORITMO IN PLACE UN ALGORITMO SI DICE ALGORITMO IN PLACE QUANDO NON CREA UNA COPIA DELL'INPUT PER RAGGIUNGERE L'OBIETTIVO, L'ORDINAMENTO IN QUESTO CASO. PERTANTO UN ALGORITMO IN PLACE RISPARMIA MEMORIA RISPETTO AD UN ALGORITMO NON IN PLACE. SI NOTI INFATTI CHE, MALGRADO LE CONSIDERAZIONI FATTE SULLA COMPLESSITÀ ABBIANO SENSO IN GENERALE, HANNO UNA RILEVANZA DECISIVA SUI GRANDI NUMERI. ALLO STESSO MODO DELLA PROPRIETÀ DI ESSERE O MENO IN PLACE.
Tipi di algoritmi di ordinamento Selection sort Inserection sort Bubble sort Quick sort Merge sort Heap sort Counting sort Bucket sort
si cerca il più piccolo elemento della sottosequenza A[i..n]; Selection sort #include<stdio.h> #include<stdlib.h> int main() { int a[10]; //vettore int i, j, imin; //indici int n, t; do{ printf("\n Quanti elementi vuoi inserire nell'array ?"); scanf("%d",&n); }while(n<1 || n>10); //controllo sulle dimensioni del vettore for(i=0;i<n;i++){ printf("\nInserisci elemento: "); scanf("%d", &a[i]); } for(i=0;i<n-1;i++){ imin=i; for(j=i+1;j<n;j++){ if(a[j]<a[imin]){ imin=j; //nel caso a[j]<a[min] assegno ad imin il valore di j, bada bene il valore //di j (ovvero l'indice) non di a[j] (ovvero il valore contenuto } // nella posizione j-esima del vettore) } t=a[i]; a[i]=a[imin]; a[imin]=t; } printf("\n\nEcco il vettore ordinato\n\n"); for(i=0;i<n;i++){ printf("%d ",a[i]); } return 0; } L'algoritmo seleziona di volta in volta il numero minore nella sequenza di partenza e lo sposta nella sequenza ordinata; di fatto la sequenza viene suddivisa in due parti: la sottosequenza ordinata, che occupa le prime posizioni dell'array, e la sottosequenza da ordinare, che costituisce la parte restante dell'array. Dovendo ordinare un array A di lunghezza n, si fa scorrere l'indice i da 1 a n-1 ripetendo i seguenti passi: si cerca il più piccolo elemento della sottosequenza A[i..n]; i scambia questo elemento con l'elemento i-esimo.
Inserection sort Ad ogni istante (iterazione), il vettore è costituito da una parte iniziale ordinata (che aumenta di volta in volta) e da la parte rimanente che contiene i valori da ordinare. Per ogni valore ancora da inserire, viene fatta una ricerca binaria nella parte ordinata del vettore e vengono spostati in avanti tutti gli elementi per liberare la posizione . Nella posizione liberata viene inserito il valore . #include <stdio.h> #define MAX 100 int leggi_array(int x[]) { int i, n; printf("Numero di elementi: "); scanf("%d", &n); printf("Inserisci %d elementi: ", n); for (i=0; i<n; i++) scanf("%d", &x[i]); return(n); } void stampa_array(int x[], int n) { int i; printf("%d ", x[i]); printf("\n"); return; void insertion_sort(int x[], int n) { int i, j, app; for (i=1; i<n; i++) { app = x[i]; j = i-1; while (j>=0 && x[j]>app) { x[j+1] = x[j]; j--; x[j+1] = app; } return;} int main(void) { int v[MAX], n; n = leggi_array(v); stampa_array(v, n); insertion_sort(v, n); return(1); /* */ Legge in input il numero n ed n numeri interi * che memorizza nell'array. Restituisce il numero * di elementi letti (n). */ * Stampa in output l'array. * Funzione che implementa l'algoritmo Insertion sort. * Riceve come argomento l'array ed il numero di * elementi contenuti nell'array. Non restituisce alcun * valore, ma modifica il contenuto dell'array, ordinandolo.
Bubble sort void bubblesort(int v[], int n) { int i,k; int temp; for(i = 0; i<n-1; i++) { for(k = 0; k<n-1-i; k++) { if(v[k] > v[k+1]) { temp = v[k]; v[k] = v[k+1]; v[k+1] = temp; } Il bubble sort è un algoritmo iterativo, ossia basato sulla ripetizione di un procedimento fondamentale. La singola iterazione dell'algoritmo prevede che gli elementi dell'array siano confrontati a due a due, procedendo in un verso stabilito . Per esempio, saranno confrontati il primo e il secondo elemento, poi il secondo e il terzo, poi il terzo e il quarto, e così via fino al confronto fra il penultimo e l'ultimo elemento. Ad ogni confronto, se i due elementi confrontati non sono ordinati essi vengono scambiati. Durante ogni iterazione almeno un valore viene spostato rapidamente fino a raggiungere la sua collocazione definitiva; in particolare, alla prima iterazione il numero più grande raggiunge l'ultima posizione dell'array.
Quick sort void scambia (tipobase v[], long i, long j) { tipobase tmp=v[i]; v[i]=v[j]; v[j]=tmp; } void QSort (tipobase v[], long inf, long sup) { tipobase pivot=v[(inf+sup)/2]; long i=inf,j=sup; while (i<=j) { while (v[i]<pivot) i++; while (v[j]>pivot) j--; if (i<j) scambia(v,i,j); if (i<=j) { i++; j--; } } if (inf<j) QSort(v,inf,j); if (i<sup) QSort(v,i,sup); } Come si vede essa si compone di un ciclo while che termina quando i>j. Dentro questo ciclo due cicli while incrementano i e decrementano j. Si noti che i due cicli terminano sicuramente quando v[i] coincide con il pivot e v[j] coincide con il pivot. Nel caso in cui i<j viene effettuato lo scambio, che non viene realizzato se i=j. Se i≤j, la variabile i viene incrementata e j decrementata.
Immaginate di dover riunire due pacchetti di carte già ordinate in un solo pacchetto che deve essere anche lui ordinato. Intuitivamente si procede in questo modo. 1- Si prende la più piccola carta fra le due prime carte dei pacchetti iniziali (che rappresentano il minimo per ogni pacchetto). Si mette la carta presa nel terzo pacchetto. 2.Si ripete il passo 1 finche l’uno dei due pacchetti non si esaurisce. 3.se uno dei pacchetti è esaurito,si prende le carte del pacchetto rimanente e gli si mette nel terzo pacchetto nello stesso ordine. Merge esegue il processo appena descritto. Merge sort #include <stdio.h> #define N 100 void Merge(int v[], int p, int q, int r); void MergeSort(int v[], int p, int r); int main(){ int v[N], i, n; printf("Immetti la lunghezza del vettore: "); scanf("%d",&n); printf("Immetti gli elementi del vettore: "); for (i = 0; i < n; i++) scanf("%d", &v[i]); MergeSort(v,0,n); printf("Il vettore ordinato e': "); printf("%d ", v[i]); printf("\n"); return 0;} void MergeSort(int v[], int p, int r){ int q, i; if (p + 1 == r) return; q = (p + r) / 2; MergeSort(v, p, q); MergeSort(v, q, r); Merge(v,p,q,r);} void Merge(int v[], int p, int q, int r){ int i = p, j = q, k = 0, w[N]; while (i < q && j < r) {
HEAP SORT L' HEAPSORT PER ESEGUIRE L'ORDINAMENTO, UTILIZZA UNA STRUTTURA CHIAMATA HEAP (MUCCHIO); UN HEAP È RAPPRESENTABILE CON UN ALBERO BINARIO IN CUI TUTTI I NODI SEGUONO UNA DATA PROPRIETÀ, DETTA PRIORITÀ. ESSO È COMPLETO ALMENO FINO AL PENULTIMO LIVELLO DELL'ALBERO E AD OGNI NODO CORRISPONDE UNO ED UN SOLO ELEMENTO. IN UNO HEAP DECRESCENTE OGNI NODO PADRE CONTIENE UN VALORE MAGGIORE O UGUALE A QUELLO DEI SUOI DUE FIGLI DIRETTI, DI CONSEGUENZA RISULTERÀ MAGGIORE ANCHE DI TUTTI I NODI CHE SI TROVANO NEL SOTTOALBERO DI CUI ESSO È LA RADICE; QUESTO NON IMPLICA AFFATTO CHE NODI A PROFONDITÀ MAGGIORE CONTENGANO VALORI MINORI DI QUELLI A PROFONDITÀ MINORE. QUINDI IN OGNI ISTANTE, IN UN HEAP DECRESCENTE, LA RADICE CONTIENE IL VALORE MAGGIORE. QUESTA STRUTTURA È MOLTO USATA, IN PARTICOLARE, PER L'ORDINAMENTO DI ARRAY.
COUNTING SORT BUCKET SORT IL COUNTING SORT È UN ALGORITMO DI ORDINAMENTO PER VALORI NUMERICI INTERI CON COMPLESSITÀ LINEARE. L'ALGORITMO SI BASA SULLA CONOSCENZA A PRIORI DELL'INTERVALLO IN CUI SONO COMPRESI I VALORI DA ORDINARE. BUCKET SORT IL BUCKET SORT È UN ALGORITMO DI ORDINAMENTO PER VALORI NUMERICI CHE SI ASSUME SIANO DISTRIBUITI UNIFORMEMENTE IN UN INTERVALLO SEMICHIUSO (0,1). DESCRIZIONE DELL’ALGORITMO L'INTERVALLO DEI VALORI, NOTO A PRIORI, È DIVISO IN INTERVALLI PIÙ PICCOLI, DETTI BUCKET (CESTO). CIASCUN VALORE DELL'ARRAY È QUINDI INSERITO NEL BUCKET A CUI APPARTIENE, I VALORI ALL'INTERNO DI OGNI BUCKET VENGONO ORDINATI E L'ALGORITMO SI CONCLUDE CON LA CONCATENAZIONE DEI VALORI CONTENUTI NEI BUCKET.