Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
PubblicatoIlaria Villa Modificato 9 anni fa
2
1 MODULO STRUTTURE DATI FONDAMENTALI: Strutture dinamiche classe 4° INDUSTRIALE ABACUS Ud1Strutture dati lineariTempi -Liste semplicemente puntate 3h+3h lab -Parallelo tra vettori e liste 1h -Pile 2h+2h lab -Code 2h+ 2h lab Ud2 Strutture dati non lineariTempi -Alberi binari 4h+4h lab -Alberi binari di ricerca 4h+4h lab Focus on
3
2 Obiettivi Conoscenza: Saper riconosce e saper argomentare il concetto fondamentale di lista dinamica e di conseguenza riconoscere particolari liste che vengono gestite con tecnica LIFO e FIFO. Competenze: Saper utilizzare semplici liste in linguaggio c++ su cui si possono svolgere operazioni fondamentali di: creazione lista, inserimento e ricerca ed estrazione. Capacità:Saper applicare in modo autonomo a un problema di diversa natura la metodologia proposta, con la possibilità di risolvere anche problemi interdisciplinari. Strumenti: Lavagna luminosa, lezione frontale e laboratorio. Prerequisiti Conoscenza e competenza della struttura dati di tipo record, array, puntatori Modularità dei programmi Ud1 Strutture dati lineari
4
3 Implementazione di strutture lineari E’ possibile implementare una struttura dati lineare in modo: statico (tramite Array) dinamico (tramite una successione di record collegati tra loro per mezzo di puntatori)
5
4 Limiti dell’allocazione statica della memoria gli array OCCUPAZIONE DI MEMORIA: sovradimensionamento della struttura dovuto alla difficoltà di stima a priori VELOCITÀ IN ESECUZIONE: rigidità nelle operazioni di inserimento e cancellazione
6
5 Ud1. STRUTTURE DATI DINAMICHE Le Liste semplici Una lista consente di memorizzare dati in modo dinamico, cioè all’occorrenza nel programma Richiamo: un puntatore rappresenta l’indirizzo di memoria della variabile puntata. Si possono definire puntatori a variabile di tipo intero, reale ma anche a variabili strutturate come ad esempio a record. Def: una lista semplice è una successione di record costituiti da due o più campi di cui uno sicuramente di tipo puntatore e gli altri di tipo informativo. L’elemento generico è il record “vagone” cha ha almeno due campi “scomparti” ed uno di essi è il puntatore “gancio” che consente il collegamento agli altri vagoni
7
6 Creazione di una lista L’operazione di creazione lista prevede: 1. la definizione della struttura, 2.la dichiarazione di un puntatore globale “motrice” che regge tutti gli altri vagoni 3.la creazione di un nuovo elemento che si deve attaccare alla motrice
8
7 …… struct vagone {int info; struct vagone * prox}; struct vagone * motrice=NULL; /*Inizial.*/ … void CreaLista (int x) {struct vagone * nuovo=NULL; /*Inizial.*/ nuovo=new(struct vagone); /*allocazione nuovo vagone */ nuovo->info=x; /* accesso ed assegnazione al campo info */ nuovo->prox=NULL; motrice=nuovo; } Creazione di una lista in C++ MOTRICE NUOVO X INFOPROX VAGONE
9
8 Inserimento in testa Nell’inserimento in testa si deve collegare un nuovo record in prima posizione ossia deve essere puntato dalle motrice. Il collegamento che va realizzato per primo è quello del nuovo record con il resto della lista. Successivamente si può staccare la motrice e farla puntare al nuovo record
10
9 Inserimento in testa in C++ … void InsTesta (int x) { struct vagone * nuovo=NULL; /*Inizial.*/ nuovo= new(struct vagone); nuovo->info=x; nuovo->prox=motrice; motrice=nuovo; } NUOVO MOTRICE XABC
11
10 Inserimento in coda In questa funzione scorro tutta la lista fino a quando non trovo l’ultimo vagone a questo attacco il nuovo
12
11 Inserimento in coda in C++ MOTRICE APP NUOVO X ABC … void InsCoda (int x) {struct vagone * nuovo=NULL; struct vagone * app=NULL; nuovo= new(struct vagone); nuovo->info=x; nuovo->prox=NULL; if (motrice==NULL)/* la lista è vuota */ InsTesta(x); /* chiamata alla funzione */ else { app=motrice; while (app->prox !=NULL) app=app->prox; app->prox=nuovo; }
13
12 Inserimento in un punto qualunque con condizione Per inserire un nuovo vagone in una posizione qualunque con il rispetto di una condizione abbiamo bisogno di un puntatore che: 1.scorra la lista 2.trovi la posizione 3.realizzi i collegamenti
14
13 Inserimento in un punto qualunque con condizione in C++ … void InsQlq (int x) {struct vagone * nuovo=NULL; struct vagone * app=NULL; nuovo= new(struct vagone); nuovo->info=x; nuovo->prox=NULL; if (motrice->info==(condizione)) { nuovo->prox=motrice; /*inserimento in testa*/ motrice=nuovo;} else { app=motrice; while((app->prox!=NULL)&&((app->prox->info) !=(condizione)) app=app->prox; if (app-> prox==NULL) cout<<“\n Elemento non inseribile condizione non verificata”; else{ nuovo->prox=app->prox; app->prox=nuovo; } } } MOTRICE APP NUOVO X CBA
15
14 Cancellazione in testa La cancellazione di un record “vagone” in testa si effettua facendo scorrere in avanti di una struttura (vagone) il puntatore che punta tutto il treno (motrice).
16
15 Cancellazione in testa In C++ … Void DropTesta () { motrice=motrice->prox; } MOTRICE ABCD
17
16 Cancellazione in coda Cancellare l’ultimo vagone della coda presuppone lo scorrimento di un puntatore d’appoggio che determina il vagone terminale della lista per interrompere tale collegamento
18
17 Cancellazione in coda in C++ … Void DropCoda () { struct vagone * app=NULL; if (motrice->prox==NULL) motrice=NULL; else{ app=motrice; while(app->prox->prox !=NULL) app=app->prox; app->prox=NULL; } } MOTRICE APP ABC MOTRICE X
19
18 Cancellazione in un punto qualunque con condizione Per cancellare un vagone in un punto qualunque abbiamo bisogno di un puntatore che: 1.scorra la lista 2.trovi il vagone da cancellare 3.realizzi i vari collegamenti
20
19 Cancellazione in un punto qualunque con condizione in C++ … Void DropQlq () {struct vagone * app=NULL; if ((motrice->prox==NULL) && (motrice->info==(Condizione)) DropTesta(); /* chiamata alla funzione */ else{ app=motrice; while((app->prox !=NULL) && (app->prox->info!= Condizione)) app=app->prox; if (app->prox==NULL) cout<<“\n condizione non verificata da alcun elemento”; else app->prox=app->prox->prox; } } MOTRICE ABCD APP
21
20 Confronto tra struttura statica di array e struttura dinamica di lista Si può osservare che: -entrambe sono costituite da elementi omogenei tra loro le componenti dell’array sono solitamente di un tipo standard definito dall’utente, gli elementi della lista sono sempre formati da una o più parti informative e da una di tipo puntatore -la lista consente dimensioni variabili, mentre l’array richiede una dimensione prefissata -L’accesso all’array avviene mediante l’indice della componente, l’accesso agli elementi della lista comporta lo scorrimento degli elementi con un puntatore inizialmente posizionato sulla testa che viene successivamente spostato tramite i puntatori
22
21 Vantaggi e svantaggi dell’impiego della lista rispetto all’array Con la lista vi è una maggiore occupazione di memoria dovuta alla presenza di puntatori e lo svantaggio di una minore semplicità di uso Il vantaggio dell’uso di una lista sta nel poter effettuare su di essa in modo più rapido le operazioni di inserimento ed eliminazione dei dati
23
22 Verifica delle conoscenze acquisite: Test vero/falso Un nodo in una lista è un’ unità atomica di informazione Il valore NULL assegna ad un puntatore il valore zero Un puntatore contiene l’indirizzo di memoria della variabile puntata L’aggettivo lineare, riferito ad una lista semplice significa che tutti i nodi della lista hanno un predecessore ed un successore La lista e una struttura dati statica Le variabili dinamiche vengono dichiarate in testa al programma L’elemento generico di una lista semplice è costituito da un record che ha almeno due campi di cui uno puntatore Se voglio inserire un nuovo elemento in una lista sicuramente dovrò creare una nuova struttura dove inserirlo e poi ricercare la posizione dove collocarlo VF
24
23 1)Scrivere la funzione di visualizzazione che legge gli elementi di una lista, a partire dal primo, seguendo l’ordine dei puntatori. 2) Fornire la dichiarazione di una lista con puntatori per memorizzare un elenco ordinato di nomi e città. 3) Utilizzando la struttura dinamica costruita nell’esercizio precedente, costruire una funzione che dopo aver acquisito da tastiera un nome, lo ricerchi nella lista: se lo trova visualizza la città corrispondente, altrimenti scrive un messaggio di non trovato. Esercizi di applicazione proposti per casa mirati all’acquisizione delle competenze... da realizzare successivamente in laboratorio
25
24 Esercizio di applicazione proposto per casa mirato all’acquisizione delle capacità Costruire una rubrica telefonica che contenga, per ciascuna persona, il nome, il cognome, e il numero di telefono. Tale rubrica dovrà essere gestita con una lista. Si deve prevedere un menù di scelta che consenta all’utente di scegliere tra le seguenti funzioni in modo ripetuto: -Una funzione di inserimento di una nuova persona in ordine alfabetico rispetto al cognome; -Una funzione di ricerca per cognome che stampi il numero di telefono; -Una funzione di cancellazione dalla rubrica.... da realizzare successivamente in laboratorio
26
25 STRUTTURE DATI FONDAMENTALI: Le Code Una coda è una struttura logica che segue una politica di tipo FIFO (First in First out). Per gestire una coda sono necessarie almeno tre funzioni: push pop codavuota. La coda a livello d’implementazione è una lista in cui l’inserimento si effettua sulla fine e l’estrazione sull’inizio.
27
26 STRUTTURE DATI FONDAMENTALI: Le Code in C++ … /* definizione dell’elemento della coda */ struct elecoda{ int info; struct elecoda * prox; } ; … struct coda{ struct elecoda * inizio; struct elecoda * fine; }; struct coda queue; /* variabile globale */ queue.inizio= NULL; /*inizializzazione*/ queue.fine= NULL;... INIZIO FINE queue info elecoda prox
28
27 Inserimento La funzione d’inserimento in coda PUSHCODA crea un nuovo record nel quale inserisce la nuova informazione e lo attacca alla fine della coda. Si utilizza anche una funzione booleana CODAVUOTA che ci dice se la coda ha o meno elementi
29
28 Inserimento in C++ void pushcoda (int x) {struct elecoda * nuovo=NULL; nuovo = new( struct elecoda); /*allocazione*/ nuovo->info=x; nuovo->prox=NULL; if (codavuota() ) { queue.inizio=nuovo; queue.fine= nuovo;} else { queue.fine-> prox = nuovo; queue.fine=queue.fine-> prox; } } NUOVO X ABC INIZIO FINE queue INIZIO FINE queue x NUOVO … bool codavuota () { if (queue.inizio==queue.fine==NULL) return true; return false;}...
30
29 Cancellazione La cancellazione elimina il primo elemento della lista gestita come coda buttando fuori il valore.
31
30 Cancellazione in C++... int popcoda() { int emergente; emergente=queue.inizio->info; queue.inizio=queue.inizio->prox; return emergente; } ABC INIZIO FINE queue EMERGENTE A
32
31 STRUTTURE DATI FONDAMENTALI: Le Pile Per gestire una pila sono necessarie almeno tre funzioni: push pop pilavuota La pila a livello d’implementazione è una lista in cui sia l’inserimento che l’estrazione si effettuano sulla fine e l’estrazione sulla testa Una pila e una struttura logica che segue una politica di tipo LIFO ( Last in First out).
33
32 STRUTTURE DATI FONDAMENTALI: Le Pile in C++ … /* definizione dell’elemento della pila */ struct elepila{ int info; struct elepila * prox; } ; struct elepila * testa =NULL; /* inizializzazione*/ TESTA info elepila prox
34
33 Inserimento La funzione d’inserimento in coda PUSHPILA crea un nuovo record nel quale inserisce la nuova informazione e lo attacca in testa alla pila. Si utilizza anche una funzione booleana PILAVUOTA che ci dice se la pila ha o meno elementi
35
34 Inserimento in C++..... void pushpila (int x) {struct elecoda * nuovo=NULL; nuovo = new( struct elepila); *allocazione*/ nuovo->info=x; nuovo->prox=NULL; if ( pilavuota()) testa=nuovo; else { nuovo-> prox = testa; testa=nuovo; } } NUOVO X ABC TESTA … bool pilavuota () { if (testa==NULL) return true; return false; } x NUOVO TESTA
36
35 Cancellazione La cancellazione elimina il primo elemento della lista gestita come pila buttando fuori il valore.
37
36 Cancellazione in C++.... int poppila() { int emergente; emergente=testa->info; testa=testa->prox; return emergente; } ABC EMERGENTE A TESTA
38
37 Ud2 Strutture dati non lineari Prerequisiti Conoscenze e competenze su: puntatori, strutture, liste Obiettivi Far capire che un albero binario è una struttura che consente di conservare dati con un certo criterio e che tale struttura viene anche usata negli archivi indicizzati per mantenere ordinato l’insieme delle chiavi o indici. Conoscenze: Sapere che cos’è la struttura logica di albero e saperla riconoscere codificata Competenze: Saper utilizzare una struttura di tipo albero e saperci lavorare: visite e ricerca di un elemento in un albero e in un albero binario di ricerca. Capacità: Saper utilizzare la struttura quando un particolare insieme di dati ne richiede l’uso. Strumenti: Lavagna luminosa, lezione frontale, laboratorio
39
38 ALBERI BINARI MOTIVAZIONE: Per raccogliere e gestire dinamicamente insiemi di dati mantenendo anche la loro struttura gerarchica
40
39 Alberi: definizione A BC DEF G HI Un Albero radicato è un’insieme non vuoto di elementi detti NODI collegati tra loro attraverso ARCHI in modo tale che: Qualunque coppia di NODI è congiunta da un solo ARCO Un Albero di N NODI contiene esattamente N-1 ARCHI Rimuovendo un ARCO qualsiasi dell’albero si ottengono 2 Alberi N.B. L’utilità degli ALBERI sta nel fatto che ciascun nodo può essere ETICHETTATO ovvero può contenere una informazione.
41
40 Alberi: proprietà A BC DEF G HI Gli Alberi sono strutture dati non lineari ovvero ogni elemento ha un solo predecessore ma, può avere più successori. Nelle strutture dati lineari invece ciascun elemento ha un solo successore ed un solo predecessore.
42
41 Alberi: proprietà A BC DEF G HI E’ uso comune parlare di Alberi in termini “genealogici” e riferendoci alla figura diremo che: A è padre di B e C così come C è padre di D, E e F ecc. B è fratello di C cosi come H lo è di I ecc. D, E, F e G sono discendenti di C ma anche di A
43
42 Alberi: come sono fatti? A BC DEF G HI RADICE NODO INTERMEDIO SOTTOALBERO FOGLIE Esiste ed è unico un NODO detto RADICE che non discende da nessun altro NODO e che ha priorità massima rispetto agli altri nodi Esistono NODI detti FOGLIE senza discendenti In ciascun NODO arriva un solo arco (fatta eccezione per la radice) Preso un qualunque NODO esso è sempre raggiungibile a partire dalla RADICE e il percorso che si fa è detto CAMMINO Da un NODO intermedio (nè RADICE nè FOGLIA) è possibile raggiungere almeno una FOGLIA Ogni NODO può essere considerato un SOTTOALBERO
44
43 Alberi similari A BD C A BD C Sono similari due ALBERI che hanno la stessa struttura, cioè la stessa forma ma non lo stesso ordinamento dei NODI
45
44 Si dice grado di un NODO il numero dei suoi sottoalberi ESEMPIO: il GRADO di A e B è 2, quello di C è 3 Si dice grado di un ALBERO il maggiore tra tutti i gradi dei suoi NODI ESEMPIO: il GRADO dell’albero è 3 Si dice livello di un NODO il numero di NODI attraversati da un cammino che parte dalla radice e arriva al NODO stesso ESEMPIO: il LIVELLO di A è 1, di B e C è 2, di H, I, D, E, F è 3 Si dice altezza di un ALBERO la lunghezza del cammino più lungo esistente tra RADICE e FOGLIA (numero di ARCHI che separano la RADICE dalla FOGLIA più lontana) ESEMPIO: l’ ALTEZZA dell’albero è 3 A BC DEF G HI Livello 1 Livello 2 Livello 3 Livello 4 Dall’esigenza di classificare NODI ed ALBERI seguono le seguenti definizioni:
46
45 Un tipo particolare di Alberi: Gli Alberi Binari Def. Un Albero Binario può essere l’albero binario vuoto, cioè senza nodi, oppure è una coppia ordinata di alberi binari detti sottoalbero destro e sottoalbero sinistro ai quali è associato un nodo detto radice. In un albero binario per ciascun NODO si hanno al massimo due figli. Per cui si ha: Def. Ricorsiva: Un Albero si dice binario se Non ha nodi (è vuoto) La radice ha al più due sottoalberi binari A BC DEF H G Albero binario vuoto B A C A B
47
46 Come si fa a “creare” la struttura di Albero Binario? L’elemento generico dell’albero è un record che ha tre campi uno informativo e gli altri due di tipo puntatore al sottoalbero sinistro e destro. In C++ … struct nodo{ char info; struct nodo * fs; struct nodo * fd; }; struct nodo * radice =NULL; NODO RADICE info fsfd
48
47 Come si fa a “creare” la struttura di Albero Binario? Vista la struttura ricorsiva dell’albero, anche il caricamento di quest’ultimo avverrà in modo ricorsivo. In C++... Void memorizza_anticipato (struct nodo * & r) {Char x; Cin>>x; If (x!=‘*’) { r= new (struct nodo); r->info=x; memorizza_ anticipato(r->fs); memorizza_anticipato(r->fd); } else r=NULL; } RADICE A X A
49
48 Il problema della visita di un albero binario La visita di un albero binario consiste nell’andare ad analizzare tutti i suoi nodi una e una sola volta. Esistono tre modalità di visita e sono tutte ricorsive: Visita in ordine anticipato ( NODO FS FD) Visita in ordine simmetrico (FS NODO FD) Visita in ordine posticipato (FS FD NODO) X
50
49 Alberi: Metodi di attraversamento IN ORDINE ANTICIPATO A BC DEF H G Simulazione di visita in ordine anticipato NODO FS FD= =A FS FD= =A B FS * C FS FD = =A B D * * * C E *FD F * FD= =A B D * * * C E * G * * F * H * * void visita_anticipato (struct nodo * r) { If (r!=NULL) { cout info; /* stampa il nodo visitato */ visita_ anticipato(r->fs); visita_anticipato(r->fd); } else cout<< “ * “; }
51
50 Alberi: Metodi di attraversamento IN ORDINE SIMMETRICO A BC DEF H G Simulazione dell’ordine di visita in ordine simmetrico FS NODO FD= =FS A FD= =FS B * A FS C FD = =* D * B * A * E FD C * F FD= =* D * B * A * E * G * C * F * H * void visita_simmetrica (struct nodo * r) { If (r!=NULL) {visita_ simmetrica(r->fs); cout info; /* stampa il nodo visitato */ visita_simmetrica(r->fd); } else cout<< “ * “; }
52
51 Alberi: Metodi di attraversamento IN ORDINE POSTICIPATO A BC DEF H G Simulazione dell’ordine di visita in ordine posticipato FS FD NODO= =FS FD A= =FS * B FS FD C A= =* * D * B * FD E * FD F C A= =* * D * B * * * G E * * * H F C A void visita_posticipato (struct nodo * r) { If (r!=NULL) { visita_ anticipato(r->fs); visita_posticipato(r->fd); cout info; /* stampa il nodo visitato */ } else cout<< “ * “; }
53
52 Gli alberi binari di ricerca: ABR X ABR chiavi<x ABR chiavi>x Definizione: Un albero binario di ricerca (ABR) e un albero binario soggetto ai seguenti vincoli: 1.Il sottoalbero sinistro contiene solo dati minori della radice ed è, a sua volta, un ABR; 2.Il sottoalbero destro contiene solo chiavi maggiori della radice ed è, a sua volta, un ABR. Il tipo di dato per la chiave può essere qualsiasi purché su di esso sia definita una relazione d’ordine totale N.B. Dalla definizione di discende che ogni sottoalbero di un ABR è a sua volta un ABR
54
53 Gli alberi binari di ricerca Proprietà E C G BFHD A 1.La visita in ordine simmetrico di un ABR produce le chiavi in modo ordinato 2. Si può usare un algoritmo di ricerca su un ABR simile a quello di ricerca binaria. Per poter applicare tale algoritmo è necessario che ad ogni passo vengano escluse la metà delle chiavi, ciò corrisponde a richiedere che l’ABR sia bilanciato in altezza. Intuitivamente si chiede che non esista uno squilibrio fra le altezze dei sottoalberi destro e sinistro di ciascun sottoalbero. L’albero in figura è perfettamente bilanciato 3.Per inserire un nuovo elemento in un ABR esiste un solo modo che consente di mantenere la struttura di ABR 4.Per cancellare un elemento si usa sostanzialmente una ricerca. Tale algoritmo non garantisce che il nuovo ABR sia bilanciato.
55
54 A cura di (in ordine alfabetico): Alessandra Mancini Maria Pia Illiano Gianluca Paglia Mirella Storti
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.