APPUNTI SUL LINGUAGGIO C Implementazioni di Liste Concatenate

Slides:



Advertisements
Presentazioni simili
Strutture dati elementari
Advertisements

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.
15 maggio 2002 Avvisi: Ultima lezione: mercoledì 29 maggio II Esonero: mercoledì 5 giugno, ora da stabilire.
Corso di informatica Athena – Periti Informatici
Tail recursion: esempio
Algoritmi e Strutture Dati Strutture Dati Elementari.
APPUNTI SUL LINGUAGGIO C
Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Esercizi su Alberi.
Prof.ssa Rossella Petreschi Lezione del 29/10/2012 del Corso di Algoritmi e Strutture Dati Riferimenti: Capitolo 19 del testo Cormen, Leiserson, Rivest,
I sistemi di equazioni di I grado Un sistema di equazioni DEFINIZIONE Un sistema di equazioni è un insieme di due o più equazioni, tutte nelle stesse.
Fondamenti di Informatica A - Massimo Bertozzi ALBERI E ALBERI BINARI DI RICERCA (BST)
Huffman Canonico: approfondimento. Come abbiamo visto, Huffman canonico ci permette di ottenere una decompressione più veloce e con un uso più efficiente.
Code con priorità Moreno Marzolla Dip. di Scienze dell'Informazione Università di Bologna
Fondamenti di Informatica A - Massimo Bertozzi LE RAPPRESENTAZIONI CONCATENATE.
La codifica di Huffman Un'implementazione in C++ (parte del materiale è opera di Mark Nelson, Dr. Dobb’s Journal, Gennaio 1996)‏
.  I tipi di dati non primitivi sono gli array, le struct e le union.  Gli array sono degli aggregati di variabili dello stesso tipo.  La dichiarazione.
Algoritmi e Strutture dati a.a.2010/2011 Prof.ssa Rossella Petreschi
Esercitazioni di Prog. II (esercizi su alberi ennari)
Progettare algoritmi veloci usando strutture dati efficienti
Inserzione e Cancellazione
Progettare algoritmi veloci usando strutture dati efficienti
Il linguaggio C Strutture Moreno Marzolla
Dizionari alberi bilanciati.
La funzione Path e le forme a cespuglio
10. Programmazione Ricorsiva Ing. Simona Colucci
Divide et Impera Quicksort Mergesort Charles Antony Richard Hoare
Lezione n°15 Prof.ssa Rossella Petreschi
B-alberi e alberi autoaggiustanti
Le postcondizioni specificano l’output della funzione.
Organizzazione fisica
Tipo di dato: array Un array è un tipo di dato usato per memorizzare una collezione di variabili dello stesso tipo. Per memorizzare una collezione di 7.
Usi (meno scontati) della visita DFS
Strutture informative
Vettori dinamici Definiremo la classe vector.
Algoritmi e Strutture Dati
APPUNTI SUL LINGUAGGIO C Strutture Dati e Puntatori
Dizionari alberi bilanciati.
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati
Lezione n°6 Prof.ssa Rossella Petreschi
Introduzione agli Algoritmi e alle Strutture Dati
Schema generale, visita in ampiezza e profondità.
Alberi n-ary Lezioni di C.
Gestione di un banco di magliette
Gestione di un ristorante
Usi (meno scontati) della visita DFS
Corso di Laurea Ingegneria Informatica Fondamenti di Informatica
APPUNTI SUL LINGUAGGIO C
Progettare algoritmi veloci usando strutture dati efficienti
APPUNTI SUL LINGUAGGIO C
comprensione e modifica di codice
* 07/16/96 Sez. 2: Ordinamento La consultazione di banche dati è sempre più cruciale in tutte le applicazioni dell’Informatica. Se vogliamo consultare.
APPUNTI SUL LINGUAGGIO C Esercizi sugli array e strutture
APPUNTI SUL LINGUAGGIO C Esercizi su File e Alberi Binari
Algoritmi e Strutture Dati
APPUNTI SUL LINGUAGGIO C
APPUNTI SUL LINGUAGGIO C
APPUNTI SUL LINGUAGGIO C Allocazione dinamica della memoria
LINGUAGGIO C Alberi e livelli
Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C
APPUNTI SUL LINGUAGGIO C Alberi Binari – primi esercizi
Esercizio Dato un albero binario, definiamo altezza minimale di un nodo v la minima distanza di v da una delle foglie del suo sottoalbero, definiamo invece.
APPUNTI SUL LINGUAGGIO C
Grafi e problem solving
Lezione n°7 Splay-Trees e Heaps Prof.ssa Rossella Petreschi
concetti ed applicazioni
Usando strutture dati nella piattaforma Java Collections Framework
Algoritmi e Strutture Dati
HeapSort Stesso approccio incrementale del selectionSort Tipo di dato
Ese 3 (del 3 Aprile 2003).
Transcript della presentazione:

