Il tuo problema è uno dei motivi per cui hanno inventato la programmazione funzionale e ad oggetti.
Si tratta di chiamare un algoritmo su una collezione di dati e "dargli qualcosa da fare" su ogni dato. Quel qualcosa da fare glielo si passa tramite un puntatore a funzione in C, o tramite un oggetto funzione in linguaggi come C++ (che poi contiene sempre un puntatore a funzione).
Un altro problema ancora è quello del tipo di dato su cui lavorare, che nel tuo caso non è sempre lo stesso e il C non fa conversioni facili.
Ho provato a fare una piccola implementazione in cui implemento tramite struct in C un piccolo oggetto funzione chiamato Car_functor, che oltre al puntatore a funzione, ha anche un campo in cui memorizzare il risultato.
Il tipo Car_data è una union, che sembra una struct, ma in realtà ha un solo campo che ha la dimensione del tipo più grande (double), quindi può memorizzare dati di tipi diversi (ma sempre uno per volta!).
Questo ti permette di chiamare gli if / case una sola volta all'inizio e non per ogni valore dell'insieme, ma non di eliminarli.
Non mi sono messo a fare alberi, ma ho usato un banale array.
La funzione WorkArrayCars è quella che nel tuo caso dovrebbe visitare l'albero in profondità e poi "fare qualcosa" sui nodi visitati.
Te la posto a scopo illustrativo, non prenderla come LA soluzione migliore e comunque ti sconsiglio di portarla nella consegna, anche perché ne hai già una.
#include <stdio.h>
#include <stdlib.h>
typedef union{
int intval;
double doubleval;
} Car_data;
typedef struct{
int x;
double y;
} Car;
typedef struct Car_functor Car_functor;
typedef void (*Fun)(Car*, Car_functor*);
struct Car_functor {
Car_data result;
Fun function;
};
void cumulate_y (Car* car, Car_functor* fctr){
fctr->result.doubleval += car->y;
}
void cumulate_x (Car* car, Car_functor* fctr){
fctr->result.intval += car->x;
}
void workArrayCars (Car cars[], int dim, Car_functor* fctr)
{
for (int i=0;i<dim;i++)
fctr->function(&cars[i], fctr);
}
int main()
{
Car cars[5];
int ch;
Car_functor fctr;
for(int i=0;i<5;i++){
cars[i].x = i;
cars[i].y = 0.0 + i;
}
for(int i=0;i<5;i++){
printf("x: %d\t", cars[i].x);
printf("y: %.1f\n", cars[i].y);
}
printf ("\nInserire: \n1: media x\n2: media y\n");
scanf("%d",&ch);
Car_data media;
switch(ch)
{
case 1:
fctr.result.intval = 0;
fctr.function = cumulate_x;
workArrayCars(cars, 5, &fctr);
media.intval = fctr.result.intval / 5;
printf("\nMedia: %d", media.intval);
break;
case 2:
fctr.result.doubleval = 0;
fctr.function = cumulate_y;
workArrayCars(cars, 5, &fctr);
media.doubleval = fctr.result.doubleval / 5;
printf("\nMedia: %.1f", media.doubleval);
break;
}
return 0;
}