Hola Fabricio,
¿Notaste que tu función recibe una lista como parámetro, pero luego en las llamadas recursivas no le pasas dicho parámetro?
Además, al estar recibiendo una lista vacía, como lo especifica la precondición, ¿por qué no te convence declarla dentro de la función en lugar de recibirla como parámetro?.
En cuanto a la funcionalidad del código, hay un tema con el manejo de l, veamos el recorrido del puntero l a lo largo del código.
Primero, le asignamos el resultado de invocar a la función con arb->izq:
l = enOrden(arb->izq);
es decir, que si todo sale bien, entonces l está apuntando al primer elemento de la lista resultante de realizar un recorrido en orden del subárbol izquierdo de arb. Acá, hay que tener en cuenta, sin embargo, que el subárbol izquierdo de arb puede ser vacío, y por lo tanto, el resultado de la invocación podría ser NULL.
Después, al mismo l, le hacemos un new nodoLista:
l = new nodoLista;
que lo que hace es que ahora ese l pase a apuntar a un nodo nuevo en memoria, pero ¿qué pasó con la lista resultante de invocar a la función con el subárbol izquierdo? La única referencia que teníamos hacia dicha lista era l, y ahora l "apunta" a otro lado, por lo tanto esa referencia se perdió. Es decir, habría que usar un puntero diferente para mantener la referencia al resultado de la primer invocación.
Luego cargamos el nuevo nodo (apuntado por l) con el elemento que está en la raíz del árbol, y hacemos que l->sig sea NULL:
l->elem = arb->elem;
l->sig = NULL;
pero luego, en la instrucción siguiente, le asignamos a l el valor de l->sig:
l = l->sig;
por lo que l ahora pasa a valer NULL y perdimos entonces la única referencia que teníamos al nuevo nodo que contenía el elemento de la raíz del árbol.
Luego, asignamos a l el resultado de la invocación a la función con el subárbol derecho:
l = enOrden(arb->der);
por lo que ahora l pasa a apuntar al primer nodo de la lista resultante de dicha invocación, pero en el camino perdimos tanto al resultado de enOrden(arb->izq), como al nuevo nodo que contenía al elemento de la raíz.
Esto nos dice que nos convendría utilizar al menos 3 punteros de tipo lista diferentes
- uno para guardar la lista resultante de invocar a la función con el subárbol izquierdo, por ejemplo Lista lizq = enOrden(arb->izq);
- otro para crear y guardar el nodo que contiene al elemento de la raiz del árbol, por elemplo Lista raiz = new nodoLista; raiz->elem = arb->elem;
- el último para guardar la lista resultante de invocar a la función con el subárbol derecho, por ejemplo Lista lder = enOrden(arb->der);
Y luego, teniendo en cuenta que las listas lizq y lder pueden ser vacías, y por lo tanto, valer NULL, hay que separar por casos y ver en cada caso cómo deberíamos concatenar ambas listas y el nodo que tiene el elemento de la raíz del árbol para obtener la lista que debemos retornar.
Teniendo siempre en cuenta que si yo muevo el único puntero que está referenciando a un cierto lugar, entonces perdí la única referencia que tenía hacia ese lugar, por lo que si era información que deseo mantener entonces tendría que moverme con un puntero auxiliar, o guardar esa información en un puntero auxiliar antes de mover el original, y si no es información que deseo mantener, entonces debo liberarla antes de perder la referencia a ella.
En cuanto a tu pregunta, dado lo que vimos, si el árbol no es vacío l va a retornar el resultado de invocar a enOrden con el subárbol derecho de arb, porque es el último valor que le fue asignado.
Es un poco difícil de explicar todo esto por acá (y de entender), así que cualquier duda que te genere no dudes en volver a consultar,
Intenta hacerlo de nuevo con esto en mente y lo vemos,
Saludos!