APPUNTI SUL LINGUAGGIO C Implementazioni di Liste Concatenate Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Implementazioni di Liste Concatenate

Le Liste Concatenate Una lista concatenata è una collezione lineare di strutture connesse da puntatori, detti link (anelli o collegamenti), da cui il termine concatenata. Elemento Elemento Elemento

Lista semplicemente concatenata Un elemento x di una lista è un oggetto con almeno due campi info[x] campo chiave next[x] puntatore al successore dell’oggetto nella lista Una lista L è un oggetto con un campo: head[L] puntatore al primo elemento x della lista Lista vuota: head[L] = NIL head[L] NIL

Implementazione tramite array Occorre conoscere la dimensione max della lista Può portare a spreco di memoria A0 A1 A2 AN-3 AN-2 AN-1 Elemento non usato

Complessita' delle operazioni operazione lista come array Inserzione di un elemento in testa O(n) Inserzione di un elemento in coda O(1) Rimozione di un elemento in testa Rimozione di un elemento in coda Concatenazione di liste Visita/Rimozione di un elemento dato qualunque

Implementazione tramite record e puntatori // definizione della struttura nodo typedef struct elem{ int info; // <tipo> <valore del nodo>; struct elem* next; } elist; // definizione del puntatore ai nodi della lista typedef elist* plist;

Le Liste semplicemente Concatenate info plist info

Complessita' delle operazioni operazione lista come array lista semplicemente concatenata (puntatori e record) Inserzione di un elemento in testa O(n) O(1) Inserzione di un elemento in coda Rimozione di un elemento in testa Rimozione di un elemento in coda Concatenazione di liste Visita/Rimozione di un elemento dato qualunque

Stack LIFO La disciplina di inserzione/cancellazione degli elementi e’ LIFO (Last In - First Out): l’ultimo elemento inserito e’ il primo elemento estratto E’ sufficiente: Un riferimento tra gli elementi della lista Un marker per indicare che un riferimento e’ non significativo (e.g. per l’ultimo elemento della lista) Una testata per accedere alla lista (alla sua testa) Le operazioni di inserimento e cancellazione (entrambe in testa!) hanno costo costante (O(1)) el.n el.2 el.1  ••• testata

Coda FIFO : doppio puntatore di testata La disciplina di inserzione/cancellazione degli elementi e’ FIFO (First In - First Out): il primo elemento inserito e’ il primo elemento estratto Inserzione ed estrazione avvengono agli estremi opposti della lista L' operazione di cancellazione in testa ha costo costante (O(1)) (anche quella di inserimento in testa, ma non ci interessa!) L'operazione di inserimento in fondo ha costo costante (O(1)) Con un solo puntatore di testata una delle due operazioni (l’inserimento in fondo) avrebbe un costo O(n) (dovrei scandire tutta la lista) Con due puntatori di testata, uno al primo e l'altro all'ultimo elemento della lista, si riconducono entrambe le operazioni a complessita' costante el.1 el.2 el.n  ••• Testata - first - last

