Struttura di una lista legata Una lista legata è una variabile strutturata in cui ogni elemento mantiene l’indirizzo (mediante un puntatore) dell’elemento.

Slides:



Advertisements
Presentazioni simili
Puntatori Linguaggio C.
Advertisements

Tipi di dato astratti Lista, Pila, Coda, Albero.
Estendere i linguaggi: i tipi di dato astratti
Strutture dati lineari
MATLAB. Scopo della lezione Programmare in Matlab Funzioni Cicli Operatori relazionali Esercizi vari.
Classi ed Oggetti in Java (Cenni). Richiami Ruolo delle Classi in Java Oggetti.
Liste di Interi Esercitazione. Liste Concatenate Tipo di dato utile per memorizzare sequenze di elementi di dimensioni variabile Definizione tipicamente.
Fondamenti di Informatica I CDL in Ingegneria Elettronica - A.A CDL in Ingegneria Elettronica - A.A Strutture dati dinamiche.
Fondamenti di Informatica I CDL in Ingegneria Elettronica - A.A CDL in Ingegneria Elettronica - A.A Strutture dati dinamiche.
Strutture dati elementari
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Caratteri e stringhe di caratteri
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Liste.
STRUTTURE DATI e LABORATORIO II ESERCITAZIONE N°13 Heap massimo.
Esercizi su alberi binari
Tail recursion: esempio
Alberi binari Definizione della struttura dati: struct tree { };
Esercizi su alberi binari di ricerca
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di Programmazione a.a.2009/2010 Prof.ssa Chiara Petrioli Corso.
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2007/2008 Corso di Programmazione 1 a.a.2007/2008 Prof.ssa Chiara Petrioli Corso di Laurea.
E.Mumolo. DEEI Introduzione alla programmazione ad oggetti in C++ Object Oriented Programming, OOP E.Mumolo. DEEI
Allocazione dinamica della memoria
CORSO DI PROGRAMMAZIONE II
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
// PROTOTIPI void costruisciLista(Pnodo &, string &); void stampaLista(Pnodo ); void creaNodo (int, Pnodo&); Pnodo inserisciNodoTesta (int,Pnodo &); Pnodo.
Introduzione agli stream e alle classi
Albero: insieme di punti chiamati NODI e linee chiamate EDGES
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Esercizi su pile Scrivere una funzione che restituisca una nuova pila che contiene i valori di una pila in ingresso in ordine inverso. La pila originale.
Esercizi su alberi binari
1 Strutture Dinamiche Corso di Informatica A Vito Perrone.
Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri per indirizzo, passaggio.
FUNZIONI... Una funzione permette di dare un nome a una espressione rendendola parametrica float f(){ return * sin(0.75); } float f1(int x) { return.
1.Scrivere una funzione per cercare un numero x in una lista circolare di interi. La funzione deve restituire NULL se il numero non esiste. 2.Scrivere.
1 ListaDiElem Cancella( ListaDiElem lista, TipoElemento elem ) { ListaDiElem puntTemp; if( ! ListaVuota(lista) ) if( lista–>info == elem ) { puntTemp =
Programmazione Mod. B - prof. Burattini - Cap 17 1.
15 maggio 2002 Avvisi: Ultima lezione: mercoledì 29 maggio II Esonero: mercoledì 5 giugno, ora da stabilire.
Corso di informatica Athena – Periti Informatici
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2007/2008 Corso di Programmazione 1 a.a.2007/2008 Prof.ssa Chiara Petrioli Corso di Laurea.
Esercizi Liste.
Esercizi su File e Liste
Grafi Rappresentazione mediante liste di adiacenza:
Tail recursion: esempio
Esercizi su alberi binari di ricerca
Alberi binari Definizione della struttura dati: struct tree { };
Complessità di un algoritmo
ESTENSIONI SEMPLICI e TEOREMA DELL’ELEMENTO PRIMITIVO
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Le strutture informative Corso di Informatica 2 a.a. 2003/04 Lezione 5.
CORSO DI PROGRAMMAZIONE II Lezione 22
Esercitazioni su liste
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea.
1. 2 Variabili statiche e dinamiche Un programma è un processo in esecuzione a cui il sistema operativo assegna una certa zona di memoria. Tale zona può.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
Liste Concatenate 11 Aprile E’ una delle strutture dati fondamentali in tutti i linguaggi di programmazione di alto livello Una Lista Concatenata.
Fondamenti di Informatica
Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Esercizi su Alberi.
Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato.
13. Strutture dati dinamiche Ing. Simona Colucci Informatica - CDL in Ingegneria Industriale- A.A
1 MODULO STRUTTURE DATI FONDAMENTALI: Strutture dinamiche classe 4° INDUSTRIALE INFORMATICA Focus on.
Transcript della presentazione:

Struttura di una lista legata Una lista legata è una variabile strutturata in cui ogni elemento mantiene l’indirizzo (mediante un puntatore) dell’elemento successivo. Ogni elemento della struttura viene detto nodo. Tutti i nodi della struttura sono implementati come variabili dinamiche. La figura seguente è un esempio di rappresentazione grafica di una lista. p4 è il puntatore nullo: non punta a niente Pk giallop1bleup2rossop3nerop4

In questo esempio Pk è il puntatore alla lista, ogni nodo della lista è composto da un dato e da un puntatore al nodo successivo: (giallo, p1) (bleu, p2) (rosso, p3) (nero, p4). La stessa situazione può essere descritta con la tabella seguente: INDIRIZZO TIPOCONTENUTOOSSERVAZIONI 0x0064fdf0Nodogiallop1= 0x0064fe0fp1 = indirizzo prossimo nodo 0x0064fe0fNodobleup2= 0x0064fe07 p2= indirizzo prossimo nodo 0x0064fe07Nodorossop3= 0x0064fff0p3=indirizzo prossimo nodo 0x0064fff0NodoNeroP4=0 o NULLp4= fine della lista p4 è il puntatore nullo: non punta a niente Pk giallop1bleup2rossop3nerop4

Una lista lineare legata è una collezione di oggetti (gli elementi della lista o nodi) definiti dinamicamente, uniti insieme da puntatori. Ogni singola variabile puntatore è costituita da almeno due campi: il primo contiene l’informazione, il secondo l’indirizzo dell’elemento successivo. Nodo: è una variabile dinamica che costituisce l’elemento della lista legata. Pk giallop1bleup2rossop3nerop4

Dalla definizione emerge chiaramente che per gestire una lista è sufficiente conoscere il puntatore al suo primo elemento. Il nodo è una variabile strutturata di tipo struct in cui uno dei campi è formato da un puntatore al prossimo nodo: chiameremo campo next tale campo, mentre gli altri dati della struct li indicheremo come campo dati (esso conterrà le informazioni specifiche). In questo modo tutti i nodi sono collegati insieme per formare il dato strutturato denominato lista. Pk giallop1bleup2rossop3nerop4

Supponiamo di voler costruire la lista sottostante; per implementarla in C++ definiamo il tipo Tnodo:. struct Tnodo { char nome[10]; Tnodo* next; } Pk giallop1bleup2rossop3nerop4

Una tipica lista inizia con una variabile puntatore al nodo e termina con il puntatore nullo. Nell’esempio in figura Pk punta al primo nodo posto all’inizio della lista; per accedere a tale nodo basta dereferenziare pk. (*pk).nome contiene il nome di 10 caratteri della struttura Tnodo (*pk).next contiene l’indirizzo del nodo successivo. struct Tnodo { char nome[10]; Tnodo* next; } La struttura Tnodo, in questo esempio, è costituita da un array di 10 caratteri e da un puntatore next al prossimo nodo; è opportuno notare come il puntatore punta ad un tipo che viene definito in quello stesso momento. annap1ugop2cirop3dariop4 Pk

In luogo della scrittura precedente si utilizza la seguente in cui non appare il simbolo * di derenfereziazione: pk->nome pk->next Il simbolo -> viene detto operatore freccia: esso si applica al puntatore della struttura e non alla variabile che denota la struttura.

Implementazione di una lista legata Una lista può essere paragonata ad un insieme, i cui elementi sono i nodi della lista (o, meglio, il campo informazione del nodo). Le prime operazioni da introdurre in un insieme sono: inserimento, cancellazione, ricerca. Come primo passo introduciamo un semplice esempio di nodo a cui fare riferimento. A questo scopo, per semplificare, riteniamo opportuno prendere come informazione base del nodo un numero intero; avremo quindi struct Tnodo { int info; Tnodo *next; }; typedef Tnodo* Pnodo;

Con typedef Tnodo* Pnodo a bbiamo definito un nuovo tipo, Pnodo, che rappresenta un puntatore a Tnodo. Il nodo della lista legata lineare è costituito da un campo info, in questo caso un intero, e da un campo next che contiene un puntatore alla struttura Tnodo. Vogliamo creare un nodo nella memoria heap con queste caratteristiche. Temp è di tipo PNodo info è un intero next è di tipo PNodo NULL non punta a niente Temp NULL infonext struct Tnodo { int info; Tnodo *next; }; typedef Tnodo* Pnodo;

Scriviamo una procedura CreaNodo che ha in input l’informazione info e che restituisce il puntatore Temp del nodo creato: Se la lista è vuota inseriamo il nodo appena creato come primo elemento; per ottenere tale risultato poniamo L = Temp, dove L è ovviamente di tipo Pnodo. void CreaNodo(int info1, Pnodo& Temp) { Temp= new Tnodo; Temp->info=info1; Temp->next=NULL; } 8next L Temp NULL Pnodo L,Temp; L=NULL; int info1;…………………… info1=8; CreaNodo(info1, Temp) if (L==NULL) L=Temp;

Se la lista non è vuota, ma contiene già qualche elemento, possiamo decidere se inserire il nuovo nodo in testa o in coda. Volendo inserire il nuovo nodo in testa, cioè all’inizio della lista, potremmo porre ancora L =Temp; in questo caso, però, perderemmo il contenuto di L. I passi da fare sono allora: conservare il valore di L in Temp->next e successivamente porre L=Temp

8 L Temp NULL 3 11 Temp NULL 6 Pnodo Insert (int info1, Pnodo L) { //E’una funzione che inserisce l'elemento in testa alla lista Pnodo Temp; CreaNodo(info1, Temp); Temp->next=L; return Temp; } Lista di partenza Nuovo nodo 8 NULL L L Nuova lista

Scriviamo ora una procedura che, assegnato un nodo con puntatore Temp ed una lista L, inserisce il nodo Temp in coda alla lista L. Osserviamo che se la lista è vuota allora è sufficiente creare il nodo con puntatore L; se la lista non è vuota dobbiamo scorrerla tutta fin quando il puntatore corrente raggiunge NULL. Attenzione che nel momento in cui viene raggiunta la fine della lista si perde il legame con la lista stessa in quanto non si conosce il puntatore al nodo precedente.

La freccia verso il basso rappresenta un puntatore a NULL; se conserviamo il puntatore precedente (PREC) ed il valore del puntatore corrente (CURR) è NULL, allora per mantenere la lista linkata dobbiamo porre: PREC->next=Temp PREC 8 L Temp NULL 3 11 NULL 6 Lista di partenza Nuovo nodo 8 CURR 3 11 L NULL 6 Nuova lista

La procedura che inserisce un nodo in coda ha la seguente intestazione void InsertCoda(int info1,Pnodo &L ); con la seguente descrizione if L==NULL Creanodo(info1,L) else scorri tutta la lista finché non raggiungi la fine, conservando sia il nodo precedente (PREC) che quello corrente (CURR);quando hai raggiunto la fine esegui CreaNodo(info1,PREC->next)

La parte evidenziata in corsivo rappresenta un ciclo che ha questa struttura: inizializzazione: curr=L e prec=NULL; condizione del ciclo: while (curr != NULL) corpo del ciclo: prec=curr e curr=curr->next In definitiva si ha void InsertCoda(int info1,Pnodo &L) { Pnodo prec, curr; if (L==NULL) CreaNodo(info1, L); else { curr=L; prec=NULL; while (curr!=NULL) { prec=curr; curr=curr->next; } CreaNodo(info1, prec->next); }

Introduciamo ora la funzione Insert che permette di aggiungere un elemento all’interno della lista dopo un preassegnato nodo individuato dal suo puntatore. Supponiamo di dover inserire il nodo nella lista L dopo il nodo avente come puntatore P. tra gli elementi 8 ed 3, e che il puntatore del nodo con item 8 è L. A questo scopo basta porre Temp->next = P->next e P->next = Temp Pnodo Insert (int info1, Pnodo P, Pnodo &L) { /*Inserisce l'elemento all’interno della lista dopo il nodo puntato da P */ Pnodo Temp; CreaNodo(info1, Temp); Temp->next=P->next; P->next=Temp; return L; }

Pnodo Insert (int info1, Pnodo P, Pnodo &L) { /*Inserisce l'elemento all’interno della lista dopo il nodo puntato da P */ Pnodo Temp; CreaNodo(info1, Temp); Temp->next=P->next; P->next=Temp; return L; } 8 L Temp NULL 3 next 11 NULL 6next Lista di partenza Nuovo nodo 8 3next 6 L NULL 11 Nuova lista P

Scriviamo ora una funzione inserisciNodoMezzo nel caso in cui si deve aggiungere un elemento all’interno della lista dopo una determinata chiave. Dovremo prima cercare la chiave se esiste, e quindi inserire il nodo come prima.

void inserisciNodoMezzo( int info1,Pnodo &L) {// inserisce un nuovo nodo in mezzo alla lista int inf; Pnodo prec, curr, Temp; cout<<"Dammi valore nodo "; cin>>inf;cout<<endl; if (L==NULL) creaNodo(info1, L); // caso lista vuota else { curr=L; prec=NULL; while ((curr->info!=info1)&&(curr->next!=NULL) { prec=curr; // cerco la chiave curr=curr->next; } if (curr->next!=NULL) // chiave trovata nel mezzo { creaNodo(inf, Temp); Temp->next=curr->next; curr->next=Temp; } if ((curr->info==info1)&&(curr->next==NULL)) { creaNodo(inf, Temp); // chiave trovata alla fine curr->next=Temp; } } Utilizziamo due puntatori: curr e prec che individuano il puntatore di scorrimento della lista L (curr) e il puntatore dell’elemento immediatamente precedente (prec). Se e quando curr->info è uguale all’info dopo del quale vogliamo porre il nuovo nodo, allora operiamo come nel caso di inserimento noto il puntatore che ora sarà curr.

Analizziamo ora la cancellazione di un nodo da una lista L. Per poter cancellare un nodo contenente un dato valore dobbiamo: cercare il nodo all’interno della lista cancellare il nodo con delete mantenendo il legame dentro la lista. La procedura CancellaNodo, scritta in modo ricorsivo, ha la seguente struttura void CancellaNodo(Pnodo &L, int info1) if (L!=NULL) if (L->info=info1) cancella mantenendo il legame nella lista else richiama la funzione col nodo successivo

Per poter eseguire il punto 2 è necessario conservare il puntatore L in un’altra variabile Temp porre L=L->next cancellare la memoria a cui punta Temp Tenendo presente queste osservazioni possiamo scrivere la procedura CancellaNodo come segue. void CancellaNodo(Pnodo &L, int info1) { Pnodo Temp; if (L!=NULL) { if (L->item==info1) { Temp=L; L=L->next; delete Temp; } else CancellaNodo(L->next, info1); }

// PROTOTIPI void costruisciLista(Pnodo &); void stampaLista(Pnodo ); void creaNodo (int, Pnodo&); Pnodo inserisciNodoTesta (int,Pnodo ); void inserisciNodoCoda (int,Pnodo &); void inserisciNodoMezzo (int,Pnodo &); void cancellaNodo (int,Pnodo &); void costruisciLista(Pnodo &L) {Pnodo nodo; int item; string NomeIn, NomeOut; ifstream filista; ofstream outlista; NomeIn="L5.txt"; filista.open(NomeIn.c_str()); if (!filista) { cerr<<"Non si puo' aprire il file"<<endl; system("pause"); } filista>>item; creaNodo(item,L); while (!filista.eof()) { filista>>item; inserisciNodoCoda(item,L); } } void stampaLista(Pnodo L) { while (L!=NULL){ cout info; L=L->next;} } Pnodo inserisciNodoTesta ( int info1,Pnodo L) {// inserisce un nuovo nodo in testa alla lista Pnodo Temp; creaNodo(info1, Temp); Temp->next=L; return Temp; }

void inserisciNodoCoda ( int info1,Pnodo &L) {// inserisce un nuovo nodo in coda alla lista Pnodo prec, curr; if (L==NULL) creaNodo(info1, L); else { curr=L; prec=NULL; while (curr!=NULL) { prec=curr; curr=curr->next; } creaNodo(info1, prec->next); }

void inserisciNodoMezzo( int info1,Pnodo &L) {// inserisce un nuovo nodo in mezzo alla lista int inf; Pnodo prec, curr, Temp; cout<<"Dammi valore nodo "; cin>>inf;cout<<endl; if (L==NULL) creaNodo(info1, L); else { curr=L; prec=NULL; while ((curr->info!=info1)&&(curr->next!=NULL)) {prec=curr; curr=curr->next; } if (curr->next!=NULL) { creaNodo(inf, Temp); Temp->next=curr->next; curr->next=Temp; } if ((curr->info==info1)&&(curr->next==NULL)) { creaNodo(inf, Temp); curr->next=Temp; } }}

Una procedura iterativa è invece la seguente void CancellaNodo(Pnodo &L, int info1) { Pnodo prec=NULL; if ((L->next!=NULL)&(L->info!=info1)) {prec=L; L=L->next;} if (L->next!=NULL){ prec->next=L->next; delete L; } else cout<<“ nodo non trovato “<<endl; }

Nell’allegato liste.cpp è riportato un codice per il trattamento delle liste legate con le seguenti funzioni: void costruisciLista(Pnodo &); //costruisce una lista a partire da un file testo void stampaLista(Pnodo ); //stampa una lista void creaNodo (int, Pnodo&); //crea un nodo Pnodo inserisciNodoTesta (int,Pnodo &); // inserisci un nodo in testa void inserisciNodoCoda (int,Pnodo &); // inserisci un nodo in coda Pnodo void inserisciNodoMezzo (int,Pnodo &); // inserisci un nodo nel mezzo void cancellaNodo (int,Pnodo &); // cancella un nodo void cercaItem(int,Pnodo,Pnodo &); // cerca un nodo con una data info bool listaVuota(Pnodo); // verifica se una lista è vuota int cercaPosizione(int, Pnodo); // cerca la posizione lungo la lista di un dato nodo int contaNodi(Pnodo); // conta quanti nodi ha la lista