Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare

Slides:



Advertisements
Presentazioni simili
Uso avanzato di C.
Advertisements

Ricorsione Procedure e funzioni ricorsive. Definizioni Un oggetto si dice ricorsivo se è definito totalmente o parzialmente in termini di sé stesso La.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Ordinamenti lineari.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Ordinamenti lineari.
Mergesort1 if (n>1) /* la collezione contiene almeno due elementi. */ {1. Dividi la collezione in due di circa la metà degli elementi. 2. chiamata ricorsiva.
CORSO DI PROGRAMMAZIONE II
Progetto di algoritmi: metodologia "Divide et Impera"
APPUNTI SUL LINGUAGGIO C
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)
void binario(int n); …………………
Massimo Comun Divisore
Esercizi La distanza di hamming tra due interi x e y si definisce come il numero di posizioni nella rappresentazione binaria di x e y aventi bit differenti.
28 ottobre Mergesort F. Bombi 28 ottobre 2003.
Teoria degli algoritmi e della computabilità Terza giornata: Ricerca e ordinamento ottimi. P vs NP, algoritmi di approssimazione, e il potere della randomizzazione.
Algoritmi CHE COS’è UN ALGORITMO di ORDINAMENTO?
ALGORITMI Un algoritmo è un insieme di istruzioni: -ordinate -non ambigue -effettivamente computabili.
Array (ordinamento) CORDA – Informatica A. Ferrari.
alberi completamente sbilanciati
#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.
GLI ALGORITMI VISIBILE SUL BLOG INFORMATICA ANNO SCOLASTICO 2013 / 2014 GABRIELE SCARICA 2°T.
Algoritmi e Strutture Dati
Paola Disisto, Erika Griffini, Yris Noriega.  Insieme ordinato di operazioni non ambigue ed effettivamente computabili che, quando eseguito, produce.
Problema dell’Ordinamento. Problema dell’ordinamento Formulazione del problema –Si vuole ordinare una lista di elementi secondo una data proprietà P Esempio:
L’ALGORITMO Un algoritmo è un procedimento formale che risolve un determinato problema attraverso un numero finito di passi. Un problema risolvibile mediante.
Divide et Impera Parte 11 - Risoluzione di problemi per divisione in sottoproblemi “bilanciati” Corso A: Prof. Stefano Berardi
1 Elementi DI INFORMATICA Università degli Studi di Cagliari Corso di Laurea in Ingegneria Elettronica Linguaggio C A.A. 2011/2012
1 ELEMENTI DI INFORMATICA Università degli Studi di Cagliari Corso di Laurea in Ingegneria Elettronica Linguaggio C A.A. 2011/2012
Esercitazioni di Prog. II (esercizi su alberi ennari)
Progettare algoritmi veloci usando strutture dati efficienti
Progettare algoritmi veloci usando strutture dati efficienti
Ordinamento.
10. Programmazione Ricorsiva Ing. Simona Colucci
Le postcondizioni specificano l’output della funzione.
Usi (meno scontati) della visita DFS
Algoritmi e Strutture Dati
Divide et Impera Quicksort Mergesort
Programmazione e Laboratorio di Programmazione
Programmazione e Laboratorio di Programmazione
Programmazione e Laboratorio di Programmazione
Scrivere programmi corretti
Ricorsione 16/01/2019 package.
Programmazione e Laboratorio di Programmazione
Algoritmo InsertionSort
Programmazione e Laboratorio di Programmazione
Schema generale, visita in ampiezza e profondità.
Alberi n-ary Lezioni di C.
Algoritmi Avanzati a.a.2011/2012 Prof.ssa Rossella Petreschi
Usi (meno scontati) della visita DFS
APPUNTI SUL LINGUAGGIO C
Progettare algoritmi veloci usando strutture dati efficienti
esercizi alberi binari
APPUNTI SUL LINGUAGGIO C
comprensione e modifica di codice
L’algoritmo MergeSort
APPUNTI SUL LINGUAGGIO C Implementazioni di Liste Concatenate
APPUNTI SUL LINGUAGGIO C Esercizi sugli array e strutture
comprensione e modifica di codice
APPUNTI SUL LINGUAGGIO C
Programmazione e Laboratorio di Programmazione
Programmazione e Laboratorio di Programmazione
MergeSort Usa la tecnica del divide et impera:
concetti ed applicazioni
Programmazione e Laboratorio di Programmazione
Ricerca 01/08/2019 package.
HeapSort Stesso approccio incrementale del selectionSort Tipo di dato
Programmazione e Laboratorio di Programmazione
Programmazione e Laboratorio di Programmazione
Programmazione e Laboratorio di Programmazione
Programmazione e Laboratorio di Programmazione
Corso di Fondamenti di Informatica
Transcript della presentazione:

Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare (Prof. Emerito alla Oxford University) Computer Jurnal 5,1,1962 John von Neumann(1903-1957) Nel 1944, il suo rapporto interno “First Draft of a Report on the EDVAC” contiene tra l’altro, il mergesort come programma di ordinamento

