Ripasso di programmazione ricorsiva

Documenti analoghi
Esercizi su programmazione ricorsiva 3

Esercizi su programmazione ricorsiva 1. Pericle Perazzo 23 marzo 2012

PROGRAMMAZIONE II canale A-D luglio 2008 TRACCIA DI SOLUZIONE

d. Cancellazione del valore 5 e. Inserimento del valore 1

Appunti Senza Pretese di Programmazione II: Costruzione di un Albero Bilanciato

Laboratorio di Informatica. Lezione 8: Liste e alberi

Alberi binari di ricerca

Alberi. Alberi: definizioni. Alberi Binari. Esercizi su alberi binari: metodi ricorsivi. Struttura dati per alberi generici. ASD-L - Luca Tesei

Implementazione dell albero binario in linguaggio C++

Note per la Lezione 4 Ugo Vaccaro

ALBERI : introduzione SOMMARIO ALBERI ALBERI. ALBERI: introduzione ALBERI BINARI: introduzione VISITE RICORSIVE DI ALBERI

L albero e un tipo astratto di dati usato per rappresentare relazioni gerarchiche.

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Esercizio 1. FONDAMENTI DI INFORMATICA II Algoritmi e Strutture dati a.a 2015/16 14 giugno 2016

Alberi binari e alberi binari di ricerca

Alberi. Strutture dati: Alberi. Alberi: Alcuni concetti. Alberi: definizione ricorsiva. Alberi: Una prima realizzazione. Alberi: prima Realizzazione

Esercitazione 6. Alberi binari di ricerca

Esercitazione 8. Corso di Tecniche di programmazione. Laurea in Ingegneria Informatica

Informatica 3. Informatica 3. LEZIONE 14: Alberi binari: introduzione. Lezione 14 - Modulo 1. Definizioni. Introduzione. Definizioni e proprietà

GLI ALBERI BINARI DI RICERCA. Cosimo Laneve

Alberi binari di ricerca

Alberi binari e alberi binari di ricerca

Esame di Algoritmi e Strutture Dati Corso di Laurea in Ingegneria Informatica Canali A-L, M-Z

Espressioni aritmetiche

ricerca di un elemento, verifica dell appartenenza di un elemento

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Algoritmi e Strutture dati - ANNO ACCADEMICO 2016/17 25 luglio 2017

Alberi binari e alberi binari di ricerca

Alberi Binario in Java

23/10/2016. gli alberi. alcune definizioni. un esempio. LABORATORIO DI PROGRAMMAZIONE 2 Corso di laurea in matematica.

Algoritmi e Strutture dati - ANNO ACCADEMICO 2017/18 12 giugno 2018

Albero Binario GT 7.3. interfacce di Positio<E>, Tree<E>, e BinaryTree<E>; il file TestLinkedBinaryTree.java

Indice come albero binario di ricerca!

Alberi. Definizione, realizzazione e algoritmi elementari. Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 7

Organigramma Gerarchia. (Tree) Nessuna persona può avere più di un superiore Ogni persona può essere superiore di altre

Algoritmi e strutture dati 16 Dicembre 2004 Canali A L e M Z Cognome Nome Matricola

Alberi. Alberi: Esempio di utilizzo

Algoritmi e Strutture di Dati

Moltiplicazione veloce di interi

cout << "Inserisci un numero:" << endl; cin >> n; ris = n*2; cout << "Il doppio di " << n << " e " << ris << endl;

Algoritmi e Strutture Dati. Lezione 3

Lezione 7 Alberi binari: visite e alberi di ricerca

ALBERI BINARI DI RICERCA

Strutture dati Alberi binari

Laboratorio di Algoritmi e Strutture Dati. Alberi Binari

Prova di Algoritmi e s.d. (1o anno) 7 Febbraio TESTO e RISPOSTE

Alberi e alberi binari I Un albero è un caso particolare di grafo

Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione

Il numero dei nodi al livello i è 1, per 0 i altezza L altezza h di un albero completamente sbilanciato con n nodi è h = n-1

