# Liste 1 # Operazioni Base su Liste di Interi ==Qui trovate l'implementazione delle funzioni base su liste di interi. Le soluzioni agli esercizi seguenti fanno riferimento a questo codice.== ```c // Librerie #include <stdio.h> #include <stdlib.h> // !!! // Dati typedef struct NodeStruct { int data; struct NodeStruct * next; } Node; typedef Node * pNode; // Prototipi void stampaLista(pNode); pNode inserisciCoda(pNode, int); pNode inserisciTesta(pNode, int); pNode inserisciPos(pNode, int, int); pNode inserisciOrdinatoNoRip(pNode, int); int listaLen(pNode); float listaMedia(pNode, int*); int cercaElemento(pNode, int); void eliminaLista(pNode); pNode eliminaPos(pNode, int); pNode eliminaElementiValore(pNode, int); // Main int main() { pNode head = NULL; // Inizializzazione della lista int err; printf("Creazione lista con inserimento in testa:\n"); head = inserisciTesta(head, 10); head = inserisciTesta(head, 20); head = inserisciTesta(head, 30); stampaLista(head); printf("\nInserimento in coda:\n"); head = inserisciCoda(head, 40); head = inserisciCoda(head, 50); stampaLista(head); printf("\nInserimento in posizione:\n"); head = inserisciPos(head, 25, 2); // Inserisce 25 alla posizione 2 stampaLista(head); printf("\nInserimento ordinato senza duplicati:\n"); head = inserisciOrdinatoNoRip(head, 35); // Inserisce ordinato head = inserisciOrdinatoNoRip(head, 10); // Tentativo duplicato stampaLista(head); printf("\nCalcolo della lunghezza e media della lista:\n"); int len = listaLen(head); float media = listaMedia(head, &err); if (!err) { printf("Lunghezza: %d, Media: %.2f\n", len, media); } else { printf("Errore nel calcolo della media (lista vuota).\n"); } printf("\nRicerca di un elemento nella lista:\n"); int val = 25; if (cercaElemento(head, val)) { printf("Elemento %d trovato nella lista.\n", val); } else { printf("Elemento %d non trovato.\n", val); } printf("\nEliminazione del nodo in posizione 3:\n"); head = eliminaPos(head, 3); // Elimina il nodo alla posizione 3 stampaLista(head); printf("\nEliminazione di tutti i nodi con valore 40:\n"); head = eliminaElementiValore(head, 40); // Elimina tutti i nodi con valore 40 stampaLista(head); printf("\nLiberazione della lista:\n"); eliminaLista(head); head = NULL; stampaLista(head); // Verifica che la lista sia vuota return 0; } // Funzioni void stampaLista(pNode head){ if(head == NULL){ printf("Lista vuota!\n"); } else{ pNode curr = head; // Stampo fino al penultimo while(curr->next != NULL){ printf("%d ->", curr->data); curr = curr->next; } // stampo l'ultimo printf("%d\n", curr->data); } } pNode inserisciCoda(pNode head, int new_data){ // Alloco il nuovo nodo pNode new = (pNode)malloc(sizeof(Node)); if(new == NULL){ printf("Errore di allocazione\n"); return head; } new->data = new_data; new->next = NULL; // Verifico che la lista sia allcocata, altrimenti il nuovo nodo è il primo if(head == NULL) return new; // Scorro la lista fino alla fine pNode curr = head; while(curr->next != NULL) curr = curr->next; // curr è l'ultimo elemento, quindi attacco new curr->next = new; return head; } pNode inserisciTesta(pNode head, int new_data){ // Alloco il nuovo nodo pNode new = (pNode)malloc(sizeof(Node)); if(new == NULL){ printf("Errore di allocazione\n"); return head; } new->data = new_data; new->next = NULL; // Bisogna che il nuovo nodo sia la testa e bisogna restituire la testa new->next = head; return new; } pNode inserisciPos(pNode head, int new_data, int index) { // Controllo se l'indice è valido if (index < 0) { printf("Indice %d non valido\n", index); return head; } // Caso speciale: lista vuota if (head == NULL) { if (index == 0) { return inserisciTesta(head, new_data); } else { printf("Lista vuota, impossibile inserire in posizione %d.\n", index); return head; } } // Caso speciale: inserimento in testa if (index == 0) { return inserisciTesta(head, new_data); } // Alloco il nuovo nodo pNode new = (pNode)malloc(sizeof(Node)); if (new == NULL) { printf("Errore di allocazione\n"); return head; } new->data = new_data; new->next = NULL; // Altri casi: Scorro la lista per trovare la posizione int pos = 0; pNode curr = head, prec = NULL; while (curr != NULL && pos < index) { prec = curr; curr = curr->next; pos++; } // Verifica se l'indice è fuori dai limiti if (pos != index) { printf("Indice %d fuori dai limiti.\n", index); free(new); return head; } // Inserimento del nodo prec->next = new; new->next = curr; return head; } pNode inserisciOrdinatoNoRip(pNode head, int new_data) { // Alloco il nuovo nodo pNode new_node = (pNode)malloc(sizeof(Node)); if (new_node == NULL) { printf("Errore di allocazione\n"); return head; } new_node->data = new_data; new_node->next = NULL; // Controllo se il valore è già presente pNode curr = head, prec = NULL; while (curr != NULL && new_data > curr->data) { prec = curr; curr = curr->next; } // Se il valore è già presente, non inserisco nulla if (curr != NULL && curr->data == new_data) { printf("Valore %d già presente, non inserito.\n", new_data); free(new_node); return head; } // Inserimento in testa (prec == NULL) if (prec == NULL) { new_node->next = curr; head = new_node; } // Inserimento tra prec e curr else { prec->next = new_node; new_node->next = curr; } return head; } int listaLen(pNode head){ int len = 0; pNode curr = head; while(curr != NULL){ curr = curr->next; len ++; } return len; } int listaMax(pNode head, int* err){ // lista vuota if(head == NULL){ printf("Lista vuota\n"); *err = 1; return 0; } // altrimenti *err = 0; int max = head->data; pNode curr = head; while(curr != NULL){ if(max < curr->data) max = curr->data; curr = curr->next; } return max; } float listaMedia(pNode head, int* err){ // lista vuota if(head == NULL){ printf("Lista vuota\n"); *err = 1; return 0; } // altrimenti *err = 0; float media = 0; int len = 0; pNode curr = head; while(curr != NULL){ media += curr->data; curr = curr->next; len++; } return media/len; } int cercaElemento(pNode head, int value){ pNode curr = head; while(curr != NULL){ if(curr->data == value) return 1; curr = curr->next; } return 0; } void eliminaLista(pNode head){ pNode curr = head; while(head != NULL){ curr = head; head = head->next; free(curr); } } pNode eliminaPos(pNode head, int index) { // Controllo se l'indice è valido if (index < 0) { printf("Indice %d non valido\n", index); return head; } // Lista vuota if (head == NULL) { printf("Lista vuota, impossibile eliminare.\n"); return head; } // Eliminazione della testa if (index == 0) { pNode temp = head; head = head->next; free(temp); return head; } // Altri casi: scorro la lista pNode curr = head, prec = NULL; int pos = 0; while (curr != NULL && pos < index) { prec = curr; curr = curr->next; pos++; } // Controllo se l'indice è fuori dai limiti if (curr == NULL) { printf("Indice %d fuori dai limiti.\n", index); return head; } // Rimuovo il nodo corrente prec->next = curr->next; free(curr); return head; } pNode eliminaElementiValore(pNode head, int value){ pNode curr = head, prec = NULL, tmp; // Elimino in testa while(curr != NULL && curr->data == value){ tmp = curr; curr = curr->next; free(tmp); } // Aggiorno la testa head = curr; // Elimino non in testa while(curr != NULL){ if(curr->data == value){ tmp = curr; prec->next = curr->next; curr = curr->next; free(tmp); } else{ prec = curr; curr = curr->next; } } return head; } ``` --- # Operazioni Base su Liste di Stringhe ==Qui trovate l'implementazione delle funzioni base su liste di stringhe. Le soluzioni agli esercizi seguenti fanno riferimento a questo codice.== ```c // Librerie #include <stdio.h> #include <stdlib.h> #include <string.h> // Per funzioni su stringhe // Macro #define LEN 100 // Tipo Stringa typedef char Stringa[LEN]; // Dati typedef struct NodeStruct { Stringa data; struct NodeStruct *next; } Node; typedef Node *pNode; // Prototipi void stampaLista(pNode); pNode inserisciCoda(pNode, Stringa); pNode inserisciTesta(pNode, Stringa); pNode inserisciPos(pNode, Stringa, int); pNode inserisciOrdinatoNoRip(pNode, Stringa); int listaLen(pNode); int cercaElemento(pNode, Stringa); void eliminaLista(pNode); pNode eliminaPos(pNode, int); pNode eliminaElementiValore(pNode, Stringa); // Main int main() { pNode head = NULL; // Inizializzazione della lista Stringa s; printf("Creazione lista con inserimento in testa:\n"); strcpy(s, "Ciao"); head = inserisciTesta(head, s); strcpy(s, "Mondo"); head = inserisciTesta(head, s); strcpy(s, "Test"); head = inserisciTesta(head, s); stampaLista(head); printf("\nInserimento in coda:\n"); strcpy(s, "Esempio"); head = inserisciCoda(head, s); stampaLista(head); printf("\nInserimento ordinato senza duplicati:\n"); strcpy(s, "Alpha"); head = inserisciOrdinatoNoRip(head, s); strcpy(s, "Test"); // Tentativo duplicato head = inserisciOrdinatoNoRip(head, s); stampaLista(head); printf("\nRicerca di un elemento nella lista:\n"); strcpy(s, "Test"); if (cercaElemento(head, s)) { printf("Elemento '%s' trovato nella lista.\n", s); } else { printf("Elemento '%s' non trovato.\n", s); } printf("\nEliminazione del nodo in posizione 1:\n"); head = eliminaPos(head, 1); // Elimina il nodo alla posizione 1 stampaLista(head); printf("\nEliminazione di tutti i nodi con valore 'Alpha':\n"); strcpy(s, "Alpha"); head = eliminaElementiValore(head, s); // Elimina tutti i nodi con valore 'Alpha' stampaLista(head); printf("\nLiberazione della lista:\n"); eliminaLista(head); head = NULL; stampaLista(head); // Verifica che la lista sia vuota return 0; } // Funzioni void stampaLista(pNode head) { if (head == NULL) { printf("Lista vuota!\n"); } else { pNode curr = head; while (curr != NULL) { printf("%s -> ", curr->data); curr = curr->next; } printf("NULL\n"); } } pNode inserisciCoda(pNode head, Stringa new_data) { pNode new_node = (pNode)malloc(sizeof(Node)); if (new_node == NULL) { printf("Errore di allocazione\n"); return head; } strcpy(new_node->data, new_data); new_node->next = NULL; if (head == NULL) return new_node; pNode curr = head; while (curr->next != NULL) curr = curr->next; curr->next = new_node; return head; } pNode inserisciTesta(pNode head, Stringa new_data) { pNode new_node = (pNode)malloc(sizeof(Node)); if (new_node == NULL) { printf("Errore di allocazione\n"); return head; } strcpy(new_node->data, new_data); new_node->next = head; return new_node; } pNode inserisciPos(pNode head, Stringa new_data, int index) { if (index < 0) { printf("Indice %d non valido\n", index); return head; } if (index == 0) return inserisciTesta(head, new_data); pNode new_node = (pNode)malloc(sizeof(Node)); if (new_node == NULL) { printf("Errore di allocazione\n"); return head; } strcpy(new_node->data, new_data); int pos = 0; pNode curr = head, prec = NULL; while (curr != NULL && pos < index) { prec = curr; curr = curr->next; pos++; } if (pos != index) { printf("Indice %d fuori dai limiti.\n", index); free(new_node); return head; } prec->next = new_node; new_node->next = curr; return head; } pNode inserisciOrdinatoNoRip(pNode head, Stringa new_data) { pNode curr = head, prec = NULL; while (curr != NULL && strcmp(new_data, curr->data) > 0) { prec = curr; curr = curr->next; } if (curr != NULL && strcmp(new_data, curr->data) == 0) { printf("Valore '%s' già presente, non inserito.\n", new_data); return head; } pNode new_node = (pNode)malloc(sizeof(Node)); if (new_node == NULL) { printf("Errore di allocazione\n"); return head; } strcpy(new_node->data, new_data); new_node->next = curr; if (prec == NULL) { return new_node; } else { prec->next = new_node; } return head; } int listaLen(pNode head) { int len = 0; pNode curr = head; while (curr != NULL) { curr = curr->next; len++; } return len; } int cercaElemento(pNode head, Stringa value) { pNode curr = head; while (curr != NULL) { if (strcmp(curr->data, value) == 0) return 1; curr = curr->next; } return 0; } void eliminaLista(pNode head) { pNode curr; while (head != NULL) { curr = head; head = head->next; free(curr); } } pNode eliminaPos(pNode head, int index) { if (index < 0) { printf("Indice %d non valido\n", index); return head; } if (head == NULL) return head; if (index == 0) { pNode temp = head; head = head->next; free(temp); return head; } pNode curr = head, prec = NULL; int pos = 0; while (curr != NULL && pos < index) { prec = curr; curr = curr->next; pos++; } if (curr == NULL) return head; prec->next = curr->next; free(curr); return head; } pNode eliminaElementiValore(pNode head, Stringa value) { pNode curr = head, prec = NULL, tmp; while (curr != NULL && strcmp(curr->data, value) == 0) { tmp = curr; curr = curr->next; free(tmp); } head = curr; while (curr != NULL) { if (strcmp(curr->data, value) == 0) { tmp = curr; prec->next = curr->next; curr = curr->next; free(tmp); } else { prec = curr; curr = curr->next; } } return head; } ``` --- # Trova Elemento Massimo (Lista di Interi) Data una lista di interi, scrivere una funzione che trova e restituisce il massimo. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Interi” ```c // Prototipo int trovaMax(pNode, int*); // Funzione int trovaMax(pNode head, int *err) { // Inizializzo l'errore a 0 *err = 0; // Gestione della lista vuota if (head == NULL) { printf("Errore: Lista vuota.\n"); *err = 1; return 0; // Valore predefinito in caso di errore } // Inizializzo il massimo con il primo elemento int max = head->data; pNode curr = head->next; // Scorro la lista per trovare il massimo while (curr != NULL) { if (curr->data > max) { max = curr->data; } curr = curr->next; } return max; } ``` --- # Somma Multipli di un Numero (Liste di Interi) Data una lista di interi e un numero n, scrivere una funzione restituisce la somma di tutti i multipli di n nella lista. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Interi” ```c // Prototipo int sommaMultipli(pNode, int, int *); // Funzione int sommaMultipli(pNode head, int n, int *err) { *err = 0; // Controllo lista vuota if (head == NULL) { printf("Lista vuota.\n"); *err = 1; return 0; } // Controllo valore di n if (n == 0) { printf("Valore non valido.\n"); *err = 1; return 0; } int somma = 0; pNode curr = head; // Scorri la lista e somma i multipli di n while (curr != NULL) { if (curr->data % n == 0) { somma += curr->data; } curr = curr->next; } return somma; } ``` --- # Puntatore Minimo Elemento Pari (Liste di Interi) Data una lista di interi, scrivere una funzione che cerca il minimo elemento pari e restituisce il puntatore all’area di memoria contenente il nodo associato a quel valore. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Interi” ## Versione 1 ```c // Prototipo pNode minimoPari(pNode); // Funzione pNode minimoPari(pNode head){ if(head == NULL){ printf("Lista vuota.\n"); return NULL; } pNode curr = head, pMin = NULL; int min = 0; while(curr != NULL){ if(curr->data % 2 == 0){ if(pMin == NULL || min > curr->data){ pMin = curr; min = curr->data; } } curr = curr->next; } return pMin; } ``` ## Versione 2 ```c // Prototipo pNode minimoPari(pNode); // Funzione pNode minimoPari(pNode head){ if(head == NULL){ printf("Lista vuota.\n"); return NULL; } pNode curr = head->next, pMin = head; while(curr != NULL){ if(curr->data % 2 == 0 && pMin->data > curr->data){ pMin = curr; } curr = curr->next; } return pMin; } ``` --- # Copia Elemento in una Posizione Specifica (Lista di Interi) Date due liste di interi e un indice, scrivere una funzione che copia l’elemento della prima lista nella posizione data nella seconda lista, alla stessa posizione. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Interi” ```c // Prototipo int copiaPos(pNode, pNode, int); // Funzione int copiaPos(pNode h1, pNode h2, int pos) { // Controllo variabile pos if (pos < 0) { printf("Errore: posizione non valida (%d).\n", pos); return 0; } // Variabili di controllo pNode curr1 = h1, curr2 = h2; int index = 0; // Scorro entrambe le liste while (curr1 != NULL && curr2 != NULL) { // Controllo se ho raggiunto la posizione desiderata if (index == pos) { curr2->n = curr1->n; // Copio il valore return 1; // Successo } // Avanzo nelle liste curr1 = curr1->next; curr2 = curr2->next; index++; } // Se arrivo qui, non ho trovato la posizione printf("Errore: posizione %d fuori dai limiti delle liste.\n", pos); return 0; } ``` --- # Copia Elementi Pari (Lista di Interi) Data una lista di interi, scrivere una funzione che cerca nella lista il tutti gli elementi pari e li copia in coda ad una nuova lista. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Interi” ```c // Prototipo pNode copiaPari(pNode, pNode); // Funzione pNode copiaPari(pNode head1, pNode head2) { if (head1 == NULL) { printf("La lista da cui copiare è vuota.\n"); return head2; // Restituisco head2 (potrebbe essere già popolata) } pNode curr = head1; // Copio i numeri pari da head1 a head2 while (curr != NULL) { if (curr->data % 2 == 0) { head2 = inserisciCoda(head2, curr->data); } curr = curr->next; } return head2; } ``` ==**Nota**: in questo modo scorro ogli volta la lista fino all'ultimo elemento, si può fare di meglio? (modificare la funzione inserisciCoda).== --- # Cerca e Aggiungi (Lista di Interi) Data una lista di interi e un valore intero, scrivere una funzione che cerca nella lista la PRIMA occorrenza del valore dato e, se lo trova, aggiunge un nodo adiacente a quello trovato, contenente lo stesso valore. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Interi” ==**Nota**: implementare una variante che svole la stessa operazione nella lista per TUTTE le occorrenze del numero in questione.== ```c // Prototipo pNode cercaAggiungi(pNode head, int num) // Funzione pNode cercaAggiungi(pNode head, int num) { // Controllo se la lista è vuota if (head == NULL) { printf("Lista vuota, impossibile cercare.\n"); return head; } // Scorro la lista per cercare il numero pNode curr = head; while (curr != NULL) { if (curr->n == num) { // Numero trovato, aggiungo una copia come nodo successivo pNode new = (pNode)malloc(sizeof(Node)); if (new == NULL) { printf("Errore di allocazione.\n"); return head; } new->n = num; new->next = curr->next; curr->next = new; printf("Elemento %d trovato e aggiunto.\n", num); return head; // Ritorno subito dopo aver aggiunto } curr = curr->next; } // Se non ho trovato il numero printf("Elemento %d non trovato.\n", num); return head; } ``` --- # Trova Stringa di Lunghezza Minima (Lista di Stringhe) Data una lista di stringhe, scrivere una funzione che trova e restituisce la stringa di lunghezza minima. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Stringhe” ```c // Prototipo void trovaStringaMin(pNode, Stringa, int*); // Funzione void trovaStringaMin(pNode head, Stringa res, int *err) { // Inizializzo errore a 0 *err = 0; // Caso lista vuota if (head == NULL) { printf("Lista vuota.\n"); *err = 1; strcpy(res, ""); // Resetta `res` a una stringa vuota return; } // Inizializzo `res` con la stringa del primo nodo strcpy(res, head->data); // Scorro la lista per trovare la stringa più corta pNode curr = head->next; // Parto dal secondo nodo while (curr != NULL) { if (strlen(res) > strlen(curr->data)) { strcpy(res, curr->data); } curr = curr->next; } } ``` --- # Copia Stringhe per Prefisso (Liste di Stringhe) Date due liste di stringhe e una stringa prefisso, scrivere una funzione che trova nella prima lista le stringhe che iniziano per il prefisso dato e copiarle in coda alla seconda lista. Scrivere una funzione separata per controllare che una stringa inizi con un certo suffisso. **Nota**: la soluzione va integrata con il codice di “Operazione Base su Liste di Stringhe” ```c // Prototipi int controllaPrefisso(Stringa, Stringa); pNode copiaStringhePerPrefisso(pNode, pNode, Stringa); // Funzioni int controllaPrefisso(Stringa s, Stringa prefix) { int len_prefix = strlen(prefix); // Il prefisso non può essere più lungo della stringa if (strlen(s) < len_prefix) return 0; // Confronta caratteri all'inizio for (int i = 0; i < len_prefix; i++) { if (s[i] != prefix[i]) return 0; } return 1; // È un prefisso } pNode copiaStringhePerPrefisso(pNode head1, pNode head2, Stringa prefix) { if (head1 == NULL) { printf("Lista vuota.\n"); return head2; } pNode curr = head1; // Scorri la lista `head1` e copia i nodi con il prefisso richiesto while (curr != NULL) { if (controllaPrefisso(curr->data, prefix)) { head2 = inserisciCoda(head2, curr->data); } curr = curr->next; } return head2; } ``` ==**Nota**: in questo modo scorro ogli volta la lista fino all'ultimo elemento, si può fare di meglio? (modificare la funzione inserisciCoda).==