Esempio di algoritmo basato su Divide et Impera Due fasi: MergeSort Esempio di algoritmo basato su Divide et Impera Due fasi: Fase di suddivisione Divide il lavoro a metà Fase di ordinamento (fusione) Impera sulle due metà!

MergeSort Dividi Dividi la lista in due metà Metà destra Metà sinistra

MergeSort Impera 1 Applica lo stesso algoritmo a ogni metà Metà sinistra Metà destra Nuove chiamate

MergeSort Impera 2 (a partire da quando si ha un solo elemento o nessuno) fondi Metà sinistra ordinata Metà destra ordinata fondi

2 3 7 4 9 1 5 Dividi 2 3 7 4 9 1 5 Dividi 2 3 7 4 9 1 5 Dividi 9 1 5 7 4 2 3 fondi 2 3 4 7 1 9 5 fondi 2 3 4 7 1 5 9 fondi 1 2 3 4 5 7 9

Pseudocodice per il mergesort if “ci sono almeno due elementi da ordinare” {1. dividi la sequenza in due metà. 2. chiamata ricorsiva di mergesort per la prima metà . 3. chiamata ricorsiva di mergesort per la seconda metà. 4. fusione (quindi ordinamento) delle due metà ordinate. }

su una lista concatenata L: if (L) /* la lista non è vuota. */ {If (L-> next) { 1. dividi la lista in due metà. /* costo lineare */ 2. chiamata ricorsiva di mergesort per la prima metà . 3. chiamata ricorsiva di mergesort per la seconda metà. 4. fusione (merging) delle due metà ordinate. } /* costo lineare, opera in loco */ }

su un vettore di n elementi: if (n>1) /* ci sono almeno due elementi. */ {1. Dividi il vettore in due metà. /*Facile: costo costante */ 2. chiamata ricorsiva di mergesort per la prima metà . 3. chiamata ricorsiva di mergesort per la seconda metà. 4. fusione (merging) delle due metà ordinate /* necessita di un vettore di appoggio */ }

Implementazione su vettori: void mergeSort (int *v,int* app,int start, int end) /* ordina, in modo crescente il vettore v di end - start+ 1 elementi, inizialmente start = 0 e end = numero di elementi -1 *prec: v!= NULL && app != NULL postc: v[i]<=v[i+1], per start <=i<end*/ { int middle; if (start < end) /* ci sono almeno 2 elementi */ { middle = (start + end) / 2; /* calcola il punto mediano */ mergeSort (v,app,start, middle); /* ordina la prima metà */ mergeSort (v,app,middle+1, end); /* ordina la seconda metà */ merge (v, app,start, middle, end); /* fonde le due metà ordinate */ }

void merge(int * v, int * app,int start, int middle, int end) /* fonde i sottovettori v[start..middle] e v[middle..end], restituendo il risultato in v. *prec: v[i]<=v[i+1] per start <= i < middle e * v[j]<=v[j+1] per middle +1 <= j < end postc: v[i]<=v[i+1] per start <= i < end */*/ {int k = start , i = middle +1 , j = start;/* k è l'indice di scorrimento della prima metà, i della seconda, j del vettore d’appoggio app */ while ((k <= middle) && (i <= end)) { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo , bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}   while (j <= end); /*altrimenti l'uscita dal ciclo 1 si è avuta per (k > middle): gli elementi v[p],...,v[end] sono già al posto giusto, quindi si ricopia solo app in v */  for (k = start;k < j; k++) v[k] = app[k];

Chiamata merge(v,app,0,3, 7); uscita (i > end) 20 40 80 90 10 30 60 70 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}   while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 0 1 2 3 4 5 6 7 j v= 20 40 80 90 10 30 60 70 0 1 2 3 4 5 6 7 k i

Chiamata merge(v,app,0,3, 7); uscita (i > end) 20 40 80 90 10 30 60 70 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}   while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 20 0 1 2 3 4 5 6 7 j v= 20 40 80 90 10 30 60 70 0 1 2 3 4 5 6 7 k i