FONDAMENTI DI INFORMATICA II (2h, punti 30/30) 26 Luglio 2011

ricerca di un elemento, verifica dell appartenenza di un elemento

Laboratorio di Algoritmi

Lezione 12 Tabelle Hash

Algoritmi e Strutture dati - ANNO ACCADEMICO 2016/17 13 giugno 2017

Informatica 3. LEZIONE 17: Alberi generici. Modulo 1: Definizione e ADT Modulo 2: Implementazione Modulo 3: Alberi e classi di equivalenza

Esempi. Albero di interi. Struttura che non è un albero!

ALBERI DI RICERCA BINARI (O ALBERI BINARI DI RICERCA)

ADT ALBERO BINARIO (tree)) ADT ALBERO BINARIO

Per semplicità eliminiamo le ripetizioni nell'albero.

alberi completamente sbilanciati

Correzione prima esercitazione: metodo distinct

Divide et impera su alberi

Esercizi parte 3. La classe ArrayBinTree dovra implementare, tra le altre, l operazione seguente: padre: dato un nodo, restituire l indice del padre.

Alberi. CORDA Informatica. A. Ferrari. Testi da. Marco Bernardo Edoardo Bontà. Dispense del Corso di. Algoritmi e Strutture Dati

Alberi ed Alberi Binari

Un albero completamente bilanciato o pieno (full) alberi completamente sbilanciati. Un albero binario completo

Lezione 9 Alberi binari: visite ed esercizi

ALGORITMI E STRUTTURE DATI

Alberi e alberi binari I Un albero è un caso particolare di grafo

Implementazione ADT: Alberi

Prima prova in itinere di Informatica 3 IOL Prof.ssa Sara Comai A.A dicembre 2004

Alberi Binari di Ricerca

Esercizio. 2 i=i*2) j=j*2)

Prova di Algoritmi e s.d. (1o anno) 17 Settembre TESTO e RISPOSTE

Informatica 3. Informatica 3. LEZIONE 17: Alberi generici. Lezione 17 - Modulo 1. Introduzione. ADT dell albero generico.

Dati e Algoritmi I (Pietracaprina) Esercizi su Alberi Binari di Ricerca e (2,4)-Tree

now is the for men all good come aid

Esercitazione 4 Algorithmi e Strutture Dati (Informatica) A.A 2015/2016

Notare come questo schema ricalchi una tipica dimostrazione per induzione. Ció noné casuale in quanto un algoritmo ricorsivo altri non éche una dimost

Alberi ed Alberi Binari di Ricerca

Albero in cui ogni nodo ha al più due figli. I figli di un nodo costituiscono una coppia ordinata

Heap e Code di Priorità

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Algoritmi e Strutture Dati. Lezione 4

Esercizio 1. E vero che in un AVL il minimo si trova in una foglia o nel penultimo livello? FB = -1. livello 0 FB = -1. livello 1 FB = -1.

Laboratorio di algoritmi e strutture dati

Algoritmo di ordinamento sul posto che ha tempo di esecuzione :

Strutture dati dinamiche in C (II)

Una definizione induttiva di albero binario astratto. Algoritmi e Laboratorio a.a Lezioni. Notazione lineare infissa per alberi binari.

Laboratorio di Programmazione II Corso di Laurea in Bioinformatica Dipartimento di Informatica - Università di Verona

ESERCITAZIONI DI INTRODUZIONE AGLI ALGORITMI (A.A. 08/09)

Alberi binari (radicati e ordinati) della radice Il padre del nodo 5 e del nodo 3

Algoritmi e Strutture Dati. Lezione 5

ALBERI. Angelo Di Iorio Università di Bologna

Lezione 6: 12 Novembre 2013

INFORMATICA 3 Prof.ssa Sara Comai

Esercitazione su Albero Binario

Appunti senza pretese di P2+Lab: Pensare ricorsivamente, programmare iterativamente, parte II: Implementazione iterativa di Mergesort

Transcript:

