Estoy teniendo un tiempo horrible con la reversión de la lista vinculada por recursión. ¿Cómo entiendo los pasos para lo mismo?

La recursión es solo llamar a una función varias veces.

La clave para entender es que cuando se vuelve a llamar a la función, el estado anterior se almacena por separado en la pila de memoria. Llame a esto un estado de función si puede. Cada uno de estos estados de función que se almacenan en la pila de memoria tienen valores de variables iguales a los valores durante su ejecución.

Tomando un ejemplo.

Tome esta implementación geeksforgeeks de reversión de una lista vinculada.

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest; /* empty list */
if (*head_ref == NULL)
return; /* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next; /* List has only one node */
if (rest == NULL)
return; /* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first; /* tricky step -- see the diagram */
first->next = NULL; /* fix the head pointer */
*head_ref = rest;
} int main()
{ node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3); recursiveReverse(&head);
return 0;
}

Deje que el enlace que estamos invirtiendo sea 1-> 2-> 3
ahora en la primera llamada de función
head_ref tiene la dirección del nodo (1)
primeros puntos a 1
el resto apunta al primero-> siguiente, que es el nodo (2)

ahora repetimos. Ahora los valores anteriores se guardan en un estado separado y se almacenan en la pila.

ahora se creará un estado completamente nuevo para esta función llamada donde
head_ref tiene la dirección del nodo (2)
primeros puntos a 2
el resto apunta al primero-> siguiente, que es el nodo (3)

volvemos a repetir y los valores anteriores se almacenan en otro estado en la pila.

ahora nuevamente se creará un estado completamente nuevo para esta llamada de función donde
head_ref tiene la dirección del nodo (3)
primeros puntos a 3
puntos de descanso a NULL

ahora que rest == NULL volvemos a nuestro estado anterior.
en este estado los valores son:
primeros puntos a 2
el resto apunta al primero-> siguiente, que es el nodo (3)

así que después de las manipulaciones del puntero, la lista vinculada se volvería así
1-> 2 <-3
head_ref ahora almacena la dirección del nodo (3)

y volvemos a nuestro primer estado donde
primeros puntos a 1
el resto apunta al primero-> siguiente, que es el nodo (2)
pero dado que la dirección de descanso se pasó durante la llamada recursiva. cambiamos el valor de rest cuando realizamos * head_ref = rest antes de regresar.

después de la manipulación, la lista ahora se convierte
1 <-2 <-3
esta es nuestra primera llamada de función donde head_ref era el puntero real de la lista vinculada desde donde se llamó. * head_ref = rest en la llamada anterior cambia el valor del puntero rest en esta llamada de función, por lo que rest ahora apunta al nodo (3).
y realizar * head_ref = rest cambia nuestra cabeza original para que apunte al nodo (3).

invirtiendo así la lista vinculada.

Cada problema resuelto de una manera puede resolverse de otra manera. Prueba esto. Ponga cada elemento de la lista vinculada en una pila. Salga y reconstruya la lista vinculada. La recursión hace exactamente eso, aunque es difícil de ver. A veces está sobrevalorado.

No te golpees la cabeza.
Verifique esto: Invierta una lista vinculada – Recursiva
Mira el video incrustado en la página web, explicado extremadamente bien. Toma mi palabra, te encantará.
Finalmente, repita el algoritmo y visualícelo en la página misma.

Ahora para su problema con los algoritmos recursivos, le sugiero que comience con problemas basados ​​en árboles. La mayoría de los algoritmos / problemas basados ​​en árboles tienen un enfoque recursivo. Sería poco difícil en los problemas iniciales, pero eventualmente comenzará a visualizar un enfoque recursivo y, por lo tanto, al final de sus ‘malos momentos’ 🙂
Te sugiero que pases por IDeserve. Este portal tiene videos para varios problemas que lo ayudarán con la preparación de entrevistas tecnológicas. La mejor de las suertes.

Gracias por A2A, Ravi Shekhawat

Puede consultar el siguiente enlace para obtener una de las mejores explicaciones de este problema utilizando imágenes:

Escribir una función para revertir una lista vinculada – GeeksforGeeks

Sin embargo, si no comprende, simplemente comente la respuesta y lo intentaré con mis palabras.