Duda con recursividad, punteros y parametros por dirección

Iniciado por jmrivas, 7 Julio 2014, 07:18 AM

0 Miembros y 1 Visitante están viendo este tema.

jmrivas

Hola a todos, ¿Cómo va?. Soy nuevo acá y decidí consultar a los que mas saben a ver si pueden darme una mano. En realidad es una simple duda que tengo que me surgió hoy mientras estaba estudiando recursividad para la facultad.



Código (cpp) [Seleccionar]

typedef struct nodo{
char info;
nodo* sig;
};

void TOBA(nodo* l1, nodo*& l2);


Código (cpp) [Seleccionar]

void main(){
nodo nodo1;
nodo nodo2;
nodo nodo3;
nodo nodo4;
nodo nodo5;
nodo aux;

nodo* pnodo1;
nodo* pnodo2;
nodo* pnodo3;
nodo* pnodo4;
nodo* pnodo5;
nodo* paux;

pnodo1 = &nodo1;
pnodo2 = &nodo2;
pnodo3 = &nodo3;
pnodo4 = &nodo4;
pnodo5 = &nodo5;
paux = &aux;


pnodo1->info = 'a';
pnodo1->sig = pnodo2;
pnodo2->info = 'e';
pnodo2->sig = pnodo3;
pnodo3->info = 'i';
pnodo3->sig = pnodo4;
pnodo4->info = 'o';
pnodo4->sig = pnodo5;
pnodo5->info = 'u';
pnodo5->sig = NULL;

paux = NULL;
TOBA(pnodo1, paux);
        getchar();
}


Código (cpp) [Seleccionar]

void TOBA(nodo*& l1, nodo*& l2){
nodo* x;

if(l1 != NULL){
TOBA(l1->sig,l2);
x = l1;
l1 = l1->sig;
x ->sig = l2;
l2 = x;
}
else{
l1 = l2;
}
}



Mi duda surge en lo siguiente, cuando la función recursiva llega al final de la lista, asigna a l1 (la lista) el valor de l2 que es NULL (a l2 se le asigna valor en el main). Como ven en el encabezado de la función, el parametro l1 tiene '&' por lo tanto va por dirección, es decir, que cuando la función detecto l1 == NULL, le asigno el valor de l2. Cuando la función va a seguir con el desarrollo de la misma de los llamados que quedaron pendientes, ¿por qué motivo l1 tiene el valor de cuando se llamó en vez de tener NULL? Ya que según lo que yo aprendí si ese parámetro se pasa por dirección, cuando vuelva a atender las instrucciones pendientes el parámetro l1 debería tener el valor que se le asignó.

Espero que se entienda mi pregunta, sino cualquier cosa intentaré explicarlo mejor.
Es mas una duda conceptual, y quisiera entender el porqué.

Muchas gracias de antemano.

eferion

Nota incial: Usa las etiquetas GeSHi para poner código fuente en tus mensajes.

Dicho esto, vamos al grano.

Código (cpp) [Seleccionar]

void TOBA(nodo*& l1, nodo*& l2)
{
  nodo* x;

  if(l1 != NULL)
  {
    // ...
  }
  else
  {
    // ...
  }
}


l1 o es puntero (usas el asterisco) o es una referencia (usas el amdpersand)... pero no mezcles los dos en la misma sentencia... Si necesitas modificar la posición de memoria a la que apuntan los punteros, usa punteros dobles. No hagas inventos raros si no estás totalmente seguro de lo que estás haciendo.

Además, la lógica de esa función es un poco extraña... ¿Qué se supone que estás intentando hacer? Llamar a TOBA de forma recursiva va a hacer que ejecutes el código:

Código (cpp) [Seleccionar]

x = l1;
l1 = l1->sig;
x ->sig = l2;
l2 = x;


un número indeterminado de veces... además, el nombre que tiene esa función no aporta absolutamente nada de información que permita "descifrar" o "comprender" mínimamente tus intenciones.

Hay que tener mucho cuidado a la hora de programar funciones recursivas... los resultados pueden ser catastróficos en caso contrario.

jmrivas

Hola, ante todo muchas gracias por contestar. Ahí agregué las etiquetas Geshi para que el código sea un poco mas claro. Si entiendo que la función es un poco confusa, es un ejercicio que dio el profesor y nosotros tenemos que realizar el seguimiento de la función para ver cual es el resultado final.
El seguimiento a la función yo lo hice, y lo que hace es recorrer la lista hasta llegar al final de la misma (NULL) y luego ejecuta las instrucciones a continuación a medida que va desagotando la pila de llamadas. En conclusión, esas instrucciones pasan la lista completa del puntero l1 al puntero l2.

Código (cpp) [Seleccionar]

x = l1;
l1 = l1->sig;
x ->sig = l2;
l2 = x;


Con respecto a lo que me decias del ampersand, si yo quiero que el valor del puntero se mantenga una vez que termina la función (cuando regresa al método main), ¿No es correcto poner el & en el encabezado para ese parámetro?


eferion

Cita de: jmrivas en  7 Julio 2014, 16:31 PM
¿No es correcto poner el & en el encabezado para ese parámetro?

No hace falta hacer cosas raras para programar. El código limpio y sencillo es mucho más sencillo de mantener que uno con "ideas felices". O usas punteros o usas referencias, pero artilugios raros como punteros a referencias o referencias a punteros pueden darte más de un disgusto. Además no parece una solución demasiado limpia.

Por otro lado... se supone que la idea es mover los elementos de una lista a otra??? ¿copiarlos tal vez?