Ripasso di programmazione ricorsiva Ripasso di programmazione ricorsiva Algoritmo ricorsivo: algoritmo espresso in termini di se stesso. Programmazione iterativa e programmazione ricorsiva sono equivalenti. Vantaggi/svantaggi rispetto a programmazione iterativa: Ricorsione è meno efficiente, ma è più semplice ed elegante per risolvere alcuni problemi (divide-et-impera, alberi) Condizioni necessarie per la correttezza: presenza di uno o più casi base convergenza verso i casi base La programmazione iterativa è in generale più efficiente della programmazione ricorsiva, perché l'invocazione di una funzione è un'operazione poco efficiente. Tuttavia, la programmazione ricorsiva risulta più semplice nel caso di algoritmi divide-et-impera e di algoritmi che operano su strutture dati gerarchiche, come gli alberi binari e gli alberi generici. Programmare in modo iterativo in questi casi è possibile ma produrrebbe codice complesso e poco comprensibile.

Ripasso di programmazione ricorsiva Relazioni di ricorrenza divide-et-impera T n = d T n = hn k at n b con n n con n n T n O n k T n O n k log n T n O n log ba sea b k sea=b k sea b k

Albero binario Definizione: Un insieme vuoto di nodi è un albero binario Un nodo p, più un albero binario B s (sottoalbero sinistro) e un albero binario B d (sottoalbero destro) è un albero binario

Classe IntBinTree IntBinTree realizza un semplice albero binario di interi ( IntBinTree.h, IntBinTree.cpp ) Ogni elemento è rappresentato da una struttura Node, che contiene: L'etichetta (int info), Il puntatore all'elemento di sinistra (Node* left), Il puntatore all'elemento di destra (Node* right) All'interno della classe è definito il puntatore all'elemento radice (Node* root)

Classe IntBinTree Per il debugging, sono definiti gli operatori put to (<<) e get from (>>) È possibile usarli per immettere un albero binario da tastiera e stamparlo a video IntBinTree mio_binario; cin >> mio_binario; // acquisisce da tastiera /* Elaborazioni varie... */ cout << mio_binario; // stampa a video

Classe IntBinTree Formato di input/output: 10 20 30 Gli spazi sono ignorati [10 [20] [30] ] Se il figlio destro non c'è: [10 [20] ] Se il figlio sinistro non c'è: [10 [] [30] ]

Classe IntBinTree Se l'albero ha più di un livello, il formato è ricorsivo: 10 20 30 20 34 100 44 [10 [20[20]] [30[34[][44]][100]] ]

