Tail recursion: esempio Scrivere una funzione ricorsiva che, dato un array ordinato di interi, determini se l’intero x è presente nell’array. int ricerca_lineare(int *array, int a, int b, int x) { int mid = (a+b)/2; if (a > b) return 0; if (array[mid] == x) return 1; else if (array[mid] < x) return ricerca_lineare(array, mid+1, b, x); else return ricerca_lineare(array, a, mid-1, x); }
Esercizi su tail recursion Scrivere una funzione ricorsiva che, data una lista di interi positivi, restituisca il massimo intero nella lista. Implementare la funzione con e senza tail recursion. Scrivere una funzione ricorsiva che, data una lista di interi, restituisca la loro somma. Utilizzare la tail recursion. Scrivere una funzione ricorsiva che restituisce la media degli elementi di una lista di interi positivi. Utilizzare la tail recursion. Scrivere una funzione ricorsiva che stampi il contenuto di una pila. Utilizzare la tail recursion. Scrivere una funzione ricorsiva che converta una lista in una lista circolare. Scrivere una funzione ricorsiva che cerchi un elemento in una lista circolare. Utilizzare la tail recursion. Scrivere una funzione ricorsiva che conti il numero di elementi di una lista circolare. Utilizzare la tail recursion. NOTA: scrivere sempre pre e post condizione di ogni funzione
Esercizio 1 Scrivere una funzione ricorsiva che, data una lista di interi positivi, restituisca il massimo intero nella lista. Implementare la funzione con e senza tail recursion. Pre condizioni: La funzione prende in ingresso una lista di interi positivi Post condizioni: La funzione restituisce l’intero di massimo valore nella lista e 0 se la lista è vuota
Implementazione ricorsiva #define MAX(a, b) (a > b ? a : b) int max(struct list *l) { if (l == NULL) return 0; return MAX(l->el, max(l->next)); }
Implementazione ricorsiva con tail recursion int max(struct list *l, int mx) { if (l == NULL) return mx; if (l->el > mx) mx = l->el; return max(l->next, mx); } int max_tr(struct list *l) return max(l, 0);
Esercizio 3 Scrivere una funzione ricorsiva che restituisce la media degli elementi di una lista di interi positivi. Utilizzare la tail recursion. Pre condizioni: la funzione prende in ingresso una lista di interi positivi Post condizioni: La funzione restituisce la media (somma degli elementi / numero degli elementi)
Svolgimento int avg(struct list *l, int somma, int n) { if (l == NULL) return somma/n; somma += l->el; n++; return avg(l->next, somma, n); } int avg_tr(struct list *l) return avg(l, 0, 0);
Esercizio 4 Scrivere una funzione che stampi il contenuto di una pila. Utilizzare la tail recursion. Pre condizioni: la funzione prende in ingresso una pila Post condizioni: la funzione stampa la pila
Svolgimento void stampa_pila(struct pila *p) { if (!pila_vuota(p)) printf("%d\n", pop(p)); stampa_pila(p); }
Esercizio 5 Scrivere una funzione ricorsiva che converta una lista in una lista circolare. Pre condizioni: la funzione prende in ingresso una lista Post condizioni: la funzione rende la lista circolare (restituisce NULL se la lista è vuota)
Svolgimento void rendi_circolare(struct list *l, struct list *s) { if (l->next == NULL) l->next = s; else rendi_circolare(l->next, s); } void rendi_circolare_tr(struct list *l) if (l == NULL) return NULL; rendi_circolare(l, l);
Esercizio 6 Scrivere una funzione ricorsiva che cerchi un elemento in una lista circolare. Utilizzare la tail recursion. Pre condizioni: la funzione prende in ingresso una lista circolare e un elemento Post condizioni: la funzione restituisce 1 se l’elemento è stato trovato, 0 altrimenti.
Svolgimento int ricerca(struct list *l, struct list *s, int x) { if (l->next == s) return l->el == x; return l->el == x || ricerca(l->next, s, x); } int ricerca_tr(struct list *l, int x) if (l == NULL) return 0; return ricerca(l, l, x);
Esercizio bonus sulle pile Scrivere una funzione che, dato un intero positivo in base 10 e una base, restituisca una stringa con la rappresentazione dell’intero nella nuova base. Utilizzare le pile. Pre condizioni: la funzione prende in ingresso un intero positivo e una base Post condizioni: la funzione alloca e restituisce una stringa contenente la rappresentazione del numero nella nuova base
Svolgimento char *converti(unsigned int k, unsigned int b) { struct pila *p = crea_pila(); int conta = 0; char *s, *rappr; if (k == 0) { conta++; push(p, 0); } while(k > 0) push(p, k % b); k /= b; conta++; } rappr = s = (char *)malloc(conta+1); while(!pila_vuota(p)) int digit = pop(p); if (digit < 10) *s = '0'+digit; else *s = 'A'+digit-10; s++; *s = 0; return rappr;