CORSO DI PROGRAMMAZIONE II

Slides:



Advertisements
Presentazioni simili
Algoritmi e Strutture Dati
Advertisements

                      Insertion-Sort
Preincremento e PostIncremento in C++
Puntatori in C e C++.
Ricorsione Procedure e funzioni ricorsive. Definizioni Un oggetto si dice ricorsivo se è definito totalmente o parzialmente in termini di sé stesso La.
Iterazione while – do while - for.
Procedure e funzioni A. Ferrari.
Linguaggio C++ Operatori – numeri pseudocasuali - costanti.
Numeri casuali.
Procedure e funzioni In linguaggio C.
Introduzione ad Array e Funzioni 2IC/2ID – a. s.2012/13.
Generazione di numeri casuali in Dev C++
I DATI LE ISTRUZIONI LE STRUTTURE FONDAMENTALI
Le funzioni.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Ordinamenti ottimi.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
Heap Sort. L’algoritmo heap sort è il più lento di quelli di ordinamento O(n * log n) ma, a differenza degli altri (fusione e quick sort) non richiede.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Usa la tecnica del.
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.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl Capitolo 4 Ordinamento:
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Capitolo 4 Ordinamento: Heapsort Algoritmi e Strutture Dati.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
CORSO DI PROGRAMMAZIONE II
CORSO DI PROGRAMMAZIONE II
Algoritmi e Strutture Dati Introduzione. Gli argomenti di oggi Analisi della bontà degli algoritmi Modello Computazionale Tempo di esecuzione degli algoritmi.
Algoritmi e Strutture Dati III. Algoritmi di Ordinamento
Progetto di algoritmi: metodologia "Divide et Impera"
07/04/2003Algoritmi Ricerca in una sequenza di elementi Data una sequenza di elementi, occorre verificare se un elemento fa parte della sequenza oppure.
Lalgoritmo MergeSort Applica la strategia del divide et impera Divide: suddivide la sequenza di n elementi data in due sottosequenze di n/2 elementi Impera:
Politecnico di Milano Esercizi Preparazione alla prima prova intermedia.
Esercizio 10.* Un cassiere vuole dare un resto di n centesimi di euro usando il minimo numero di monete. a) Descrivere un algoritmo goloso per fare ciò.
Problema dell’ordinamento di un array: Il metodo Bubble Sort.
30 ottobre Mergesort F. Bombi 30 ottobre 2002.
Radix-Sort(A,d) // A[i] = cd...c2c1
Università degli Studi di BresciaA.A. 2012/2013 Fondamenti di Programmazione Docente: Alessandro SaettiA.A. 2012/2013 Università degli Studi di Brescia.
void binario(int n); …………………
Creazione progetto in C++/DEV
Massimo Comun Divisore
Passaggio di parametri per indirizzo
28 ottobre Mergesort F. Bombi 28 ottobre 2003.
ALGORITMI a.
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.
Algoritmi di Ordinamento
Algoritmi CHE COS’è UN ALGORITMO di ORDINAMENTO?
Array (ordinamento) CORDA – Informatica A. Ferrari.
#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.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE La Ricorsione Marco D. Santambrogio – Ver. aggiornata al 21 Maggio 2014.
GLI ALGORITMI VISIBILE SUL BLOG INFORMATICA ANNO SCOLASTICO 2013 / 2014 GABRIELE SCARICA 2°T.
Top STACK Top Le operazioni fondamentali che si fanno sugli stack sono: riempimento e svuotamento. Questo implica che durante lo svolgimento del programma.
TECNICA DIVIDE ET IMPERA
Ordinamento in tempo lineare Il limite inferiore Ω(n log n) vale per tutti gli algoritmi di ordinamento generali, ossia per algoritmi che non fanno alcuna.
Algoritmi e Strutture Dati
Paola Disisto, Erika Griffini, Yris Noriega.  Insieme ordinato di operazioni non ambigue ed effettivamente computabili che, quando eseguito, produce.
CORSO DI PROGRAMMAZIONE II
Procedure e funzioni In linguaggio C.
Lo strano mondo degli algoritmi di ordinamento Algoritmi.
Lezione 8 Ricorsione Code.
1 Informatica Generale Marzia Buscemi Ricevimento: Giovedì ore , Dipartimento di Informatica, stanza 306-PS o per posta.
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:
GLI ALGORITMI DI ORDINAMENTO
L’ALGORITMO Un algoritmo è un procedimento formale che risolve un determinato problema attraverso un numero finito di passi. Un problema risolvibile mediante.
Capitolo 4 Ordinamento: lower bound Ω(n log n) e MergeSort ((*) l’intera lezione) Algoritmi e Strutture Dati.
Divide et Impera Parte 11 - Risoluzione di problemi per divisione in sottoproblemi “bilanciati” Corso A: Prof. Stefano Berardi
Algoritmi e Strutture Dati Università di Camerino Corso di Laurea in Informatica (12 CFU) I periodo didattico Emanuela Merelli
Operatori – numeri pseudocasuali - costanti
Transcript della presentazione:

