# 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).==