Esercizio 27C, resistenza equivalente di un circuito (albero)
In questa pagina 4
Testo (scritto del 24/06/2026, parte 3, in C). Circuiti di resistenze. Svolgi il seguente esercizio sviluppando le funzioni richieste in C. I prototipi delle funzioni non possono essere modificati. Durante l'esame non è possibile consultare appunti o materiale didattico; è consentito utilizzare la documentazione Linux con man.
Un simulatore di circuiti elettrici elementari rappresenta un circuito costituito esclusivamente da resistenze mediante un albero binario proprio. Ogni foglia rappresenta una singola resistenza. Ogni nodo interno rappresenta il collegamento di due sotto-circuiti: il nodo indica se i due sotto-circuiti figli sono collegati in serie oppure in parallelo. Di conseguenza ogni sottoalbero rappresenta un sotto-circuito. Ad esempio un circuito con in serie con il parallelo di ed è rappresentato dall'albero con radice Serie, figlio sinistro e figlio destro Parallelo con figli e . In C:
typedef enum tipo_nodo { RESISTORE, SERIE, PARALLELO } TipoNodo;
typedef struct circuito {
TipoNodo tipo;
double valore;
struct circuito *left;
struct circuito *right;
} Circuito;Per i nodi di tipo RESISTORE, il campo valore contiene la resistenza in ohm e i figli sono NULL. Per i nodi SERIE o PARALLELO, valore non è usato e i figli rappresentano i due sotto-circuiti collegati.
Funzioni da completare:
double combinaResistenze(double a, double b, TipoNodo tipo): restituisce la resistenza equivalente di due blocchi. Per un collegamento in serie vale ; in parallelo .double resistenzaEquivalente(Circuito *root): calcola ricorsivamente la resistenza equivalente dell'intero circuito. Per un puntatoreNULLrestituisce . I test usano circuiti validi, in cui ogni nodo interno ha due figli.int contaResistori(Circuito *root): conta ricorsivamente quante resistenze singole, cioè nodi di tipoRESISTORE, sono presenti nel circuito.
Indicazioni: la visita dell'albero deve essere ricorsiva; si possono definire funzioni ausiliarie; non modificare main() e le funzioni di test; il Makefile collega la libreria matematica con -lm. Esempio: una resistenza da in serie con il parallelo di due resistenze da ha resistenza equivalente : il parallelo vale e il collegamento in serie aggiunge gli altri .
Richiami
Alberi in C e visite ricorsive: Alberi e heap in CAlbero binario in C con nodo struct e figli left/right; funzioni ricorsive (conteggio, altezza, visita inorder, liberazione in postorder); inserimento in un albero binario di ricerca con Nodo **; min-heap su array con indici da 1 (insert, removeMin, bottomUp).Alberi e heap in C →. Valutazione di un albero binario proprio con una visita in postorder: il valore di un nodo interno dipende dai valori dei figli (vedi Alberi binariAlbero binario e albero binario proprio; interfaccia; relazioni tra nodi, foglie e altezza (m = n-m+1, h+1 <= m <= 2^h, 2h+1 <= n <= 2^(h+1)-1) con dimostrazioni; visita inorder; parse tree e valutazione di espressioni; heightSum come esempio di calcolo di un'informazione più ricca.Alberi binari →, analogo alla valutazione di un'espressione).
Soluzione
double combinaResistenze(double a, double b, TipoNodo tipo) {
if (tipo == SERIE)
return a + b;
return (a * b) / (a + b); /* PARALLELO */
}
double resistenzaEquivalente(Circuito *root) {
if (root == NULL)
return 0.0;
if (root->tipo == RESISTORE)
return root->valore;
double a = resistenzaEquivalente(root->left);
double b = resistenzaEquivalente(root->right);
return combinaResistenze(a, b, root->tipo);
}
int contaResistori(Circuito *root) {
if (root == NULL)
return 0;
if (root->tipo == RESISTORE)
return 1;
return contaResistori(root->left) + contaResistori(root->right);
}Struttura. Entrambe le funzioni sono visite ricorsive: caso base NULL (e foglia = RESISTORE), poi si combinano i risultati dei due figli. resistenzaEquivalente è un postorder in cui la "visita" è combinaResistenze. Complessità tempo (una chiamata per nodo) e stack.
Dettagli.
- Per il parallelo divide per zero: nei circuiti dei test le resistenze sono positive, quindi non succede. Con un ramo in cortocircuito () la formula darebbe , corretta.
- Si usano
doublee nonint: in aritmetica intera troncherebbe il risultato. - Si controlla
root->tipoper distinguere foglia e nodo interno, senza guardare i figli: nelle foglie sonoNULL, ma è il tipo a definire il significato del nodo.
Prove eseguite
| Circuito | Resistori | |
|---|---|---|
| una sola resistenza da | ||
albero vuoto (NULL) |
(Controllo: e ; combinaResistenze(3, 6, SERIE) , combinaResistenze(3, 6, PARALLELO) . Provato compilando con gcc -std=c99.)
Errori comuni
- Usare la divisione tra interi (
int a, b) o dimenticare la parentesi in(a * b) / (a + b). - Dimenticare il caso
RESISTOREe richiamarsi ricorsivamente sui figliNULL(non rompe, macombinaResistenzeverrebbe chiamata con tipoRESISTOREe darebbe un risultato errato). - Contare i nodi interni invece delle foglie in
contaResistori: i resistori sono le foglie (in un albero proprio sono , vedi Alberi binariAlbero binario e albero binario proprio; interfaccia; relazioni tra nodi, foglie e altezza (m = n-m+1, h+1 <= m <= 2^h, 2h+1 <= n <= 2^(h+1)-1) con dimostrazioni; visita inorder; parse tree e valutazione di espressioni; heightSum come esempio di calcolo di un'informazione più ricca.Alberi binari →). - Confondere serie e parallelo: la serie somma, il parallelo ha la resistenza equivalente minore di ciascun ramo.
Versione ripasso
Testo. Circuito di resistenze come albero binario proprio (RESISTORE, SERIE, PARALLELO); implementare combinaResistenze(a, b, tipo) (serie , parallelo ), resistenzaEquivalente(Circuito*) (ricorsiva, NULL ) e contaResistori(Circuito*).
- Postorder (vedi Alberi binariAlbero binario e albero binario proprio; interfaccia; relazioni tra nodi, foglie e altezza (m = n-m+1, h+1 <= m <= 2^h, 2h+1 <= n <= 2^(h+1)-1) con dimostrazioni; visita inorder; parse tree e valutazione di espressioni; heightSum come esempio di calcolo di un'informazione più ricca.Alberi binari →):
NULL⇒ ;RESISTORE⇒valore(o nel conteggio); altrimenti si combinano i valori dei due figli concombinaResistenze. - Codice:
combinaResistenze:tipo == SERIE ? a + b : (a * b) / (a + b);contaResistori: somma dei due figli. - Complessità: , stack (vedi Alberi e heap in CAlbero binario in C con nodo struct e figli left/right; funzioni ricorsive (conteggio, altezza, visita inorder, liberazione in postorder); inserimento in un albero binario di ricerca con Nodo **; min-heap su array con indici da 1 (insert, removeMin, bottomUp).Alberi e heap in C →).
- Prove: (3 resistori); ; una resistenza ⇒ , ;
NULL⇒ , . - Codice:
combinaResistenze:tipo == SERIE ? a + b : (a * b) / (a + b);resistenzaEquivalente:NULL,RESISTOREvalore, altrimenticombinaResistenze(eq(left), eq(right), tipo);contaResistori:NULL,RESISTORE, altrimenti somma dei figli. - Controllo: , .
- Dettagli:
doublee nonint(la divisione intera tronca); si distingue foglia e nodo interno dal campotipo; parallelo con non compare nei test (resistenze positive). - Errori: divisione tra interi; caso
RESISTOREomesso; contare i nodi interni; serie e parallelo scambiati.