ALGORITMO
Un algoritmo è un procedimento che risolve un determinato problema
attraverso un numero finito di passi.
Un formalismo che permette di rappresentare gli algoritmi è il
diagramma di flusso.
Esempio:
Problema del trasporto della capra, del lupo e del cavolo da una sponda ad un'altra del
fiume
1 Porta la capra sull'altra sponda
2 Torna indietro
3 Porta il cavolo sull'altra sponda
4 Porta la capra indietro
5 Porta il lupo sull'altra sponda
6 Torna indietro
7 Porta la capra sull'altra sponda
Proprietà di un algoritmo
È finito
 È definito e preciso
 Fornisce un risultato
 È eseguibile
 Risolve i problemi

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
(ES. ordina dal maggiore al minore)
una relazione d'ordine o ordine su di un insieme è una relazione binaria tra
elementi appartenenti all'insieme
è un elenco di coppie ordinate di elementi appartenenti all'insieme
I diversi algoritmi di ordinamento
Esistono tre “grandi gruppi” di algoritmi di ordinamento:

ITERATIVI

RICORSIVI

I CASI PARTICOLARI
Suddivisi a loro volta in tre tipi diversi:
ITERATIVI
• insertion sort
• selection sort
• bubble sort
CASI PARTICOLARI
• counting sort
• radix sort
• bin sort
RICORSIVI
• merge sort
• quicksort
• heap sort
Iterativi
Un algoritmo iterativo è una tipologia di algoritmo costituito da una
sequenza di azioni che viene ripetuta, finché è necessaria la ripetizione stessa
(un ciclo). Ad ogni iterazione, l'esecutore svolge un compito. Al termine verifica
se tale compito vada ripetuto mediante una condizione di ripetizione.
Per spiegare meglio il concetto di
algoritmo iterativo, si consideri il lavoro di
un addetto ad una catena di montaggio:
egli deve eseguire le stesse azioni
ripetutamente finché ci sono pezzi
da assemblare.
L'algoritmo iterativo della catena di
montaggio può essere così descritto:
1.Preleva i componenti
2.Assembla i componenti
3.Passa i componenti al
collega
4.Se ci sono altri componenti
da assemblare, torna al
punto 1
#include<stdio.h>
Int main() {
Int a, i;
a= 10;
For(i=0; i < a; i++;)
Printf(“ %d”, i);
Return 0;
System(“PAUSE”)
}
Algoritmo che
stampa i numeri
da 0 a 9,
attraverso un
ciclo “for”
Insertion sort
L'Insertion sort, in italiano ordinamento a inserimento, è un algoritmo relativamente semplice
per ordinare un array. Non è molto diverso dal modo in cui un essere umano, spesso, ordina un mazzo
di carte. L'algoritmo utilizza due indici: uno punta all'elemento da ordinare e l'altro all'elemento
immediatamente precedente. Se l'elemento puntato dal secondo indice è maggiore di quello a cui punta
il primo indice, i due elementi vengono scambiati di posto; altrimenti il primo indice avanza. Il
procedimento è ripetuto finché si trova nel punto in cui il valore del primo indice deve essere inserito.
Es.
void InsertionSort(int x[], int n) {
int i, j, app;
for (i = 1; i < n; i++) {
app = x[i];
for (j = i - 1;(j >= 0) && (x[j] > app); j--)
x[j+1] = x[j];
x[j + 1] = app;
}
}
Selection sort
Anche l'ordinamento per selezione (selection sort) è un algoritmo di ordinamento che opera in
place ed in modo simile all'ordinamento per inserzione; seleziona il numero minore nella sequenza
di partenza e lo sposta nella sequenza ordinata; di fatto la sequenza viene suddivisa in due parti:
I passaggi sono
• si inizializza un puntatore i che va da 1 a n (dove n è la lunghezza dell'array).
• Si cerca il più piccolo elemento dell'array
• Scambia l'elemento più piccolo con l'elemento alla posizione i
• Incrementa l'indice i e si torna al passo uno fino alla fine dell'array
Es.
void selection(double a[], unsigned long N) {
int i, j, min;
double t;
for (i=0; i < N-1; i++) {
for (j= 0; j < N; j++)
if (a[j] < a[j+1]) {
t = a[j+1];
a[j+1] = a[i];
a[i] = t;
}
}
}
Bubble sort
Il bubblesort è un algoritmo iterativo, ovvero 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 penultimo e
ultimo elemento. Per 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.
Es.
void BubbleSort(int *array, int elemN) {
int i, tmp, ultimo;
int alto=elemN; /* elemN è il numero degli elementi del vettore da ordinare */
while (alto >= 0) { /* in questo modo si evita 1 passaggio*/
ultimo = -1;
for (i=0; i<alto; i++) {
if (array[i]>array[i+1]) { /* sostituire ">" con "<" per avere un ordinamento decrescente */
tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
ultimo = i;
}}
alto = ultimo;
}}
Ricorsivi
Una funzione ricorsiva è una funzione che richiama sé stessa (ricorsione diretta) o richiama una funzione che
a sua volta la richiama (ricorsione indiretta). Affinché il procedimento abbia fine è necessario che siano
verificate le due seguenti proprietà:
• Debbono esistere dei parametri (valori base) per cui la funzione non richiami sé stessa
• Ogni volta che la funzione richiama sé stessa i parametri devono essere più vicini ai valori base
Es.
/* Fattoriale di un numero */
#include <stdio.h>
int calcFatt(int numero); /*1*/
main() {
int n,fat;
printf("\nCalcola il fattoriale di un numero");
printf("\n\nIntrodurre il numero ");
scanf("%d",&n); fat=calcFatt(n); /*2*/
printf("\n Fattoriale di %d = %d",n,fat);
}
/* Calcola Fattoriale utilizzando la Ricorsione*/
int calcFatt(int numero) {
int f;
if (!numero) /*3*/
f=1;
else
f=numero*calcFatt(numero-1); /*4*/
return f;
}
Quicksort
Quicksort è un ottimo algoritmo di ordinamento ricorsivo in place che si basa sul paradigma
divide et impera. La base del suo funzionamento è l'utilizzo ricorsivo della procedura partition:
preso un elemento da una struttura dati si pongono gli elementi minori a sinistra rispetto a questo
e gli elementi maggiori a destra.
Es.
void sort(int array[], int begin, int end) {
int pivot, l, r;
if (end > begin) {
pivot = array[begin];
l = begin + 1;
r = end+1;
while(l < r)
if (array[l] < pivot)
l++;
else {
r--;
swap(array[l], array[r]); }
l--;
swap(array[begin], array[l]);
sort(array, begin, l);
sort(array, r, end);
}
}
Merge sort
Il merge sort è un algoritmo di ordinamento basato su confronti che utilizza un processo di
risoluzione ricorsivo, sfruttando la tecnica del Divide et Impera, che consiste nella suddivisione del
problema in sottoproblemi della stessa natura di dimensione via via più piccola. Concettualmente,
l'algoritmo funziona nel seguente modo:
 Se la sequenza da ordinare ha lunghezza 0 oppure 1, è già ordinata. Altrimenti:
 La sequenza viene divisa (divide) in due metà (se la sequenza contiene un numero dispari di
elementi, viene divisa in due sottosequenze di cui la prima ha un elemento in più della seconda)
 Ognuna di queste sottosequenze viene ordinata, applicando ricorsivamente l'algoritmo(impera)
 Le due sottosequenze ordinate vengono fuse (combina).
1’ caso particolare counting 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. L'algoritmo conta il numero di occorrenze di ciascun valore presente nell'array da
ordinare, memorizzando questa informazione in un array temporaneo di dimensione pari
all'intervallo di valori. Il numero di ripetizioni dei valori inferiori indica la posizione del valore
immediatamente successivo.
// counting.h
#ifndef COUNTING_H
#define COUNTING_H
void counting_sort(int* A, int Alen, int* B, int k);
#endif
// counting.c
#include "counting.h"
#include <stdio.h>
void counting_sort(int* A, int Alen, int* B, int k){
int i;
int C[k];
for(i=0; i<k; i++)
C[i] = 0;
int j;
for(j=0; j<Alen; j++)
C[A[j]] = C[A[j]]+1;
for(i=1; i<k; i++)
C[i] = C[i]+C[i-1];
for (j=Alen-1; j>=0; j--){
B[C[A[j]]-1] = A[j];
C[A[j]] = C[A[j]]-1;
}
}
2’ caso particolare Radix sort
Radix sort utilizza un procedimento contro intuitivo per l'uomo, ma più facilmente
implementabile. Esegue gli ordinamenti per posizione della cifra ma partendo dalla cifra meno
significativa. Questo affinché l'algoritmo non si trovi a dovere operare ricorsivamente su
sottoproblemi di dimensione non valutabili a priori.
Es.
void RadixSort(int[] a) {
int[] t=new int[a.Length];
int r=4;
int int b=32;
int[] count=new int[1<<r];
int[] pref=new int[1<<r];
int groups=(int)Math.Ceiling((double)b/(double)r);
int mask = (1<<r)-1;
for (int c=0, shift=0; c<groups; c++, shift+=r) {
for (int j=0; j<count.Length; j++)
count[j]=0;
for (int i=0; i<a.Length; i++)
count[(a[i]>>shift)&mask]++;
pref[0]=0;
for (int i=1; i<count.Length; i++)
pref[i]=pref[i-1]+count[i-1];
for (int i=0; i<a.Length; i++) t[pref[(a[i]>>shift)&mask]++]=a[i];
t.CopyTo(a,0);
}}
FINE
Presentazione di Bonacorsi Giulio
Fonti:
• Wikipedia
Scarica

ALGORITMO - WordPress.com