Programmazione ricorsiva a oggetti class IntBinTree: public BaseBinTree<int>{ /* */ public: void esercizio(){ // esercizio(); // sottoalbero sinistro? esercizio(); // sottoalbero destro? } }; È necessario applicare il seguente accorgimento per programmare in modo ricorsivo su classi. Per esportare la funzionalità (e per testare il programma dal main) è necessario scrivere un metodo pubblico della classe IntBinTree. Però l'esercizio non può essere svolto in questo metodo pubblico, perché, non avendo un puntatore al nodo come argomento, non può essere richiamato ricorsivamente.

Programmazione ricorsiva a oggetti 1 2 3 4 6 7 8 9 10 11 12 class IntBinTree{ /* */ private: static void _esercizio(node* r){ // _esercizio(r->left); _esercizio(r->right); } public: void esercizio(){_esercizio(root);} // funzione di interfaccia }; Quindi il metodo pubblico deve invocare un altro metodo privato (con un nome simile) e passargli il puntatore a root come argomento esplicito. Il puntatore this che viene passato sempre come argomento implicito risulta così inutile. Per aumentare l'efficienza e la leggibilità, si elimina dichiarando statico il metodo privato.

File per l'esercitazione Copiare dalla cartella condivisa in una cartella locale: BaseBinTree.h ( da non modificare) IntBinTree.h IntBinTree.cpp Includere i file nel progetto Dev-Cpp

o 1 Aggiungere a IntBinTree una funzione ricorsiva che restituisce la somma di tutte le etichette pari dell'albero. 10 8 20 = 40 2

o 1 Soluzione 1 2 3 4 6 7 int IntBinTree::_sumEven(const Node* t){ if (t == NULL) return 0; } return (t->info % 2 == 0?t->info:0) + _sumeven(t->left) + _sumeven(t->right); T 0 = d T n = h 2T n 2 T n O n

o 2 Aggiungere a IntBinTree una funzione ricorsiva che specchia l'albero. 10 10 20 20 2 8 8 2 [ 10 [20] [[2[]][8]] ] [ 10 [[8][2[][]]] [20] ]

o 2 Soluzione 1 2 3 4 6 7 8 9 void IntBinTree::_mirror(Node* t){ if (t == NULL) return; // scambio il sottoalbero sinistro con il destro: Node* app = t->left; t->left = t->right; t->right = app; _mirror(t->left); _mirror(t->right); } T (0) = d T (n) = h+ 2T( n 2) T (n) Ο(n)

o 3 Aggiungere a IntBinTree una funzione che conta quanti nodi hanno un numero pari di discendenti 10 3 2 = 4 8

o 3 Soluzione 1 2 3 4 6 7 8 9 10 11 12 int IntBinTree::conta(const Node* r){ if(!r) return 0; return 1 + conta(r->left) + conta(r->right); } int IntBinTree::_esercizio3(const Node* r){ if(!r) return 0; int numdisc = conta(r->left) + conta(r->right); return (numdisc % 2 == 0? 1 : 0) + _esercizio3(r->left) + _esercizio3(r->right); }

o 3 Soluzione conta(): O n _esercizio3(): T (0) = d T (n) = hn+ 2T( n 2) O nlog n

Tecnica per diminuire la complessità Si fa una funzione sola invece di due La funzione esegue due cose contemporaneamente: Conta i discendenti Conta i nodi che hanno un numero pari di discendenti La funzione deve restituire due interi Il secondo intero viene restituito tramite un riferimento a intero int _esercizio3(const Node* r, int& numdisc); return: Numero di nodi che hanno un numero pari di discendenti return: Numero dei discendenti

o 3 Soluzione efficiente 1 2 3 4 6 7 8 9 10 11 int IntBinTree::_esercizio3(const Node* r, int& numnodi){ if(!r) { numnodi = 0; return 0; } } int numnodil, numnodir; int countl = _esercizio3(r->left, numnodil); int countr = _esercizio3(r->right, numnodir); numnodi = numnodil + numnodir + 1; return ((numnodil + numnodir) % 2 == 0? 1 : 0) + countl + countr; T (0) = d T (n) = h+2t( n 2) Ο(n)

Programmazione ricorsiva a oggetti 1 2 3 4 class IntBinTree{ /* */ public: int esercizio3(){ int numnodi; return _esercizio3(root, numnodi); } }; La funzione di interfaccia deve avere una variabile locale per accogliere il secondo valore di ritorno, che poi viene scartato.

o 4 Aggiungere a IntBinTree una funzione ricorsiva che conta quanti nodi hanno un nel sottoalbero destro ma non nel sinistro 10 3 8 2 = 2

o 4 Soluzione 1 2 3 4 6 7 8 9 10 11 12 13 14 1 16 bool isinside(int i, const Node* r){ if(!r) return false; if(r->info == i) return true; if(isinside(i, r->left)) return true; return isinside(i, r->right); } int conta(const Node* tree){ if(!tree) return 0; bool cinques = isinside(, tree->left); bool cinqued = isinside(, tree->right); int cs = conta(tree->left); int cd = conta(tree->right); if(cinqued &&!cinques) return cs + cd + 1; else return cs + cd; } O nlog n

o 4 Soluzione efficiente 1 2 3 4 6 7 8 9 10 11 int conta(const Node* tree, bool& cinque){ if (!tree) {cinque = false; return 0;} } bool cinques, cinqued; int c = conta(tree->left, cinques) + conta(tree->right, cinqued); cinque = cinques cinqued (tree->label == ); if(cinqued &&!cinques) return c+1; else return c; O n