FdI_20121030_Operazioni sui vettori.pptx

annuncio pubblicitario
Linguaggio C
Operazione sui vettori
Operazioni sui vettori
Problemi di ricerca
Esiste un certo data in un vettore?
Ricerca sequenziale (dall’inizio o dalla fine,
l’unica se i dati non sono ordinati)
Ricerca dicotomica (dal mezzo, su dati
ordinati)
Ricerca sequenziale
#include <stdio.h>!
#define MAXDIM 100 /* dimensione massima del!
vettore */!
main()!
{int i,K,N;!
int V[MAXDIM];!
do{!
printf("\n Inserire la dimensione del vettore!
non superiore a %d\n",MAXDIM);!
scanf("%d",&N);!
}while(N>MAXDIM);!
/* inserimento vettore */!
for (i=0;i<N;i++)!
{!
printf("Inserire l'elemento %d : ",i+1);!
scanf("%d",&V[i]);!
}!
/* Inserimento del valore da cercare ( chiave K!
)*/!
printf("Inserire l'elemento da cercare : ");!
scanf("%d",&K);!
/* scandire gli elementi del vettore partendo dal!
primo V[0] e fermandosi se si trova K o se si!
finisce l’array*/!
i=0;!
while( K != V[i] && i<N )!
i = i + 1;!
/*il risultato della ricerca dipende da quale!
condizione di uscita è stata verificata*/!
if ( i<N ) printf("Elemento trovato in posizione!
%d\n", i+1);!
else printf("Elemento non trovato\n");!
}!
Ricerca dicotomica
1)
2)
3)
Si individua l’elemento che sta a metà del vettore;
Si confronta la chiave K con tale elemento. Se l’elemento
individuato non è uguale a quello cercato :
• se K > elemento mediano la ricerca continua solo nel
semivettore superiore
• se K < elemento mediano la ricerca continua solo nel
semivettore inferiore
Il procedimento continua suddividendo i semivettori via via
individuati.
Esempio: 2 4 5 6 8 9 14 trovare 9
Confronto 9 con 6 - ripeti sul vettore 8 9 14
Confronta 9 con 9 - trovato
Ricerca dicotomica
#include <stdio.h>!
#define MAXDIM 100!
main()!
{!
int i,inf,sup,med,K,N; int V[MAXDIM];!
do{!
printf("\n Inserire la dimensione del vettore non!
superiore a %d\n",MAXDIM);!
scanf("%d",&N);!
}while(N>MAXDIM);!
/* inserimento del vettore ordinato */!
for (i=0;i<N;i++)!
{!
printf("Inserire l'elemento %d : ",i+1);!
scanf("%d",&V[i]);!
}!
/* Inserimento del valore da cercare K */!
printf("Inserire l'elemento da cercare : ");!
scanf("%d",&K);!
/*inizializzazione degli indici */!
inf = 0; sup = N-1; med = (inf + sup)/2;!
/*accedi al mediano del vettore a ciascun passo */!
while ( K != V[med] && inf<sup )!
{!
if ( K > V[med] ) /*vai nella parte alta*/!
inf = med+1;!
else!
sup = med-1; /*vai nella parte bassa*/!
med = (inf + sup)/2;!
}!
/*risultato della ricerca */!
if ( V[med]== K )!
printf("Elemento trovato in posizione %d\n", med+1);!
else printf("Elemento non trovato\n");!
}!
Quale preferire?
La Ricerca Sequenziale
ricerca con successo:Nel caso migliore ho un
solo confronto e in quello peggiore N
Il numero medio di confronti risulta (N+1)/2
ricerca senza successo:
L’algoritmo esamina sempre tutto il vettore,
quindi il numero di confronti è sempre N
La Ricerca dicotomica
Ad ogni iterazione l'insieme è dimezzato, il numero
di confronti è pari a quante volte N può essere
diviso per 2 fino a ridurlo a 0.
in un vettore di dimensione N = 2h, l’algoritmo deve
compiere circa h = log2(N) passi (e quindi confronti) per
la ricerca senza successo, nel caso medio il numero è
leggermente inferiore mentre nel caso migliore è 1.
Esempio : per cercare un elemento in un insieme di
1.000.000 elementi, nel caso pessimo con la Ricerca
Sequenziale dovremmo eseguire circa 1.000.000
confronti, mentre con la Ricerca Binaria ne
dobbiamo effettuare al massimo 21.
Algoritmo di ordinamento
! " Metodo per ordinare un insieme di oggetti.
! " Il problema dell’ordinamento è un problema classico dell’informatica:
-"
-"
Valenza didattica: problema in sè molto semplice e chiunque è in
grado di comprendenre i termini generali
Valenza in ambito applicativo: si ritrova spesso come sottoproblema
in molti casi reali
! " Sono stati proposti molti algoritmi diversi ed eleganti:
-"
Se presentati in opportuna successione permettono di evidenziare gli
aspetti fondamentali della progettazione e della costruzione di un
algoritmo efficiente
Algoritmo di ordinamento
! " Il problema dell’ordinamento (sorting) può essere posto nei seguenti
termini:
-" Dati un insieme di elementi qualsiasi A={a1,a2,…,an}, su cui sia
possibile definire una relazione d’ordine totale ! si richiede
diprodurre una permutazione degli elementi in modo che aih ! aik per
ogni h,k=1,2,….,n e h ! k
-" Una relazione d’ordine totale è una relazione riflessiva,
antisimmetrica e transitiva definita su ogni coppia di elementi
dell’insieme
-" La soluzione è unica a meno di elementi uguali:
Algoritmi di ordinamento
! " Soluzioni via via sempre più sofisticati ma con complessità
computazionale sempre più bassa
Algoritmi di ordinamento
! " I primi 3 algoritmi analizzat – SELECTION SORT, INSERTION
SORT e BUBBLE SORT – sono estremamente elementari e consentono
un’implementazione assai semplice:
-" il costo da pagare alla semplicità di questi algoritmi sta ovviamente
nell’elevata complessità computazionale,che inquesti casi è O(n2).
! " L’algoritmo QUICKSORT consente di raggiungere una complessità di
O(nlog2n) nel caso medio, mentre nel caso più sfavorevole ritorna ad
una complessità di O(n2).
Algoritmi di ordinamento
! " Gli algoritmi MERGESORT e HEAPSORT consentono di raggiungere
una complessità di O(nlog2n) anche nel caso peggiore:
-" è possibile dimostrare che il limite inferiore alla complessità
computazionale del problema dell’ordinamento mediante confronti
(senza dunque poter sfruttare altre informazioni sull’insieme da
ordinare) è proprio pari a nlog2n, possiamo concludere che tali
algoritmi sono ottimi.
Algoritmi di ordinamento
! " Gli algoritmi COUNTING SORT e BUCKET SORT sono invece basati
su altri criteri e strategie, diverse dal confronto fra i valori degli
elementi dell’insieme da ordinare, e sfruttano pertanto altre
informazioni sui dati in input:
-" Grazie a questo consentono di ridurre ulteriormente la complessità
nel caso peggiore, arrivando ad una complessità lineare di (n). Sotto
a tale soglia è impossibile scendere,dal momento che per ordinare un
insieme di n elementi è necessario esaminarli tutti almeno una volta.
! " Ci possiamo concentrare soltanto nello studio della complessità nel
caso peggiore, dal momento che è il parametro più conservativo per la
valutazione dell’efficienza di un algoritmo.
Selection sort
Selection sort
! " Un algoritmo decisamente intuitivo ed estremamente semplice.
! " Nella pratica è utile quando l’insieme da ordinare è composto da pochi
elementi e dunque anche un algoritmo non molto efficiente può essere
utilizzato con il vantaggio di non rendere troppo sofisticata la codifica
del programma che lo implementa.
! " L’idea di fondo su cui si basa l’algoritmo è quella di ripetere per n volte
una procedura in grado di selezionare alla i-esima iterazione l’elemento
più piccolo nell’insieme e di scambiarlo con l’elemento che in quel
momento occupa la posizione i
Selection sort
! " In altre parole:
-"
-"
-"
alla prima iterazione dell’algoritmo verrà selezionato l’elemento più
piccolo dell’intero insieme e sarà scambiato con quello che occupa la
prima posizione;
alla seconda iterazione è selezionato il secondo elemento più piccolo
dell’insieme, ossia l’elemento più piccolo dell’insieme
“ridotto”costituito dagli elementi {a2,a3,...,an}ed è scambiato con
l’elemento che occupa la seconda posizione;
Si ripete fino ad aver collocato nella posizione corretta tutti gli n
elementi.
Selection Sort
void selection_sort(int[] A, int n) {
int i=0;
for (i=0;i<n;i++) {
int j=0;
for (j=i+1;j<n;j++) {
if (a[j] < a[i]) {
int temp=a[j];
a[j]=a[i];
a[i]=temp;
}
}
}
Selection sort
Trovo il minimo fra gli N; poi il minimo fra gli N-1; etc e lo metto nella
posizione da ordinare
#define N 100!
….!
main ()!
{!
int i, j, min, temp; int dati[N];!
/*acquisisci gli N valori*/!
……!
for (i = 0; i < N-1; i++) {!
min = i;!
for (j = i+1; j < N; j++) {!
/* trovo l’indice in cui si trova il minimo */!
if(dati[j]<dati[min])!
min=j;!
temp = dati[i];!
dati[i]=dati[min]; /*metto il minimo a posto*/!
dati[min]= temp;!
}!
}!
Selection Sort
! " Il numero di operazioni è:
(n-1) + (n-2) + … + 2 + 1 ! n(n-1)/2 ! O(n2)
! " Un inconveniente dell'algoritmo di ordinamento per selezione è che il
tempo di esecuzione dipende solo in modo modesto dal grado di
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.
! " Verificare che esso impiega più o meno lo stesso tempo sia su file già
ordinati che su file con tutte le chiavi uguali, o anche su file ordinati in
modo casuale.
Selection Sort
! " Nonostante l'approccio brutale adottato, ordinamento per selezione ha
un'importante applicazione: poiché ciascun elemento viene spostato al
più una volta, questo tipo di ordinamento è il metodo da preferire
quando si devono ordinare file costituiti da record estremamente grandi
e da chiavi molto piccole. Per queste applicazioni il costo dello
spostamento dei dati è prevalente sul costo dei confronti e nessun
algoritmo è in grado di ordinare un file con spostamenti di dati
sostanzialmente inferiori a quelli dell'ordinamento per selezione.
Esempio selection
67345
37645
34675
34576
34567
inizio
dopo for i=0
dopo for i =1
dopo for i=2
dopo for i = 3
Per capire meglio…. h0p://it.wikipedia.org/wiki/Selec8on_sort Insertion sort
Insertion Sort
! " 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.
! " Algoritmo in place, cioè ordina l'array senza doverne creare una copia,
risparmiando memoria.
Insertion 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
Insertion Sort
void insertion_sort(int[] A,int n) {
int i=0,j=0;
for (i=1;i<n;i++) {
int x=a[i], s=1, d=i-1;
while (s<=d) {
int m=(s+d)/2;
if (x<a[m]) d=m-1;
else s=m+1;
}
for (j=i-1,j>=s;j--) a[j+1]=a[j];
a[s]=x;
}
}
Insertion sort
..{ int i, j; int dati[N];!
for (i = 1; i <N; i++)!
for (j = i; j > 0; j--)!
if (dati[j]<dati[j-1])!
{/*scambia*/;!
temp = dati[j-1];!
dati[j-1]=dati[j];!
dati[j]= temp;!
}}!
Esempio insertion
67345
37645
34675
34576
34567
inizio
dopo for i=0
dopo for i =1
dopo for i=2
dopo for i = 3
Per capire meglio…. h0p://it.wikipedia.org/wiki/File:AnimazioneInser8onSort.gif Insertion Sort
! " Complessità:
-"
-"
Caso peggiore O(n2)
Caso migliore O(n) ! vettore già ordinato
! " Molto vantaggioso per vettori quasi ordinati
Bubble sort
Bubble Sort
! " L’algoritmo BUBBLE SORT (ordinamento a bolle) so basa sull’idea di
far emergere pian piano gli elementi più piccoli verso l’inizio
dell’insieme da ordinare facendo sprofondare gli elementi maggiori
verso il fondo:
-" un po’ come le bollicine in un bicchiere di acqua gassata ! da qui il
nome di ordinamento a bolle.
! " La strategia adottata è quella di scorrere più volte la sequenza da
ordinare, verificando ad ogni passo l’ordinamento reciproco degli
elementi contigui, ai e ai+1, ed eventualmente scambiando la posizione
di quelle coppie di elementi non ordinate.
Bubble Sort
! " Procedendo dall’inizio alla fine della sequenza, al termine di ogni
scansione si è ottenuto che l’elemento massimo è finito in fondo alla
sequenza stessa, mentre gli elementi più piccoli hanno cominciato a
spostarsi verso l’inizio della sequenza stessa.
! " Dunque alla fine della prima scansione possiamo essere certi che
l’elemento massimo ha raggiunto la sua posizione corretta nell’ultima
posizione della sequenza:
-" la scansione successiva potrà fermarsi senza considerare l’ultimo
elemento dell’insieme e riuscendo così a collocare nella posizione
corretta (la penultima) il secondo elemento più grande dell’insieme;
! " Si ripete fino ad aver completato l’ordinamento dell’intera sequenza.
Bubble Sort
void bubble_sort(int[] A, int n) {
bool scambio=true;
int ultimo=n-1,i=0;
while (scambio) {
scambio=false;
for (i=0;i<ultimo;i++) {
if (a[i]>a[i+1]) {
int temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
scambio=true;
}
}
ultimo--;
}
}
Bubblesort – ordinare array a
#include <stdio.h>!
# define! N 10!
main ()!
{
int pass, j, temp, a[N];!
/* lettura di a*/!
/* bubblesort a*/!
for (pass = 1; pass <N; pass++)!
for (j = 0; j <N-1; j++)!
if a[j] > a[j+1]!
{/* scambio*/!
temp = a[j] ; a[j] = a[j+1] ; a[j+1]=temp;!
}
/* stampa di a*/!
….!
}
sort
Bubble sort su array
N passate
Confronta un elemento con il successivo
Se il primo è minore o uguale, nulla
Se maggiore, scambia
Repeat
esempio:
originale:
passata 1:
passata 2:
passata 3:
34267
32467
23467
23467
Per capire meglio…. h0p://it.wikipedia.org/wiki/Bubble_sort Bubble Sort
! " Il numero di operazioni è:
(n-1) + (n-2) + … + 2 + 1 ! n(n-1)/2 ! O(n2)
Quick Sort
Quick Sort
! " Quicksort è un 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 un array si pongono gli elementi minori a
sinistra rispetto a questo e gli elementi maggiori a destra
-" La stessa procedura poi è richiamata in modo ricorsivo sui due sotto
insiemi
! " Il Quicksort, termine che tradotto letteralmente in italiano indica
ordinamento rapido, è l'algoritmo di ordinamento che ha, in generale,
prestazioni migliori tra quelli basati su confronto.
Approccio ricorsivo
! " L'idea base può esprimersi agevolmente in termini ricorsivi.
-"
-"
Ad ogni stadio si effettua un ordinamento parziale di una sequenza di
oggetti da ordinare. Assunto un elemento come perno dello stadio, si
confrontano con esso gli altri elementi e si posizionano alla sua
sinistra i minori e a destra i maggiori, senza tener conto del loro
ordine. Dopo questo stadio si ha che il perno è nella sua posizione
definitiva.
Successivamente si procede in modo ricorsivo all'ordinamento
parziale delle sottosequenze di elementi rimasti non ordinati, fino al
loro esaurimento.
Quick Sort
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]);
}
Quick Sort
l--;
swap(array[begin], array[l]);
sort(array, begin, l);
sort(array, r, end);
}
}
Merge Sort
Merge Sort
! " Il merge sort è un algoritmo di ordinamento molto intuitivo e
abbastanza rapido, che utilizza un processo di risoluzione ricorsivo.
! " L'idea alla base del merge sort è il procedimento Divide et Impera, 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.
Due fasi
! " Fase 1: divide
-"
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 primo ha un elemento in meno del secondo.
! " Fase 2: impera
-"
Supponendo di avere due sequenze già ordinate. Per unirle,
l'algoritmo mergesort estrae ripetutamente il minimo delle due
sequenze in ingresso e lo pone in una sequenza in uscita.
Merge
void merge (int[] a, int left, int center, int right)
int i = left, j=center + 1,k=0; int[] b;
while ((i <= center) && (j <= right)) {
if (a[i] <= a[j]){
b[k]=a[i];
i=i + 1;
} else {
b[k] = a[j];
j=j + 1;
}
k=k + 1;
}
Merge (continua)
for (k =left ;k<right;k++) {
a[k] = b[k - left];
}
Merge Sort
void mergesort (int[] a, int left, int right) {
int center;
if (left < right) {
center = (left + right) / 2;
mergesort(a, left, center);
mergesort(a, center+1, right);
merge(a, left, center, right);
}
Merge Sort
! " Complessità:
-"
Caso peggiore ! O(n log n)
! " Richiede memoria aggiuntiva per O(n)
Scarica