Indice
Esercizi liste
Esercizio 1: Sequenze di double (discusso a lezione)
Consideriamo il problema di leggere da standard input una sequenza di valori reali terminata da 0.0 creando la lista corrispondente di tipo
typedef struct lista_d { double val; struct lista_d * next; } lista_d_t ;
- sviluppare un programma C che legge un singolo elemento dallo standard input usando una funzione
double leggi_nuovo_valore(void);
e utilizza le funzioni
lista_d_t * inserisci_testa ( lista_d_t * l, double v); lista_d_t * inserisci_coda ( lista_d_t * l, double v); lista_d_t * inserisci_ord ( lista_d_t * l, double v);
per inserire nella lista. La scelta del tipo di inserizione viene richiesta all'utente una volta per tutte prima di inserire i valoro.
Inoltre, si utilizza una funzione stampa_lista()
per stampare la lista inserita prima di terminare.
Esercizio 2: Altre funzioni su liste di double
Implementare le seguenti funzioni in modo iterativo e ricorsivo:
/** calcola e restituisce il massimo della lista l */ double max ( lista_d_t * l); /** calcola e restituisce la somma di tutti gli elementi della lista l*/ double somma ( lista_d_t * l); /** libera la memoria occupata dalla lista */ void free_list( lista_d_t * l); /** cancella, se presente, l'elemento che contiene la prima occorrenza del valore v dalla lista l (liberando la memoria) e restituisce la nuova lista */ lista_d_t * cancella_uno ( lista_d_t * l, double v); /** cancella tutti gli elementi di valore del valore v dalla lista l (liberando la memoria) e restituisce la nuova lista */ lista_d_t * cancella_tutti ( lista_d_t * l, double v);
e sviluppare un main() che ne testa il funzionamento.
Esercizio 3: Verifica di proprietà su liste (ricorsivamente)
Definire una funzione ricorsiva che verifica che per ogni elemento di una lista valga la proprietà
\[
l(i + 1) = 2*l(i)
\]
dove $l(i)$ indica l'i-esimo elemento della lista a partire dalla testa. La funzione restituisce true
se la proprietà è verificata e false
altrimenti. I valori booleani sono definiti con un opportuno tipo enumerato.
Esercizio 4: Liste con doppio puntatore
Realizzare le funzioni dell'esercizio 1 utilizzando liste con puntatore al precedente e al successivo
typedef struct elem_d { double val; struct elem_d * prec; struct elem_d * next; } elem_d_t ;
in questo caso la lista complessiva puo' essere definita ad esempio come una struttura con due puntatori, uno alla testa ed uno alla coda
typedef struct lista_d { struct elem_d * head; struct elem_d * tail; } lista_d_t ;
come si modificano gli algoritmi sviluppati precedentemente ?
Esercizio 5: (avanzato) Array sparsi (//a la Python//) implementati come liste
Vogliamo realizzare degli array di double di grandi dimensioni che contengono solo una piccola percentuale di elementi diversi da 0 come liste concatenate definite come
typedef struct sparse_d { double val; unsigned index; struct elem_d * next; } sparse_d_t ;
nella lista sono presenti solo gli elementi diversi da zero e per ogni elemento e' indicato l'indice a cui corrisponde. La Lista e' mantenuta ordinata rispetto al campo indice.
Realizzare le funzioni put
e get
che permettono di leggere il valore dell'elemento di un certo indice i
(get
) e di modificarne il valore (put
), un possibile prototipo per queste funzioni e':
double put (sparse_d_T * a, unsigned indice); sparse_d_t * put (sparse_d_T * a, double x, unsigned indice);