# Ricorsione e Ordinamento # Stampa numeri Si scriva una funzione ricorsiva che prende in input un intero positivo n e che stampi tutti i numeri interi da 1 a n. ```c // Librerie #include <stdio.h> // Prototipi void f(int); // Main int main(){ // definisco il numero int n = 10; // chiamo la funzione ricorsiva f(n); return 0; } // Funzioni void f(int n){ // Finché n è più grande di 1, chiamo la funzione con il numero precedente if(n > 1){ f(n-1); } // Quando la funzione termina stampo il numero printf("%d\n", n); } ``` Si scriva una funzione ricorsiva che prende in input un intero positivo n e che stampi tutti i numeri interi da n a 1. ```c // Librerie #include <stdio.h> // Prototipi void f(int); // Main int main(){ // definisco il numero int n = 10; // chiamo la funzione ricorsiva f(n); return 0; } // Funzioni void f(int n){ // Prima di chiamare se stessa la funzione stampa il numero printf("%d\n", n); // Finché n è più grande di 1, chiamo la funzione con il numero precedente if(n > 1){ f(n-1); } } ``` --- # Potenze Si scriva una funzione ricorsiva “potenza” che prende in input un numero base e un numero esponente e restituisce la base elevata all’esponente. ==Suggerimento== Il caso base si ha per $e = 0$, dove $b^{0}=1$. Altrimenti, si sfrutti la proprietà $b^e = b \cdot b^{e-1}$. ```c // Librerie #include <stdio.h> // Prototipi int potenza(int, int); // Main int main(){ // Variabili int base = 2, esponente = 2, res; // calcolo potenza res = potenza(base, esponente); printf("%d^%d = %d\n", base, esponente, res); return 0; } // Funzioni int potenza(int base, int esponente){ // Caso base if(esponente == 0){ return 1; } else{ return base * potenza(base, esponente - 1); } } ``` --- # Conversione in Binario Si scriva un funzione ricorsiva per la conversione di un numero n in binario. La funzione deve restituire un intero che sembra la rappresentazione in binario del numero. **Esempi:** $(6)_{10} = (110)_{2}$, $(7)_{10} = (111)_{2}$. ==Suggerimento== Si pensi all'algoritmo visto a lezione. Quando $\frac{n}{2} = 0$ allora siamo arrivati alla fine e bisogna restituire `n%2`. Si ricordi che ad ogni step, il prossimo ci darà la cifra più significativa. ```c // Librerie #include <stdio.h> // Prototipi int converti(int); // Main int main(){ int n = 6; int res = converti(n); printf("%d -> %d\n", n, res); return 0; } // Funzioni int converti(int n){ // Caso base if(n/2 == 0){ return n % 2; } else{ return n % 2 + 10 * converti(n/2); } } ``` --- # Triangolo di Tartaglia Scrivere una funzione che stampi il triangolo di tartaglia dato un numero intero N. Si utilizzi una funzione ricorsiva per il calcolo dei coefficienti del triangolo. **Esempio** ![image](https://hackmd.io/_uploads/Hkev41tMJx.png) ==Suggerimento== Ogni elemento del tringolo di tartaglia in posizione n (riga), k (colonna) è il coefficiente binomiale $\binom{n}{k} = \frac{n!}{k! (n-k)!}$. Si noti che $\binom{n}{0} = \binom{n}{n} = 1$ dato che per convenzione $0! = 1$. Si ricordi la proprietà $\binom{n}{k} = \binom{n-1}{k} + \binom{n-1}{k-1}$. ```c // Librerie #include <stdio.h> // Prototipi int binom(int, int); // Main int main(){ int N = 10; for(int n = 0; n <= N; n++){ for(int k = 0; k <= n; k++){ printf("%d\t", binom(n, k)); } printf("\n"); } return 0; } // Funzioni int binom(int n, int k){ // coefficiente binomiale if(n == k || k == 0){ return 1; } else{ return binom(n-1, k) + binom(n-1, k-1); } } ``` --- # Inverti Stringa Si scriva una funzione ricorsiva in grado di invertire una stringa data in ingresso. ## Versione 1 ```c // Librerie #include <stdio.h> #include <string.h> // Macro #define LEN 100 // Prototipi void wrapper(char [], char[]); void invertiStringa(char [], char [], int); // Main int main(){ char src[LEN] = "ciao mamma!", dest[LEN]; wrapper(src, dest); printf("Stringa originale: %s\n", src); printf("Stringa invertita: %s\n", dest); return 0; } // Funzioni void wrapper(char src [], char dest []){ invertiStringa(src, dest, strlen(src)-1); dest[strlen(src)] = '\0'; } void invertiStringa(char src[], char dest[], int pos){ if(src[0] != '\0'){ // stringa sorgente non è finita // copio nelle attuali celle di memoria dest[pos] = src[0]; // chiamo ricorsivamente cambiando i contatori invertiStringa(src+1, dest, pos - 1); } } ``` ## Versione 2 ```c // Librerie #include <stdio.h> #include <string.h> // Macro #define LEN 100 // Prototipi void invertiStringa(char [], char [], int); // Main int main(){ char src[LEN] = "ciao mamma!", dest[LEN]; int len = 0; invertiStringa(src, dest+strlen(src)-1, strlen(src)); printf("Stringa originale: %s\n", src); printf("Stringa invertita: %s\n", dest); return 0; } // Funzioni void invertiStringa(char src[], char dest[], int og_len){ if(src[0] != '\0'){ // stringa sorgente non è finita // copio nelle attuali celle di memoria dest[0] = src[0]; // chiamo ricorsivamente cambiando i contatori invertiStringa(src+1, dest-1, og_len); } else{ // dest sarà una cella prima dell'inizio e devo puntare alla fine dest[og_len+1] = src[0]; } } ``` ## Versione 3 ```c // Librerie #include <stdio.h> #include <string.h> // Macro #define LEN 100 // Prototipi void invertiStringa(char [], char [], int*); // Main int main(){ char src[LEN] = "ciao mamma!", dest[LEN]; int len = 0; invertiStringa(src, dest+strlen(src)-1, &len); printf("Stringa originale: %s\n", src); printf("Stringa invertita: %s\n", dest); return 0; } // Funzioni void invertiStringa(char src[], char dest[], int * og_len){ if(src[0] != '\0'){ // stringa sorgente non è finita // copio nelle attuali celle di memoria dest[0] = src[0]; // incremento il counter di lettere copiate (*og_len) = (*og_len) + 1; // chiamo ricorsivamente cambiando i contatori invertiStringa(src+1, dest-1, og_len); } else{ // dest sarà una cella prima dell'inizio e devo puntare alla fine dest[*og_len+1] = src[0]; } } ``` --- # Ricerca Binaria Scrivere un programma che effettua una ricerca binaria tramite una funzione ricorsiva su un array ordinato. ```c // Librerie #include <stdio.h> #define N 5 // Prototipi int ricercaBinaria(int[], int, int, int); // Main int main(){ int v[N] = {1,3,5,7,9}; int n = 7; if(!ricercaBinaria(v, 0, N-1, n)){ printf("Non "); } printf("Trovato\n"); return 0; } // Funzioni int ricercaBinaria(int v[], int start, int end, int n){ if(start > end){ return 0; } else{ int m = (start+end)/2; if(v[m] == n) return 1; else if(v[m] < n) return ricercaBinaria(v, m+1, end, n); else return ricercaBinaria(v, start, m-1, n); } } ``` --- # Ordinamento Si scrivano le funzioni iterative per implementare selection sort e bubble sort per ordinare un array di interi. Si scriva la funzione ricorsiva merge sort per ordinare un array di interi ```c // Librerie #include <stdio.h> #define N 10 // Prototipi void stampaArray(int[], int); void selectionSort(int[], int); void bubbleSort(int[], int); void mergeSort(int[], int, int); void merge(int[], int, int, int); void copiaArray(int[], int[], int); // Main int main(){ int v[N] = {2,4,1,6,5,9,5,10,4,2}; int t[N]; printf("Array: "); stampaArray(v, N); printf("Selection Sort: "); copiaArray(v, t, N); selectionSort(t, N); stampaArray(t, N); printf("Bubble Sort: "); copiaArray(v, t, N); bubbleSort(t, N); stampaArray(t, N); printf("Merge Sort: "); copiaArray(v, t, N); mergeSort(t, 0, N-1); stampaArray(t, N); return 0; } // Funzioni void selectionSort(int v[], int dim){ for(int i = 0; i < dim; i++){ for(int j = i + 1; j < dim; j++){ if(v[i] > v[j]){ int tmp = v[j]; v[j] = v[i]; v[i] = tmp; } } } } void bubbleSort(int v[], int dim){ int i, j, n_swap,tmp; for(i = 0; i < dim - 1; i++){ n_swap = 0; for(j = 0; j < dim - i - 1; j++){ if(v[j] > v[j+1]){ tmp = v[j]; v[j] = v[j+1]; v[j+1] = tmp; n_swap++; } } if(n_swap == 0) break; } } void mergeSort(int v[], int start, int end){ int mid; if(start < end){ mid = (start + end)/2; mergeSort(v, start, mid); mergeSort(v, mid + 1, end); merge(v, start, end, mid); } } void merge(int v[], int start, int end, int mid){ int i=start, j=mid+1, k=start, copy[N]; // faccio il merge fino alla fine di una delle due porzioni while((i <= mid) && (j <= end)){ if(v[i] > v[j]){ copy[k] = v[j]; j++; } else{ copy[k] = v[i]; i++; } k++; } // finisco la copia della prima porzione (se necessario) while(i <= mid){ copy[k] = v[i]; k++; i++; } // OPPURE finisco la copia della seconda porzione (se necessario) while(j <= end){ copy[k] = v[j]; k++; j++; } // copio "copy" nell'array di partenza, ma solo nella porzione interessata for(i=start; i <= end; i++){ v[i] = copy[i]; } } void stampaArray(int v[], int dim){ printf("["); for(int i = 0; i<dim; i++) printf("%d,", v[i]); printf("]\n"); } void copiaArray(int src[], int dest[], int dim){ for(int i = 0; i < dim; i++){ dest[i] = src[i]; } } ```