Salta al contenuto
Note per Studenti Esercizio 27 · C, resistenza equivalente di un circuito (albero)

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 R1R_1 in serie con il parallelo di R2R_2 ed R3R_3 è rappresentato dall'albero con radice Serie, figlio sinistro R1R_1 e figlio destro Parallelo con figli R2R_2 e R3R_3. In C:

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:

  1. double combinaResistenze(double a, double b, TipoNodo tipo): restituisce la resistenza equivalente di due blocchi. Per un collegamento in serie vale a+ba + b; in parallelo (a⋅b)/(a+b)(a \cdot b)/(a + b).
  2. double resistenzaEquivalente(Circuito *root): calcola ricorsivamente la resistenza equivalente dell'intero circuito. Per un puntatore NULL restituisce 0,00{,}0. I test usano circuiti validi, in cui ogni nodo interno ha due figli.
  3. int contaResistori(Circuito *root): conta ricorsivamente quante resistenze singole, cioè nodi di tipo RESISTORE, 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 100 Ω100\,\Omega in serie con il parallelo di due resistenze da 200 Ω200\,\Omega ha resistenza equivalente 200 Ω200\,\Omega: il parallelo vale 100 Ω100\,\Omega e il collegamento in serie aggiunge gli altri 100 Ω100\,\Omega.


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

c
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à Θ(n)\Theta(n) tempo (una chiamata per nodo) e O(h)O(h) stack.

Dettagli.

  • Per a+b=0a + b = 0 il parallelo divide per zero: nei circuiti dei test le resistenze sono positive, quindi non succede. Con un ramo in cortocircuito (a=0a = 0) la formula darebbe 0/b=00/b = 0, corretta.
  • Si usano double e non int: (ab)/(a+b)(a b)/(a + b) in aritmetica intera troncherebbe il risultato.
  • Si controlla root->tipo per distinguere foglia e nodo interno, senza guardare i figli: nelle foglie sono NULL, ma è il tipo a definire il significato del nodo.

Prove eseguite

Circuito ReqR_{eq} Resistori
100+(200∥200)100 + (200 \parallel 200) 200,0200{,}0 33
(10∥10)∥10(10 \parallel 10) \parallel 10 3,33333{,}3333 33
una sola resistenza da 4747 47,047{,}0 11
albero vuoto (NULL) 0,00{,}0 00

(Controllo: (10∥10)=5(10 \parallel 10) = 5 e 5∥10=5015=3,333…5 \parallel 10 = \frac{50}{15} = 3{,}333\dots; combinaResistenze(3, 6, SERIE) =9= 9, combinaResistenze(3, 6, PARALLELO) =2= 2. Provato compilando con gcc -std=c99.)

Errori comuni

Versione ripasso

Testo. Circuito di resistenze come albero binario proprio (RESISTORE, SERIE, PARALLELO); implementare combinaResistenze(a, b, tipo) (serie a+ba + b, parallelo aba+b\frac{ab}{a+b}), resistenzaEquivalente(Circuito*) (ricorsiva, NULL →0,0\to 0{,}0) e contaResistori(Circuito*).

Teoria collegata