LISTE, INSIEMI, ALBERI E RICORSIONE



Documenti analoghi
Una funzione è detta ricorsiva se chiama, direttamente o indirettamente, se stessa. In C tutte le funzioni possono essere usate ricorsivamente.

Laboratorio di Algoritmi e Strutture Dati

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)

La struttura dati ad albero binario

Corso di Laurea in Ingegneria Gestionale Esame di Informatica a.a settembre 2011

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Fondamenti di Informatica 2

Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007

Esempio: dest = parolagigante, lettere = PROVA dest (dopo l'invocazione di tipo pari ) = pprrlogvgante

2. Spiegare brevemente qual è la funzione del compilatore e la sua importanza per il programmatore.

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

B+Trees. Introduzione

Esercizi Capitolo 6 - Alberi binari di ricerca

Algoritmi di Ricerca. Esempi di programmi Java

Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione

Università degli Studi di Ferrara - A.A. 2014/15 Dott. Valerio Muzzioli ORDINAMENTO DEI DATI

Calcolare il massimo di una lista

Programmazione I - Laboratorio

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

(Esercizi Tratti da Temi d esame degli ordinamenti precedenti)

Laboratorio di Algoritmi e Strutture Dati

Realizzazione di una classe con un associazione

Funzioni in C. Violetta Lonati

Gestione dei File in C

Studente (Cognome Nome): Corso di Informatica Corso di Laurea in Ingegneria Gestionale a.a Secondo Compitino 21 Dicembre 2006

Compito di Fondamenti di Informatica

RICERCA DI UN ELEMENTO

Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione

Alberi binari di ricerca

Introduzione al MATLAB c Parte 2

Laboratorio di Algoritmi e Strutture Dati

I tipi di dato astratti

Algoritmi e Strutture Dati

Tipi di Dato Ricorsivi

obiettivi di questa seconda metà del corso fare un passo avanti rispetto a :... meccanismi di composizione dei dati

Fondamenti di Informatica T-1, 2009/2010 Modulo 2 Prova d Esame 5 di Giovedì 15 Luglio 2010 tempo a disposizione 2h30'

Le Liste. Elisa Marengo. Università degli Studi di Torino Dipartimento di Informatica. Elisa Marengo (UNITO) Le Liste 1 / 31

dall argomento argomento della malloc()

COGNOME E NOME (IN STAMPATELLO) MATRICOLA

Algoritmi e strutture dati. Codici di Huffman

Appunti tratti dal videocorso on-line di Algoritmi e Programmazione Avanzata By ALeXio

Alberi binari di ricerca

Appello di Informatica B

I puntatori e l allocazione dinamica di memoria

Laboratorio di Algoritmi e Strutture Dati

costruttori e distruttori

INTRODUZIONE A WINDOWS

ci sono più problemi che programmi esiste un problema che non si può risolvere con un programma

Gestione dinamica di una pila

Algoritmo. I dati su cui opera un'istruzione sono forniti all'algoritmo dall'esterno oppure sono il risultato di istruzioni eseguite precedentemente.

Informatica B. Sezione D. Scuola di Ingegneria Industriale Laurea in Ingegneria Energetica Laurea in Ingegneria Meccanica

Matematica - SMID : Programmazione Febbraio 2009 FOGLIO RISPOSTE

Utilizzo delle formule in Excel

Per visualizzare e immettere i dati in una tabella è possibile utilizzare le maschere;

Il tipo di dato astratto Pila

RICORSIVITA. Vediamo come si programma la soluzione ricorsiva al problema precedente: Poniamo S 1 =1 S 2 =1+2 S 3 =1+2+3

File di testo e file binari Directory

Capitolo 3. L applicazione Java Diagrammi ER. 3.1 La finestra iniziale, il menu e la barra pulsanti

Corso di Fondamenti di Informatica Algoritmi su array / 2

Inizializzazione, Assegnamento e Distruzione di Classi

Database Manager Guida utente DMAN-IT-01/09/10

Laboratorio di Informatica

Studente (Cognome Nome): Corso di Informatica Corso di Laurea in Ingegneria Gestionale a.a Primo scritto 11 Gennaio 2008

Liberare la memoria allocata dinamicamente.

Esame di Informatica Generale 9 CFU 21 Giugno 2011 Professori: Carulli, Fiorino, Mazzei

Matematica in laboratorio

GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL

PROGRAMMI LINGUAGGIO C

Informatica 3. LEZIONE 23: Indicizzazione. Modulo 1: Indicizzazione lineare, ISAM e ad albero Modulo 2: 2-3 trees, B-trees e B + -trees

Allocazione dinamica della memoria - riepilogo

Programmazione 1 A.A. 2015/2016

MODULO 5 ACCESS Basi di dati. Lezione 4

Esame del 3 febbraio 2010

CRITERI DI CONVERGENZA PER LE SERIE. lim a n = 0. (1) s n+1 = s n + a n+1. (2) CRITERI PER LE SERIE A TERMINI NON NEGATIVI

Introduzione al Linguaggio C

Quotazione compareto( ) Quotazione piurecente( ) Quotazione Quotazione Quotazione non trovato count( )

Punto Print Il programma per stampare. Documentazione Tecnica

Programmazione funzionale

Esercizio 1. Esercizio 2

Guida all uso di Java Diagrammi ER

ISCRIZIONE GARE NUOTO ON LINE ISTRUZIONI OPERATIVE PER LE SOCIETA

STAMPA DI UNA PAGINA SEMPLICE

Gest ione di list e in C

Lezione 9: Strutture e allocazione dinamica della memoria

ESERCIZI DI PROBLEM SOLVING E COMPOSIZIONE DEI DIAGRAMMI DI FLUSSO per le classi terza

Prossime lezioni. Dai TDA agli oggetti. Riassunto. Riassunto TDA. Oggi. Stefano Mizzaro 1

Gestione del sito in WordPress

Ricorsione. (da lucidi di Marco Benedetti)

Struttura a record. File ad accesso diretto. Modalità di apertura. Modalità di apertura

STAMPA UNIONE DI WORD

Algoritmi su array / 2

Corso di Informatica Corso di Laurea in Ingegneria Gestionale a.a Secondo Compitino 17 Dicembre 2005

Informatica 3. Informatica 3. LEZIONE 12: Liste. Lezione 12 - Modulo 1. Posizione corrente. Introduzione

Transcript:

LISTE, INSIEMI, ALBERI E RICORSIONE Settimo Laboratorio

LISTE E RICORSIONE

SVUOTALISTA: CONSIDERAZIONI Per svuotare una lista si devono eliminare i singoli nodi allocati con la malloc... Come fare? Per eliminare ogni nodo, dovrò potermi muoveri sulla lista... quindi se parto ad eliminare dal primo nodo, succede che...???

SVUOTALISTA: VERSIONE RICORSIVA SCHEMA RICORSIVO: caso base: E([]) = [] caso generale: E([a L]) = [E(L)] void svuotalistaric(lista* l){ if((*l) == NULL) return; // lista vuota svuotalistaric(&((l*)->next)); // scorro la lista free(*l); // elimino nodo (*l) = NULL; // aggiorno puntatore } Note: Notice that this function leaves the value of ptr unchanged, hence it still points to the same (now invalid) location, and not to the null pointer. http://www.cplusplus.com/reference/clibrary/cstdlib/free/

SVUOTALISTA: VERSIONE ITERATIVA void svuotalistait(lista* l){ if(*l == NULL) return; nodo * curr = *l; nodo * succ = (*l)->next; *l = NULL; } while(curr!= NULL){ free(*curr); *curr = *succ; *succ = (*succ)->next; }

ESERCIZIO: INSERIMENTO IN POSIZIONE I_ESIMA Inserire un nuovo elemento in posizione i_esima. Se la lista contiene meno di i elementi, inserire il nuovo elemento in coda. SCHEMA RICORSIVO: caso base: caso generale:

ESERCIZIO: INSERIMENTO IN POSIZIONE I_ESIMA Inserire un nuovo elemento in posizione i_esima. Se la lista contiene meno di i elementi, inserire il nuovo elemento in coda. lista InserisciPosizione(lista li, int pos, int i, int v); Argomenti: li: puntatore al primo nodo della lista; pos: posizione corrente nella lista; i: posizione dove aggiungere il nuovo elemento; v: valore del nuovo elemento.

ESERCIZIO: INSERIMENTO IN POSIZIONE I_ESIMA Inserire un nuovo elemento in posizione i_esima. Se la lista contiene meno di i elementi, inserire il nuovo elemento in coda. lista InserisciPosizione(lista li, int pos, int i, int v); SCHEMA RICORSIVO: caso base: II([], pos, i, v) = [v] caso base: II([a L], pos, i, v) = [v a L] // se i = pos caso generale: II([a L], pos, i, v) = [a II(L, pos, i + 1, v)] // se i < pos

ESERCIZIO: INSERIMENTO IN POSIZIONE I_ESIMA lista InserisciPosizione(lista li, int pos, int i, int v) { if(li == NULL){ lista pn = malloc(sizeof(nodo)); pn->val = v; pn->next = NULL; return pn; } if(pos == i){ return InserisciinTesta(li, v); } li->next = InserisciPosizione(li->next, pos, i + 1, v); return li; }

ESERCIZIO: ELIMINA NODO Scrivere un programma che elimini tutti i nodi di una lista che contengono il valore v. SCHEMA RICORSIVO: caso base: caso generale:

ESERCIZIO: ELIMINA NODO Scrivere un programma che elimini tutti i nodi di una lista che contengono il valore v. SCHEMA RICORSIVO: caso base: E([], v) = [] caso generale: E([a L], v) = E([L], v) [a E(L)] // se a = v // se a!= v

ESERCIZIO: ELIMINA NODO lista eliminanodo(lista li, int v) { if(li == NULL) return li; nodo * succ = li->next; if(li->value == v){ li->next = NULL; free(li); return eliminanodo(succ, v); } li -> next = eliminanodo(succ, v); return li; }

ESERCIZIO: STAMPA NODI IN POSIZIONE DISPARI Scrivere un programma che stampa solamente i valori contenuti nei nodi in posizione dispari SCHEMA RICORSIVO: caso base: caso generale:

ESERCIZIO: STAMPA NODI IN POSIZIONE DISPARI Scrivere un programma che stampa solamente i valori contenuti nei nodi in posizione dispari SCHEMA RICORSIVO: caso base: S([], i) = stampa[] caso generale: S([a L], i) = stampa[a] S([L]) S([L]) se i è dispari se i è pari

ESERCIZIO: STAMPA NODI IN POSIZIONE DISPARI void stampadispari(lista li, int i) { if(li == NULL) return; if(i % 2!= 0) printf( %d, li->value); stampadispari(li->next, i + 1); }

ESERCIZIO: CONTA VALORI Scrivere una funzione ricorsiva che conta il numero di elementi contenuti in una lista che hanno valore minore di un valore v int contaminore(lista li, int v); SCHEMA RICORSIVO: caso base: caso generale:

ESERCIZIO: CONTA VALORI Scrivere una funzione ricorsiva che conta il numero di elementi contenuti in una lista che hanno valore minore di un valore v int contaminore(lista li, int v); SCHEMA RICORSIVO: caso base: C([]) = 0 caso generale: C([a L]) = 1+C(L) 0+C(L) // se a < v // se a >= v

ESERCIZIO: CONTA VALORI int contavalori(lista li, int v) { if(li == NULL) return 0; if(li->value == v) return 1 + contavalori(li->next, v); return contavalori(li->next, v); }

ESERCIZIO: TROVA VALORE Scrivere una funzione ricorsiva che ritorna 1 se il valore v è contenuto nella lista li, 0 altrimenti. int trovavalore(lista li, int v); SCHEMA RICORSIVO: caso base: caso generale:

ESERCIZIO: TROVA VALORE Scrivere una funzione ricorsiva che ritorna 1 se il valore v è contenuto nella lista li, 0 altrimenti. int trovavalore(lista li, int v); SCHEMA RICORSIVO: caso base: T([], v) = 0 caso generale: T([a L]) = 1 // se a = v T([L], v) // se a!= v

ESERCIZIO: TROVA VALORE int trovavalore(lista li, int v) { if(li == NULL) return 0; if(li->value == v) return 1; return trovavalori(li->next, v); }

INSIEMI E RICORSIONE

INSIEME Lista con due proprietà Ordinata Senza repliche typedef Lista Insieme; Ogni operazione che viene eseguita su un oggetto di tipo insieme, deve rispettare le due proprietà.

FUNZIONE INSERIMENTO L inserimento di un nuovo elemento all interno di un insieme, richiede di individuare la corretta posizione di inserimento, per mantenere la proprietà di ordinamento, e dovrà controllare che l elemento non sia già presente. Si può fare sia ricorsivamente sia iterativamente Schema Ricorsivo caso base: I([], v) = [v] caso base: I([a L], v) = [v a L] caso ricorsivo: I([a L], v) = [a I(L, v)] se a > v [a L] se a = v se a < v

FUNZIONE INSERIMENTO Insieme InsiemeIns(Insieme li, int el) { if (!li li->val > el) return inseriscilistatesta(li,el); if (li->val==el) return li; } if (li->val<el) { Insieme pi=insiemeins(li->next, el); li->next=pi; return li; }

ESERCIZIO: INTERSEZIONE Scrivere la funzione che esegue l intersezione di due insiemi. Insieme InsiemeIntersezione(Insieme l1, Insieme l2); SCHEMA RICORSIVO: Caso base: Caso generale:

ESERCIZIO: INTERSEZIONE Scrivere la funzione che esegue l intersezione di due insiemi. Insieme InsiemeIntersezione(Insieme l1, Insieme l2); SCHEMA RICORSIVO: Caso base: I([],[]) = [] I([],[a L]) = [] I([a L],[]) = [] Caso generale: I([a L1],[b L2]) = I(L1,[b L2]) se a<b I([a L1],L2) se a>b [a I(L1,L2)] se a=b

ESERCIZIO: INTERSEZIONE Insieme InsiemeIntersezione(Insieme l1, Insieme l2) { if (!l1 &&!l2) return NULL; if (l1 &&!l2) return InsiemeIntersezione(l1->next,l2); if (!l1 && l2) return InsiemeIntersezione(l1,l2->next); if (l1->val==l2->val) return ListInsInTesta(InsiemeIntersezione(l1->next, l2->next), l1->val); if (l1->val<l2->val) return InsiemeIntersezione(l1->next,l2); } if (l1->val>l2->val) return InsiemeIntersezione(l1,l2->next);

ESERCIZIO: DIFFERENZA Scrivere la funzione che esegue la differenza tra due insiemi. Insieme InsiemeDifferenza(Insieme l1, Insieme l2); SCHEMA RICORSIVO: D([],[])=[] Caso base: D([],[a L])=[] D([a L],[])=[a D(L,[])] [a D(L1,[b L2]) se a<b Caso generale: D([a L1],[b L2]) = D([a L1],L2) se a>b D(L1,L2) se a=b

ESERCIZIO: DIFFERENZA Insieme InsiemeDifferenza(Insieme l1, Insieme l2) { if (!l1 &&!l2) return NULL; if (l1 &&!l2) return ListInsInTesta(InsiemeDifferenza(l1->next,l2), l1->val); if (!l1 && l2) return InsiemeDifferenza(l1,l2->next); if (l1->val==l2->val) return InsiemeDifferenza(l1->next, l2->next); if (l1->val<l2->val) return ListInsInTesta(InsiemeDifferenza(l1->next,l2), l1->val); } if (l1->val>l2->val) return InsiemeDifferenza(l1,l2->next);

ALBERI E RICORSIONE

DEFINIZIONE: ALBERO typedef struct Nodo { int val; struct Nodo* left; struct Nodo* right; } Nodo; typedef Nodo* Albero; radice Nodi Interni Livello 0 Livello 1 Livello I1 Livello 1II foglie

ESERCIZIO: CREO UN ALBERO VUOTO Albero CreaAlberoVuoto(){ } return NULL;

typedef struct Nodo { int val; struct Nodo* left; struct Nodo* right; } Nodo; MAIN typedef Nodo* Albero; Albero CreaAlberoVuoto(){ return NULL; } main(){... }

ESERCIZIO: ALBERO ORDINATO Creare un albero binario ordinato: ogni nodo contiene nell albero di sinistra tutti i valori minori o uguali al valore del nodo e nell albero di destra tutti i valori maggiori al valore del nodo. Esempio: dall inserendo dei valori 5, 2, 10, 8, 4, 15 si ottiene il seguente albero Al 5 [5,Al, Ar] Sotto-albero destro Ar 2 10 Sotto-albero sinistro 4 8 15

ESERCIZIO: INSERIMENTO DI UN ELEMENTO Creare una funzione per inserire un elemento all interno dell albero, mantenendo la proprietà di ordinamento dell albero. Albero Inserisci(Albero alb, int val); SCHEMA RICORSIVO: Caso base: Caso generale:

ESERCIZIO: INSERIMENTO DI UN ELEMENTO Creare una funzione per inserire un elemento all interno dell albero, mantenendo la proprietà di ordinamento dell albero. Albero Inserisci(Albero alb, int val); SCHEMA RICORSIVO: Caso base: I([], v) = [v] Caso generale: I(A=[val Al Ar], v) = [val I(Al, v) Ar] // se v <= val [val Al I(Ar, v)] // se v > val

ESERCIZIO: INSERIMENTO DI UN ELEMENTO Albero Inserisci(Albero al, int v){ if(al == NULL){ Albero pn=malloc(sizeof(nodo)); pn->val=v; pn->left=null; pn->right=null; return pn; } } if(al->val >= v){ al->left = Inserisci(al->left, v); }else{ al->right = Inserisci(al->right, v); } return al;

ESERCIZIO: STAMPA ALBERO Scrivere una funzione che stampa il contenuto dell albero. void Stampa(Albero alb); SCHEMA RICORSIVO: Caso base: S([]) = [] Caso generale: S(A=[val Al Ar]) = val S(Al) S(Ar)

ESERCIZIO: STAMPA ALBERO // stampa in ordine di inserimento void Stampa(Albero al){ } if(!al) return; printf("%d - ", al->val); Stampa(al->left); Stampa(al->right);

ESERCIZIO: STAMPA ALBERO // variante ordine crescente void StampaOrdinata(Albero al){ if(!al) return; StampaOrdinata(al->left); printf("%d - ", al->val); StampaOrdinata(al->right); } // variante ordine decrescente void StampaInversa(Albero al){ if(!al) return; StampaInversa(al->right); printf("%d - ", al->val); StampaInversa(al->left); }

ESERCIZIO: CERCA VALORE Scrivere una funzione ricorsiva che cerca il nodo contenente un valore v all interno dell albero. Albero CercaValore(Albero alb, int val); SCHEMA RICORSIVO: Caso base: Caso generale:

ESERCIZIO: CERCA VALORE Scrivere una funzione ricorsiva che cerca il nodo contenente un valore v all interno dell albero. Albero CercaValore(Albero alb, int val); SCHEMA RICORSIVO: Caso base: C([], v) = [] C(A=[val, Al, Ar], v) = A se v = val Caso generale: C(A=[val, Al,Ar], v) = C(Al, v) // se v < val C(Ar, v) // se v > val

ESERCIZIO: CERCA VALORE Albero Cerca(Albero al, int v){ if(!al) return NULL; if(v == al->val) return al; } if(v < al->val) return Cerca(al->left, v); else return Cerca(al->right, v);

CONTA NUMERO NODI Scrivere una funzione che ritorna il numero di nodi presenti in un albero Schema ricorsivo caso base: caso ricorsivo:

CONTA NUMERO NODI Scrivere una funzione che ritorna il numero di nodi presenti in un albero Schema ricorsivo caso base: C([]) = 0 caso ricorsivo: C([a Al Ar]) = 1 + C(Al) + C(Ar)

CONTA NUMERO NODI int contanumeronodi(albero al){ } if(!al) return 0; return 1 + contanumeronodi(al->left) + contanumeronodi(al->right);

ELIMINA FOGLIE Scrivere una funzione che elimini tutte le foglie dell albero passato e ritorni il numero di elementi eliminati Schema ricorsivo caso base; caso ricorsivo:

ELIMINA FOGLIE Scrivere una funzione che elimini tutte le foglie dell albero passato e ritorni il numero di elementi eliminati Schema ricorsivo caso base: E([]) = [], 0 caso base: E([a Al Ar]) = [], 1 // se Al = Ar = NULL caso ricorsivo = E([a Al Ar]) = [a E(Al) E(Ar)]

SESTA CONSEGNA

SESTA CONSEGNA Consegna dovrà essere eseguita entro il giorno 26 gennaio 2011 Le consegne effettuate successivamente non verranno considerate... Comando per la consegna: consegna consegna6

ESERCIZIO 1 Creare un file Amici che contenga per ogni riga i seguenti dati: Nome spazio Cognome spazio età spazio squadra del cuore Realizzare un programma che implementi le seguenti funzioni: leggere il file creando una lista dinamica di tipo amico (un tipo definito come sopra); data la lista di amici e un intero, crea una nuova lista di tutti gli amici che hanno quell'età e la visualizza; data la lista di amici e una squadra di calcio, elimina dalla lista tutti gli amici che tifano quella squadra di calcio e visualizza la lista.

ESERCIZIO 2 Si consideri il seguente problema di matematica ricreativa, dovuto al matematico russo Boris Kordemsky. Il gatto Purrer ha deciso di schiacciare un pisolino, e subito sogna di essere circondanto da 13 topolini, 12 grigi e uno bianco disposti a cerchio; nel sogno il padrone gli dice: "Purrer, devi mangiare tutti i topi ma quello bianco per ultimo". Dato che non li mangia in sequenza ma saltando ogni volta n posizioni, da quale topo deve partire, ovvero in quale posizione si deve trovare il topolino bianco partendo dal primo mangiato? Realizzare un programma in C che, fornito in ingresso il passo n che il gatto fa tra due topi mangiati (n>=2), tramite l'utilizzo di una lista dica in quale posizione si deve trovare il topo bianco rispetto al primo mangiato.