Le code suivant fonctionne bien lorsque head est envoyé en tant que paramètre. Comme je suis nouveau en C, je ne comprenais pas comment cela fonctionnait. Aidez-moi s'il vous plaît.
struct node *recursiveReverseLL(struct node *list)
{
struct node *revHead;
if (list == NULL || list->link == NULL)
{
return list;
}
revHead = recursiveReverseLL(list->link);
list->link->link = list;
list->link = NULL;
return revHead;
}
Je ne sais pas comment les liens sont fournis en utilisant ces appels récursifs. c'est à dire) si les liens sont en tant que,
1 -> 2 -> 3 -> 4
alors hw est-il changé comme,
4 -> 3 -> 2 -> 1
L'algorithme récursif général pour cela est:
Divide
la liste en 2
parties - premier nœud .__ et reste de la liste.rest
de la liste chaînée rest
à first
.head
Voici le code avec les commentaires en ligne:
struct node* recursiveReverseLL(struct node* first){
if(first == NULL) return NULL; // list does not exist.
if(first->link == NULL) return first; // list with only one node.
struct node* rest = recursiveReverseLL(first->link); // recursive call on rest.
first->link->link = first; // make first; link to the last node in the reversed rest.
first->link = NULL; // since first is the new last, make its link NULL.
return rest; // rest now points to the head of the reversed list.
}
J'espère que cette image rendra les choses plus claires:
image http://geeksforgeeks.org/wp-content/uploads/2009/07/Linked-List-Rverse.gif .
Solution alternative:
struct node *head;
void reverse(struct node *prev, struct node *cur)
{
if(cur){
reverse(cur,cur->link);
cur->link = prev;
}
else{
head = prev;
}
}
En mode principal, appel inversé (NULL, tête);
/* Reverses a linked list, returns head of reversed list
*/
NodePtr reverseList(NodePtr curr) {
if (curr == NULL || curr->next == NULL) return curr; // empty or single element case
NodePtr nextElement = curr->next;
curr->next = NULL;
NodePtr head = reverseList(nextElement);
nextElement->next = curr;
return head;
}
Une autre solution:
struct node *reverse_recur(struct node *temp)
{
if(temp->link==NULL)
{
return temp;
}
struct node *temp1=temp->link;
temp->link=NULL;
return (reverse_recur(temp1)->link=temp);
}
Il me semble que personne n’a suggéré un algorithme qui est tail-récursif . En principe, un algorithme de type récursif peut être compilé sans pile (à condition que le compilateur soit suffisamment intelligent), produisant ainsi un code qui consomme moins de mémoire.
Supposons que TList
soit un type de données personnalisé pour une liste à lien unique, il s'agit d'un pointeur sur une structure constituant un champ link
permettant d'accéder à l'élément suivant de la liste.
L'algorithme est le suivant:
`` `
TList reverse_aux(TList l, TList solution) {
if (l == NULL) {
return solution;
} else {
TList tmp = l->link;
l->link = solution;
return reverse_aux(tmp, l);
}
}
TList reverse(TList l) {
return reverse_aux(l, NULL);
}
`` `
To fix head also:
void reverse_list_recursive_internal (struct list **head, struct list *node)
{
/* last node, fix the head */
if (node->next == NULL) {
*head = node;
return;
}
reverse_list_recursive_internal(head, node->next);
node->next->next = node;
node->next = NULL;
}
void reverse_list_recursive (struct list **head)
{
if (*head == NULL) {
return;
}
reverse_list_recursive_internal(head, *head);
}
Que la liste chaînée soit 1-> 2 -> 3 -> 4
la fonction en c is--
struct linked_node * reverse_recursive(struct linked_node * head)
{
struct linked_node * first;/*stores the address of first node of the linked
list passed to function*/
struct linked_node * second;/* stores the address of second node of the
linked list passed to function*/
struct linked_node * rev_head;/*stores the address of last node of initial
linked list. It also becomes the head of the reversed linked list.*/
//initalizing first and second
first=head;
second=head->next;
//if the linked list is empty then returns null
if(first=NULL)
return(NULL);
/* if the linked list passed to function contains just 1 element, then pass
address of that element*/
if(second==NULL)
return(first);
/*In the linked list passed to function, make the next of first element
NULL. It will eventually (after all the recursive calls ) make the
next of first element of the initial linked list NULL.*/
first->next=NULL;
/* storing the address of the reverse head which will be passed to it by the
condition if(second==NULL) hence it will store the address of last element
when this statement is executed for the last time. Also here we assume that
the reverse function will yield the reverse of the rest of the linked
list.*/
rev_head=reverse(second);
/*making the rest of the linked list point to the first element. i.e.
reversing the list.*/
second->next=first;
/*returning the reverse head (address of last element of initial linked
list) . This condition executes only if the initial list is 1- not empty
2- contains more than one element. So it just relays the value of last
element to higher recursive calls. */
return(rev_head);
}
lance maintenant la fonction pour la liste chaînée 1-> 2-> 3 -> 4
liste de fonction est
1 (premier) -> 2 (deuxième) -> 3 -> 4
À l'intérieur de reverse (& 2) le code s'exécute jusqu'à ce que rev_head = reverse (& 3); liste de fonctions
2 (premier) -> 3 (deuxième) -> 4
À l'intérieur de reverse (& 3) le code s'exécute jusqu'à ce que rev_head = reverse (& 4); list si function
3 (premier) -> 4 (deuxième)
inside reverse (& 4) condition de fin seconde == NULL est vrai, le retour est exécuté et l'adresse de 4 est renvoyée.
liste de fonction
4(first)-> NULL(second)
après avoir exécuté second-> next = first; la liste devient
NULL <- 3(first) <-4 (seconde)
return (rev_head); est exécuté ce qui passe & 4 car rev_head = & 4
la liste en fonction est
NULL <-2 (premier) 3 (seconde) <- 4
et rev_head est & 4 qui a été retourné par rev (& 3)
après avoir exécuté second-> next = first, la liste devient
NULL <-2 (premier) <- 3 (seconde) <- 4
return (rev_head); est exécuté ce qui retourne & 4 to rev (& 1);
la liste en fonction est
NULL <-1 (premier) 2 (seconde) <- 3 <-4
et la valeur de rev_head est & 4 qui a été passé par reverse (& 3)
maintenant second-> next = le premier est exécuté et la liste devient
NULL <-1 (premier) <- 2 (seconde) <- 3 <-4
return (rev_head); est exécuté // rev_head = & 4 qui a été renvoyé par reverse (& 2) et la valeur de rev_head est transmise à la fonction principale.
j'espère que cela t'aides. Il m'a fallu beaucoup de temps pour comprendre cela et aussi pour écrire cette réponse.
C'est une belle approche que l'on peut suivre pour inverser SLL de manière récursive:
1. struct node* head; // global head
2. void rec_reverse(struct node* prev, struct node* cur)
3. {
4. if (cur)
5. {
6. rec_reverse(cur, cur->next);
7. cur->next = prev;
8. }
9. else
10. head = prev;
11. }
Appelez la fonction de cette façon:
rec_reverse(NULL, head);
Approche: