Linguaggio C: Strutture e Liste Concatenate · Struct: dichiarazione q La dichiarazione di una...
Transcript of Linguaggio C: Strutture e Liste Concatenate · Struct: dichiarazione q La dichiarazione di una...
Linguaggio C: Strutture e Liste Concatenate
Valeria Cardellini
Corso di Calcolatori Elettronici A.A. 2018/19
Università degli Studi di Roma “Tor Vergata”
Dipartimento di Ingegneria Civile e Ingegneria Informatica
Argomenti
q Struct q Definizione di lista in C q Operazioni su lista: inserimento, cancellazione,
ricerca di un elemento
Valeria Cardellini - CE 2018/19 1
Struct
q Una struttura (o struct) è un tipo di dato aggregato
q E’ una collezione finita di variabili correlate (denominate campi o membri), in genere di tipo diverso, ognuna identificata da un nome
q Sintassi struct [nome_etichetta] {"
"tipo1 nome_campo1;""tipo2 nome_campo2;""…"
} [nome_variabile];"
Valeria Cardellini - CE 2018/19 2
Struct: esempi
q Dati anagrafici di una persona struct dati_anagrafici {" char cognome[20];" char nome[20];" int eta;" char codice_fiscale[15];"};"
q Punto geometrico struct punto {" int x, y;"};"
Valeria Cardellini - CE 2018/19 3
Struct: dichiarazione
q La dichiarazione di una struttura non riserva memoria, ma crea un nuovo tipo di dato
q Le variabili di tipo struct sono dichiarate nello stesso modo delle variabili di altro tipo ❍ Esempio struct punto p1, p2;"
q La dichiarazione di una variabile di tipo struct può essere contestuale alla dichiarazione del tipo ❍ Esempio struct punto {" int x, y; /* x e y sono i due campi, scalari di tipo int */"} p1, p2;"❍ p1 e p2 sono due variabili di tipo punto"
Valeria Cardellini - CE 2018/19 4
Operazioni su struct
q Inizializzare una variabile struct ❍ Con valore costanti (tra parentesi graffe) ❍ Esempio: struct punto p1 = {2, 5};"
q Assegnare variabili di tipo struct a variabili dello stesso tipo ❍ Copia del valore di tutti i campi
q Rilevare l’indirizzo di una variabile di tipo struct q Conoscere la dimensione di una struct
❍ Tramite sizeof"q Accedere ai campi di una struct
q È possibile dichiarare un puntatore a struct ❍ Es: struct punto *p3;"
Valeria Cardellini - CE 2018/19 5
Accedere ai campi di struct
q Per accedere ai singoli campi di una variabile di tipo struct due notazioni:
1. Operatore . o campo di struttura struct dati_anagrafici pers1;"pers1.eta = 21;"
2. Operatore -> o puntatore a struttura ❍ L’operatore -> permette l’accesso ai campi di una
struttura per mezzo di un costrutto della forma <puntatore a struttura> -> <nome campo> "
❍ Esempio struct dati_anagrafici *pers2;"pers2->eta = 40; equivale a (*pers2).eta = 40;"
Valeria Cardellini - CE 2018/19 6
cognome nome eta codice_fiscale
pers2
Gestione e passaggio di strutture
q A differenza degli array, il nome della variabile di tipo struct rappresenta la struttura nel suo complesso
q E’ possibile: ❍ Assegnare una variabile di tipo struct ad un’altra
ü Esempio: p2 = p1; ❍ Far restituire una variabile di tipo struct ad una funzione ❍ Passare ad una funzione una variabile di tipo struct come
parametro significa passarne una copia ❍ Per passare una struttura per riferimento, occorre
passare alla funzione l’indirizzo della variabile di tipo struct
Valeria Cardellini - CE 2018/19 7
typedef
q Dichiara il nome di un nuovo tipo di dato (in realtà un’abbreviazione o pseudonimo) a partire da altri tipi (scalari, aggregati, ...) ❍ Sintassi typedef tipoEsistente nuovoTipo;
q La dichiarazione di tipo è identica alla definizione di una variabile, ma è preceduta dalla clausola typedef
q Esempio: typedef char string[30];"string parola;"❍ Definisce la variabile parola di tipo string, cioè di tipo
char[30]"
Valeria Cardellini - CE 2018/19 8
Struct annidate
q Un campo di una struttura può a sua volta essere una struct"❍ L’accesso ai campi interni richiede l’indicazione del
“percorso” da seguire:"typedef struct {" int giorno;" int mese;" int anno;" } Data;"" typedef struct {" char *cognome;" char *nome;" int eta;" Data data_nascita;" char *codice_fiscale;" } dati_anagrafici;
Valeria Cardellini - CE 2018/19 9
Codice sorgente: struct_annidata.c
Lista concatenata
q Struttura dati in cui ogni nodo ha un collegamento (link) ad un altro nodo: lista concatenata (linked list)
q Il collegamento è un puntatore con l’indirizzo di memoria dell’altro nodo ❍ Si accede alla lista per mezzo di un puntatore al suo
primo nodo (head) ❍ Si accede ai nodi successivi per mezzo del puntatore
memorizzato in ogni nodo ❍ Il puntatore dell’ultimo nodo è impostato a NULL
q In una lista i dati sono memorizzati in modo dinamico
Valeria Cardellini - CE 2018/19 10
31 18 25
head
Strutture auto-referenzianti
q Definiamo il nodo di una lista (il tipo del dato non è specificato) struct listNode {" <type> data; // Ogni nodo contiene un dato" struct listNode *next; // Puntatore al prossimo nodo"};"❍ next è un puntatore al tipo di oggetto che si sta
dichiarando ❍ Struttura auto-referenziante (self-referencing): la
struttura contiene un puntatore ad una struttura dello stesso tipo
Valeria Cardellini - CE 2018/19 11
Esempio: strutture auto-referenzianti
q Esempio: struct listNode {" int data; // Ogni nodo contiene un intero" struct listNode *next; // Puntatore al prossimo nodo"} x, y, z;""x.data = 1;"y.data = 2;"z.data = 3;"x.next = &y; "y.next = &z; "z.next = NULL;""
Valeria Cardellini - CE 2018/19 12
1 2 3
x y z
data next data next data next
Esempio: strutture auto-referenzianti
q Attenzione: i nodi delle liste concatenate non sono generalmente memorizzati in modo contiguo struct listNode *ptr = &x; "/* ptr punta alla struttura x */"ptr++; " "/* ptr punta alla locazione di memoria " ptr + sizeof(x) */"ptr = ptr->next; "/* ptr punta ad y */"
Valeria Cardellini - CE 2018/19 13
Tipo di dato lista
typedef <tipo> dataType; // definito dal programmatore "struct listNode { " dataType data; " struct listNode *next; "};"typedef struct listNode ListNode;" // sinonimo di struct listNode"typedef ListNode *List; " // sinonimo di ListNode * ""In modo equivalente: typedef <tipo> dataType; // definito dal programmatore "typedef struct listNode { " dataType data; " struct listNode *next; "} ListNode;"typedef ListNode *List;" Valeria Cardellini - CE 2018/19 14
Codice sorgente: lista_concatenata.c
Tipo di dato lista
In modo equivalente: typedef <tipo> dataType; // definito dal programmatore "typedef struct ListNode *List;"typedef struct listNode { " dataType data; " List next; "} ListNode;""
In modo equivalente: typedef <tipo> dataType; // definito dal programmatore "typedef struct listNode ListNode;"typedef struct ListNode *List;"struct listNode { " dataType data; " List next; "};"
Valeria Cardellini - CE 2018/19 15
Codice sorgente: lista_concatenata.c
Allocazione di memoria
q Se head è una variabile di tipo List (List head;) chiamando la funzione malloc"head = (List)malloc(sizeof(listNode)); oppure "head = (List)malloc(sizeof(*head)); ❍ Si ottiene dal sistema una porzione di memoria adeguata a
contenere un listNode e si assegna l’indirizzo a head ""
Valeria Cardellini - CE 2018/19 16
Creazione di una lista con un nodo
typedef char itemType; "... "List newNode(itemType value) { " List head; " head = (List)malloc(sizeof(listNode)); " if (head != NULL) { " head->item = value; " head->next = NULL; " }" else " printf("%c not inserted. No memory available.\n", value);" return head; "}"
Valeria Cardellini - CE 2018/19 17
a
Assumendo value = ‘a’
Creazione di un nodo ed inserimento in testa
q Si crea la nuova struct listNode da inserire in testa q Si memorizza il valore nel nuovo nodo q Si fa puntare il nuovo nodo alla precedente testa della lista q Si fa puntare la testa della lista al nuovo nodo
Valeria Cardellini - CE 2018/19 18
b
Assumendo di inserire ‘b’ come nuovo elemento
a
a
b new
Creazione di un nodo ed inserimento in testa
void insertHead(List *s, char value)"{" List new;" new = malloc(sizeof(ListNode));" if (new != NULL) { /* Is space available? */" new->data = value;" new->next = *s;" *s = new;" }" else" printf("%c not inserted. No memory available.\n", value);"}
Valeria Cardellini - CE 2018/19 19
Codice sorgente: lista_concatenata.c
Rimozione dalla testa della lista
q Si salva il puntatore al primo nodo da rimuovere q Si preleva il valore dell’elemento q Si fa puntare la testa della lista al secondo nodo q Si dealloca lo spazio del primo nodo
Valeria Cardellini - CE 2018/19 20
b a
value
b temp
b a
Rimozione dalla testa della lista
char deleteHead(List *s)"{" List temp;" char value;""
temp = *s;""
if (temp != NULL) {" value = temp->data;" *s = temp->next;" free(temp);" return value;" }" return '\0';"}"
Valeria Cardellini - CE 2018/19 21
Codice sorgente: lista_concatenata.c
Creazione di un nodo ed inserimento ordinato
q Inserimento ordinato dei valori ❍ In un ciclo, occorre scorrere la lista fino a trovare il nodo
prima del quale deve essere inserito il nuovo nodo, ossia fin quando il valore da inserire risulta maggiore del valore del nodo corrente ü Si usano due puntatori, previous e current, che puntano
rispettivamente al nodo precedente e al nodo corrente ❍ Se la lista è vuota, rendere il nuovo nodo come testa e
restituirlo, altrimenti inserire il nuovo nodo tra previous e current
Valeria Cardellini - CE 2018/19 22
Creazione di un nodo ed inserimento ordinato
/* Insert a new value into the list in sorted order */"void insertSorted(List *s, char value) {" List new, previous, current; "" new = malloc(sizeof(ListNode)); /* Create node */" if (new != NULL) { /* Is space available? */" new->data = value;" new->next = NULL;" previous = NULL;" current = *s;"" /* Loop to find the correct location in the list */" while (current != NULL && value > current->data) {" previous = current; /* walk to ... */" current = current->next; /* ... next node */" }" "
Valeria Cardellini - CE 2018/19 23
Codice sorgente: lista_concatenata.c
Creazione di un nodo ed inserimento ordinato
/* Insert new node at beginning of list */" if (previous == NULL) {" new->next = *s;" *s = new;" }" else { /* Insert new node between previous and current */" previous->next = new;" new->next = current;" }" }" else" printf("%c not inserted. No memory available.\n", value);"}"
Valeria Cardellini - CE 2018/19 24
Codice sorgente: lista_concatenata.c
Rimozione di un nodo
q Rimozione di un nodo ❍ Se è da rimuovere la testa della lista
ü Si preleva il valore del nodo ü Si salva il puntatore al nodo da rimuovere ü Si fa puntare la testa della lista al secondo nodo ü Si dealloca lo spazio del primo nodo
❍ Altrimenti, in un ciclo occorre scorrere la lista fino a trovare il nodo da rimuovere ü Si usano due puntatori, previous e current, che puntano
rispettivamente al nodo precedente e al nodo corrente ❍ Se il nodo viene trovato
ü Si salva il puntatore al nodo da rimuovere ü Si fa puntare il nodo precedente al nodo successivo a quello
da rimuovere ü Si dealloca lo spazio del nodo
Valeria Cardellini - CE 2018/19 25 Codice sorgente: lista_concatenata.c
Rimozione di un nodo
/* Delete a list element and return the deleted value */"char delete(List *s, char value)"{" List previous, current, temp; "" /* Delete first node */" if (value == (*s)->data) {" temp = *s; /* Hold onto node being removed */" *s = (*s)->next; /* De-thread the node */" free(temp); /* Free the de-threaded node */" return value;" }" else {" previous = *s;" current = (*s)->next;"" "
Valeria Cardellini - CE 2018/19 26
Codice sorgente: lista_concatenata.c
Rimozione di un nodo
/* Loop to find the correct location in the list */" while (current != NULL && current->data != value) {" previous = current; /* walk to ... */" current = current->next; /* ... next node */" }"" /* Delete node at current */" if (current != NULL) {" temp = current;" previous->next = current->next;" free(temp);" return value;" } " }"" return '\0';"}""
Valeria Cardellini - CE 2018/19 27
Codice sorgente: lista_concatenata.c