CORSO DI PROGRAMMAZIONE II Lezione 10 Merge sort prof. E. Burattini a.a. 2010-2011

MERGE - SORT Un algoritmo di sort classico ha in genere una complessità di calcolo pari a O(N2). Vediamo un algoritmo che, fondato sul criterio del DIVIDE ET IMPERA, ha una complessità più bassa. Il merge-sort è fondato sul principio ricorsivo di ridurre il problema di partenza di un fattore 2 e nessun processo ricorsivo attivato viene fatto più di una volta.

Merge-sort. Dato un array A di dimensioni N, che si vuole ordinare, lo si suddivide in due sub-array ciascuno di dimensioni N/2. I due sub-array così ottenuti vengono a loro volta divisi a metà. Il processo termina quando ogni sub-array prodotto contiene un solo elemento. Si consideri l’esempio seguente:

3 5 2 6 4 1 7 3 5 2 6 4 1 7 1 2 3 5 6 4 7 1 2 3 5 6 4 7 5 3 6 2 1 4 7 5 3 6 2 1 4 7 4 7 5 6 2 3 1 4 7 5 6 2 3 1

Si parte con la richiesta di ordinare gli elementi dell’array compresi tra 0 e N, si riduce poi questo intervallo attraverso due variabili Lo e Hi fino a quando nel subarray non resta che un elemento. Questo è ovviamente ordinato e quindi si attiva la catena pop. Per dividere i Subarrays usiamo una variabile locale Mid. Questi Subarrays saranno prima ordinati (sorted) o poi fusi (merged). CASO BASE si ha quando i due subarrays sono ridotti ad una sola variabile cioè sono banalmente ordinati. Quando si arriva al Caso Base allora si attiva il processo di Merge tra i due arrays adiacenti rimasti. Se invece siamo in presenza di subarrays con più di un elemento questo implica che il subarray deve essere ordinato.

Lo pseudo codice per l’algoritmo di sort è il seguente: void SortIt(int Lo, Hi, int AnArray[]); usa i valori degli indici in input (Lo,Hi) per dividere AnArray in due subarray (inferiore e superiore) if gli indici del subarray inferiore implicano un array ordinabile SortIt(usa come indici quelli del subarray inferiore ,AnArray) if gli indici del subarray superiore implicano un array ordinabile SortIt(usa come indici quelli del subarray superiore ,AnArray) Inizialmete avremo: SortIt(0, N-1, AnArray) Di seguito si mostra l’albero ricorsivo per un array di 8 elementi

7 6 3 1 2 4 5 3 5 2 6 4 1 7 Sort(0,7) Sort(0,3) Sort(4,7) Sort(0,1)

// Mergesort #include <iostream> #include <cstdlib> #include "InsertArray.h" using namespace std; // PROTOTIPI void SortIt(int, int, int [], int); void Update(int [],int &, int &); void Merge(int, int, int, int [], int); // DEFINIZIONI void SortIt(int Lo, int Hi,int AnArray[], int N) { int Mid; Mid=(Lo+Hi)/2; if (Lo < Mid) { SortIt(Lo,Mid,AnArray, N); } if ((Mid+1) < Hi) { SortIt(Mid+1,Hi,AnArray, N); Merge(Lo,Mid,Hi,AnArray, N); }; int main() { int Lo=0; int Hi,N; cout<<" Quanti numeri vuoi ordinare? "; cin>>Hi; N=Hi; int AnArray[Hi]; int I, Mid; cout<<"VETTORE DA ORDINARE "<<endl; for (I=0;I<Hi;I++) AnArray[I]=rand()%10; cout<<endl; StampaVettore (AnArray, N, 'A'); SortIt(Lo,Hi-1,AnArray, N); cout<<" VETTORE ORDINATO\n"<<endl; system("pause"); }

