Mira, es muy fácil:
El dato tiene una estructura clásica de árbol binario
typedef struct _nodo {
int dato;
struct _nodo *izq;
struct _nodo *der;
} Nodo;
Y a partir de aquí se lee la función
void mostrarArbol(Nodo * arbol, unsigned contador){
No estaba puesto, pero considero unsgined a contador pues lo normal es que la raíz sea 0 y vaya ascendiendo a cada nivel, por tanto los números negativos no son aptos para este menester.
mostrarArbol recibe el puntero a un tipo Nodo para no andar todos los datos de cada estructura, contador indicará la profundidad del nivel a que se encuentra (esto lo saco de más adelante como veremos).
if(arbol == NULL){
return;
}
Este es la condición de fin de recursividad. Ésta se detendrá al llegar a un nodo vacío, es decir, cuándo se esté fuera del árbol.
else{
mostrarArbol(arbol->der, contador+1);
Pero si la nodo forma parte del árbol se seguirá por su rama derecha. No hay que preocuparse por si está vacía, ya que hemos visto anteriormente que la función se encarga de terminar la búsqueda si eso pasa. Además se le indica a la función que el siguiente nivel será uno mas que éste, con contador+1. No se ha usado contador++ porque se quiere retener, para la actual instancia de la función, del valor que guarda.
for(int i=0; i<contador; i++){
cout << " ";
}
cout << arbol->dato << endl;
Y por esto es por lo que se necesita el dato de contador: a cada nivel se le representa su profundidad con un espacio. Al final de los espacios se coloca el dato que hay en el nodo. Así la representación es más visual.
mostrarArbol(arbol->izq, contador + 1);
}
}
Se procede a realizar con la rama izquierda lo que se hacía con la derecha.