# :christmas_tree: Alberi Albero Binario: ```c= typedef struct TreeNode { int data; struct TreeNode * left; struct TreeNode * right; } TreeNode; typedef TreeNode * Tree; ``` --- # Numero di Foglie Si scriva una funzione che, dato un albero binario, conti il numero delle foglie dell’albero. ```c= int contaFoglie(Tree root){ // Caso base: albero vuoto if(root == NULL) return 0; // Caso base: siamo arrivati a una foglia if(root->right == NULL && root->left == NULL) return 1; // Caso ricorsivo: non sono una foglia return contaFoglie(root->right) + contaFoglie(root->left); } ``` --- # Numero di Branches (non foglie) Si scriva una funzione che conta il numero di nodi che non sono foglie. ```c= int contaNoFoglie(Tree root){ // Se root è una foglia non conta niente if(root == NULL || (root->right == NULL && root->left == NULL)) return 0; // Se root non è una foglia conta 1 return 1 + contaNoFoglie(root->left) + contaNoFoglie(root->right); } ``` --- # Somma Nodi Si scriva una funzione che restituisce la somma di tutti i nodi dell’albero. ```c= // Sommare il valore dei nodi int sommaNodi(Tree root){ // Caso Base: albero vuoto if(root == NULL) return 0; // Caso Ricorsivo int value = root->data; int value_left = sommaNodi(root->left); int value_right = sommaNodi(root->right); return value + value_left + value_right; } ``` --- # Inserimento Ordinato (per BST) Si scriva una funzione che, dato un albero BST e un valore, inserisce un nuovo nodo nell'albero (senza ripetizioni). ```c= Tree createNode(int value) { Tree newNode = (Tree)malloc(sizeof(TreeNode)); if (newNode == NULL) { printf("Errore di allocazione memoria.\n"); return NULL; } newNode->data = value; newNode->left = NULL; newNode->right = NULL; return newNode; } Tree insert(Tree root, int value) { if (root == NULL) { return createNode(value); // Crea un nuovo nodo se il sottoalbero è vuoto } if (value < root->data) { root->left = insert(root->left, value); // Inserisce a sinistra } else if (value > root->data) { root->right = insert(root->right, value); // Inserisce a destra } // Se il valore è già presente, non fare nulla (niente duplicati) return root; } ``` --- # Cerca Max Si scriva una funzione che restituisce il massimo valore di un nodo contenuto in un albero. Si implementino due funzioni, una che opera per alberi generici e una che opera per Alberi Binari di Ricerca (BST). ## Versione per Alberi Generici ```c= int max2(int a, int b){ if(a > b) return a; else return b; } int max3(int a, int b, int c){ return max2(a, max2(b, c)); } int cercaMax(Tree root){ // Caso Albero Vuoto (ci entro solo se l'albero di partenza è vuoto) // Oppure se un nodo non foglia ha un solo figlio if(root == NULL) return 0; // Caso Foglia if(root->left == NULL && root->right == NULL) return root->data; // Caso Ricorsivo int value = root->data; int max_left = cercaMax(root->left, err); int max_right = cercaMax(root->right, err); return max3(value, max_left, max_right); } ``` ## Versione per BST ```c= int cercaMaxOrdinato(Tree root){ if(root == NULL) return 0; if(root->right == NULL) return root->data; return cercaMaxOrdinato(root->right, err); } ``` ==**Nota:** come si gestisce il caso in cui l'albero di partenza è vuoto?== --- # Alberi Identici Scrivere una funzione che prende in inout due alberi e restituisce 1 se i due sono identici ```c= int alberiIdentici(Tree root1, Tree root2){ // Casi base if(root1 == NULL && root2 == NULL) return 1; if(root1 == NULL || root2 == NULL) return 0; // Casi ricorsivi int condizione_nodo = root1->data == root2->data; int condizione_left = alberiIdentici(root1->left, root2->left); int condizione_right = alberiIdentici(root1->right, root2->right); return condizione_nodo && condizione_left && condizione_right; } ``` ---