Complessita' delle operazioni operazione lista semplicemente concatenata con doppio puntatore lista semplicemente concatenata con singolo puntatore Inserzione di un elemento in testa O(1) Inserzione di un elemento in coda O(n) Rimozione di un elemento in testa Rimozione di un elemento in coda Concatenazione di liste Rimozione di un elemento dato qualunque

Le liste concatenate Tipi di liste concatenate: Lista semplicemente concatenata Vi si accede con un puntatore esterno collegato al primo nodo Termina con un puntatore nullo contenuto nell’ultimo nodo E’ attraversata/scandita in un sola direzione (quella data dai puntatori) Lista circolare semplicemente concatenata Come la precedente, ma in aggiunta il puntatore contenuto nell’ultimo nodo si ricollega indietro al primo nodo della lista Lista doppiamente concatenata Vi si può accedere tramite due distinti puntatori esterni, uno collegato al primo nodo e l’altro all’ultimo nodo Ogni nodo ha due puntatori, uno che va avanti verso il nodo successivo ed uno che ritorna indietro al precedente Il puntatore che va avanti dell’ultimo nodo è nullo così come quello che va indietro del primo nodo Può essere attraversata/scandita sia in avanti che indietro (fino ai suoi estremi) Lista circolare doppiamente concatenata Come la precedente, ma il puntatore che va avanti dell’ultimo nodo si collega al primo nodo e il puntatore che va indietro del primo all’ultimo nodo

Coda FIFO : lista circolare con testata che riferisce l'ultimo elemento della lista Immaginiamo una lista circolare in cui la testata riferisca l'ultimo elemento anziche' il primo: Si puo' inserire in tempo costante un elemento sia in testa che in coda alla lista Si puo' cancellare in tempo costante l'elemento in testa alla lista Si possono liberare tutti i nodi di una lista in tempo costante inserendoli in una lista dei liberi La cancellazione dell'elemento in coda alla lista ha costo O(n) L'eliminazione di un elemento qualunque della lista (possedendone il riferimento) ha tempo O(n) testata el.1 el.2 ••• el.n

Complessita' delle operazioni operazione lista circolare semplicemente concatenata lista semplicemente concatenata con doppio puntatore Inserzione di un elemento in testa O(1) Inserzione di un elemento in coda Rimozione di un elemento in testa Rimozione di un elemento in coda O(n) Concatenazione di liste Rimozione di un elemento dato qualunque

Eliminazione dei casi particolari - 1 Consideriamo di avere una lista ordinata di interi rappresentata come in figura: dove el.1  el.2  …  el.n e di volere scrivere una procedura per l'inserzione ordinata di un nuovo elemento: typedef struct elem { int value; struct elem *next; } node; typedef node *sortedIntList; el.1 el.2 el.n  ••• testata

Eliminazione dei casi particolari - 2 sortedIntList ordInsert(sortedIntList *l, int newEl) { if (*l == NULL) { // caso 1: lista vuota *l = (sortedIntList)malloc(sizeof(node)); (*l)->value = newEl; (*l)->next = NULL; return (*l); } else if (newEl <= (*l)->value) { // caso 2: inserisco elemento minimo, al primo posto node *t = *l; (*l)->next = t; } else { // caso 3 : inserisco elemento non minimo // in lista non vuota // continua alla prossima pagina

Eliminazione dei casi particolari - 3 sortedIntList s = *l; // individua il nodo precedente il nuovo // elemento while (s->next != NULL && s->next->value < newEl) { s = s->next; } sortedIntList t = (sortedIntList)malloc(sizeof(node)); t->value = newEl; t->next = s->next; s->next = t; return (t);

Eliminazione dei casi particolari - 4 I casi 1 e 2 rappresentano casi particolari, a fronte del caso 3 che e' il caso generale. (N.B.: in realta' la distinzione tra i casi 1 e 2 e' stata costruita ad arte a scopo didattico) Si potrebbero riassorbire i casi particolari in quello generale, semplificando cosi' la procedura? Si', basta inserire un nodo dummy in testa alla lista! Il valore del nodo dummy e' ovviamente irrilevante. Il nodo dummy e' sempre presente nella lista, anche quando questa e' vuota. dummy el.1 el.n  ••• testata

Eliminazione dei casi particolari - 5 typedef struct elem { int value; struct elem *next; } node; typedef node *sortedIntList; void listInit(sortedIntList *l) { *l = (sortedIntList)malloc(sizeof(node)); (*l)->value = 0; // un valore dummy (*l)->next = NULL; } int listEmpty(sortedIntList l) { return(l->next == NULL);

Eliminazione dei casi particolari - 6 sortedIntList ordInsert(sortedIntList l, int newEl) { // N.B.: l puo' essere passata per valore perche' // non c'e' mai necessita' di modificare la // testata sortedIntList s = l; // individua il nodo precedente il nuovo elemento while (s->next != NULL && s->next->value < newEl) { s = s->next; } sortedIntList t = (sortedIntList)malloc(sizeof(node)); t->value = newEl; t->next = s->next; s->next = t; return (l);

Lista Doppiamente Concatenata Le liste i cui elementi sono collegati da un unico riferimento (link) hanno diversi problemi. Dato un elemento (il riferimento ad un nodo della lista) la lista puo' essere scandita solo in una direzione non si puo' conoscere l'elemento precedente quello dato (e.g. per rimuovere l'elemento dato) se non scandendo tutta la lista quindi l'eliminazione di un elemento qualunque della lista (pur possedendone il riferimento) ha complessita' lineare (O(n)) Questi problemi sono risolti se dotiamo ogni elemento della lista di due riferimenti, uno in avanti e l'altro all'indietro, cosi' che la lista possa essere scandita in entrambe le direzioni. In questo modo inserzione e rimozione di un elemento in un punto dato della lista (in particolare all'inizio e alla fine) hanno sempre complessita' costante (O(1))

Lista Doppiamente Concatenata Struttura di una lista circolare, doppiamente linkata, con nodo dummy di testata. testata next dummy prev next el.1 prev next el.2 prev next el.n prev

Lista doppiamente concatenata typedef struct elem { int value; struct elem *prev; struct elem *next; } node; typedef node *DoubleLinkedList; void listInit(DoubleLinkedList *l) { *l = (DoubleLinkedList)malloc(sizeof(node)); (*l)->value = 0; // un valore dummy (*l)->prev = NULL; (*l)->next = NULL; } int listEmpty(DoubleLinkedList l) { return(l->next == NULL);

Lista circolare doppiamente concatenata con nodo dummy di testata Esercizio: scrivere in C le procedure per: L'inserimento di un elemento in testa e in coda alla lista La cancellazione di un elemento in testa e in coda alla lista L'eliminazione di un elemento qualunque della lista (passando il valore dell’elemento come parametro formale)

Complessita' delle operazioni operazione lista circolare semplicemente concatenata lista circolare doppiamente concatenata Inserzione di un elemento in testa O(1) Inserzione di un elemento in coda Rimozione di un elemento in testa Rimozione di un elemento in coda O(n) Concatenazione di liste Rimozione di un elemento dato qualunque

Liste e Insiemi Esercizio: Una lista puo' essere utilizzata per rappresentare un insieme. Operazioni tipiche su insiemi sono: intersezione unione inserimento di un elemento in un insieme rimozione di un elemento da un insieme. Definire una rappresentazione tramite lista per insiemi di numeri interi e scrivere delle funzioni C che realizzino queste operazioni. Quale e' la complessita' di queste funzioni? Come cambiano le cose a seconda del fatto che le liste siano mantenute ordinate o meno?

APPUNTI SUL LINGUAGGIO C Implementazioni di Liste Concatenate Corso di Algoritmi e strutture Dati APPUNTI SUL LINGUAGGIO C Implementazioni di Liste Concatenate FINE