Inserisci l’elemento più piccolo e incrementa opportunamente l’indice void Merge(int Lo,int Mid,int Hi, int AnArray[], int N) { int Temp[N]; int Index, I1, I2; I1=Lo; I2=Mid+1; for (Index=Lo;Index<=Hi;Index++) { if (I1 > Mid ) { Temp[Index]=AnArray[I2]; I2=I2+1; } else { if (I2 > Hi) { Temp[Index]=AnArray[I1]; I1=I1+1; } else { if (AnArray[I1] < AnArray[I2]) { I1=I1+1; } I2=I2+1; } } Se è stata controllata tutta la prima metà allora aggiungi direttamente la seconda Se è stata controllata tutta la seconda metà allora aggiungi direttamente la prima Inserisci l’elemento più piccolo e incrementa opportunamente l’indice for (Index=Lo; Index<=Hi; Index++) AnArray[Index]=Temp[Index]; } Allegato mergesort

Sort(0,7) 1 2 3 4 5 6 7 Sort(4,5) 5 7 6 2 5 4 3 1 1 2 3 4 5 6 7 Sort(0,3) Sort(0,1) merge 5 7 2 5 6 7 Sort(2,3) 5 7 2 6 Sort(4,7) Sort(6,7) 2 5 6 7 1 3 4 2 5 6 7 4 2 5 6 7 4 1 3 1 2 3 4 5 6 7 void SortIt(int Lo, int Hi,int AnArray[]) { int Mid; Mid=(Lo+Hi)/2; if (Lo < Mid) { SortIt(Lo,Mid,AnArray); } if ((Mid+1) < Hi) { SortIt(Mid+1,Hi,AnArray); } Merge(Lo,Mid,Hi,AnArray); }; 3 4 7 7 Stack della ricorsione

Svantaggi del Merge-Sort Necessita di un vettore di appoggio Effettua gli spostamenti anche se il vettore di partenza è già ordinato

Complessità del MERGE-SORT I livelli dell’albero di sort sono log N. Ad ogni livello dell’albero si fa un merge di N elementi, quindi in totale la complessità è data da N*log2 N 3 5 2 6 4 1 7 Livello N° Array   1 20 2 21 …… …….. …. K N 2k N° passi = K*N dove K=log2N

Scrivere un programma che con due funzioni ricorsive dica: Esercizio Dato un Array del tipo Scrivere un programma che con due funzioni ricorsive dica: 1 - Dato X chi è il padre e la madre di X 2 - Dato X determini chi è il nonno e la nonna di Y FIGLIO PADRE MADRE M U R A G C N B P I

// PROTOTIPI void leggi_dati(char[ ][3],int,int); void scrivi_dati(char[ ][3],int,int); char CercaPadre(char [ ][3], char , int ,int ,int ); char CercaNonno(char [ ][3], char , int ,int ,int ); // MAIN int main () { int rig=5; int col=3; char mat[5][3]; char X; cout<<"FIGLIO PADRE MADRE"<<endl; leggi_dati(mat,rig,col); scrivi_dati(mat,rig,col); cout<<"Dammi figlio ";cin>>X; cout<<"Il padre di "<<X<<" e' "<<CercaPadre(mat,X, rig,0,1)<<endl;; cout<<"La madre di "<<X<<" e' "<<CercaPadre(mat,X, rig,0,2)<<endl; cout<<"Il padre del padre di "<<X<<" e' "<<CercaNonno(mat,X, rig,0,1)<<endl; cout<<"La madre della madre di "<<X<<" e' "<<CercaNonno(mat,X, rig,0,2)<<endl; system("pause"); }

char CercaPadre(char a[][3], char x, int Nfam,int i,int j) // DEFINIZIONI char CercaPadre(char a[][3], char x, int Nfam,int i,int j) // determina chi è il padre di X} { if (i>Nfam ) return 'i'; else if (a[i][0]==x) return a[i][j]; return CercaPadre(a,x, Nfam,i+1,j); } char CercaNonno(char a[][3], char x, int Nfam,int i,int j) // determina chi è il genitore di X} return CercaPadre(a,a[i][j], Nfam,0,j); return CercaNonno(a,x, Nfam,i+1,j); Allegato: eserAvi

Data una matrice di interi NxN scrivere una funzione ricorsiva che valga TRUE se la somma degli elementi di ogni riga è minore della riga precedente e la somma degli elementi di ogni colonna è maggiore della somma della colonna precedente, FALSE altrimenti. 1 3 2 5 8 4 7 9 6 FALSE 2 3 6 5 1 4 TRUE

Data una matrice di interi NxN scrivere una funzione ricorsiva che valga TRUE se la somma degli elementi di ogni riga è minore della riga precedente e la somma degli elementi di ogni colonna è maggiore della somma della colonna precedente, FALSE altrimenti. FALSE TRUE 1 3 2 5 8 4 7 9 6 2 3 5 6 1 4 bool verifica (int a[][N], int N1, int &sr1,int &sr2,int &sc1,int &sc2,int i,int j) { if (i>=N1-1) {cout<<"CONDIZIONI SODDISFATTE"<<endl; return true; } else if (j<N1) { sr1=sr1+a[i][j]; sr2=sr2+a[i+1][j]; sc1=sc1+a[j][i]; sc2=sc2+a[j][i+1]; verifica2(a,N1,sr1,sr2,sc1,sc2,i,j+1); } if ((sr2<sr1)&&(sc2>sc1)) { sr1=0;sr2=0;sc1=0;sc2=0; verifica2(a,N1,sr1,sr2,sc1,sc2,i+1,0); {cout<<"CONDIZIONI NON SODDISFATTE"<<endl; return false;}

Se Sl=‘Smacchiare’ e S2=‘Macchia’ allora la funzione vale TRUE. ESERCIZIO Scrivere un algoritmo ricorsivo per il calcolo della funzione booleana tale che assegnati due array di caratteri Sl e S2 restituisca TRUE se il secondo è contenuto tutto o in parte nel primo. FALSE altrimenti. Esempio: Se Sl=‘Smacchiare’ e S2=‘Macchia’ allora la funzione vale TRUE. Se Sl='Mentecatto' e S2=’tatto' allora la funzione vale FALSE stud ok

ESERCIZIO Date due matrici A(nxn) e B(nxn) di interi scrivere una funzione ricorsiva booleana che calcoli la somma di tutti i numeri contenuti in A sottratti a quelli contenuti in B e dica se la differenza è negativa .