Chiamata merge(v,app,0,3, 7); uscita (i > end) 20 40 80 90 10 30 60 70 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}  while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 20 30 0 1 2 3 4 5 6 7 j v= 20 40 80 90 10 30 60 70 0 1 2 3 4 5 6 7 k i

Chiamata merge(v,app,0,3, 7); uscita (i > end) 20 40 80 90 10 30 60 70 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}   while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 20 30 40 0 1 2 3 4 5 6 7 j v= 20 40 80 90 10 30 60 70 0 1 2 3 4 5 6 7 k i

Chiamata merge(v,app,0,3, 7); uscita (i > end) 20 40 80 90 10 30 60 70 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}  while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 20 30 40 60 0 1 2 3 4 5 6 7 j v= 20 40 80 90 10 30 60 70 0 1 2 3 4 5 6 7 k i

Chiamata merge(v,app,0,3, 7); uscita (i > end) 20 40 80 90 10 30 60 70 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}   while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 20 30 40 60 70 0 1 2 3 4 5 6 7 j v= 20 40 80 90 10 30 60 70 0 1 2 3 4 5 6 7 k i

Chiamata merge(v,app,0,3, 7); uscita (i > end) 20 40 80 90 10 30 60 70 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}   while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 20 30 40 60 70 80 90 0 1 2 3 4 5 6 7 j

Chiamata merge(v,app,0,3, 7);uscita (k > middle) 20 50 60 70 10 30 80 90 while ((k <= middle) && (i <= end)) /*ciclo 1*/ { if (v[k] <= v[i])    {app[j] = v[k]; k++;} else    {app[j] = v[i];i++;}   j++; }  if (k <= middle) /* (i > end) ha provocato l'uscita dal ciclo 1, bisogna aggiungere in coda gli ultimi elementi nella prima metà */ do {app[j] = v[k]; j++;k++;}   while (j <= end); 0 1 2 3 4 5 6 7 k i app= 10 20 30 50 60 70 0 1 2 3 4 5 6 7 k> middle j v= 10 20 30 50 60 70 80 90  for (k = start;k < j; k++) v[k] = app[k]; 0 1 2 3 4 5 6 7 k i

int verificaOrd(const int *a, const int n) /* controlla se il vettore è ordinato * postc: dà 1 se v[i]<= v[i+1] per 0 <= i < n-1 e 0 altrimenti */ {int i; for(i=0;i< n-1;i++) if (a[i] > a[i+1]) return 0; return 1; } int* inVett(const int num) /*restituisce un vettore inizializzato con interi pseudocasuali*/ {int i, *vett; vett = malloc(num*sizeof(int)); srand(time(NULL)); for (i = 0;i < num;i++) vett[i] = rand()%129 ; return vett;}

main() {int num, j,numTest; int* app,* vett; printf("Inserisci il numero di test da effettuare.\n"); scanf("%d",&numTest); for (j=0;j<numTest;j++) {printf("Inserisci il numero di elementi del vettore.\n"); scanf("%d",&num); app = (int*)malloc(num*sizeof(int)); vett = inVett(num); printf("Gli elementi scelti a caso e inseriti nel vettore sono:\n"); stVett(vett,num); mergeSort(vett,app,0,num-1); assert(verificaOrd(vett,num)); printf("Gli elementi ordinati nel vettore sono:\n"); printf("Tutto bene con il mergeSort.\n"); } return 0;