Recursively reverse a linkedlist (code in Stanford CSed library) explanation

…衆ロ難τιáo~ 提交于 2020-01-15 06:09:04

问题


My recursion skill is pretty rusty. I've been thinking about this problem and searched the forum for a long time but still cannot understand. Right now I'm looking at the recursively reverse a linked list code from Stanford CS ed library.

#include <stdio.h> 

struct Node {
  int x;
  struct Node *next;
};

void Reverse(struct Node ** headRef){
    struct Node* first;
    struct Node* rest;

    if(*headRef==NULL)
       return;

    first= *headRef;
    rest= first->next;  

    if(rest==NULL)
        return; 

    Reverse(&rest);
    printf("Rest%d\n", (rest)->x); // I added this line to print rest
    first->next->next=first;
    first->next=NULL;
    *headRef=rest;
}

void printList(struct Node* head){

    if(!head)
       return;
    else{
       printf("%d ", head->x);
       printList(head->next);   
    }
}

void main(){
    struct Node *head;
    struct Node * node1= (struct Node*) malloc(sizeof(struct Node));
    struct Node * node2= (struct Node*) malloc(sizeof(struct Node));
    struct Node * node3= (struct Node*) malloc(sizeof(struct Node));
    struct Node * node4= (struct Node*) malloc(sizeof(struct Node));
    head= node1;
    node1->next=node2;
    node1->x=1;
    node2->x=2;
    node3->x=3;
    node4->x=4;
    node2->next=node3;
    node3->next=node4;
    node4->next=NULL;
    Reverse(&head);
}

Now suppose I have a linked list 1->2->3->4. What I cannot understand is the last line, which will set the headRef to 4 eventually, I think it should set the headRef to 2. I tried to execute the function and it printed out:

4
4
4

for the variable rest.

However, if I commented the last line in the the Reverse function out, it still reversed the list but would print

4
3
2.

The second result I can understand, but the first one seemed quite confusing. Does the statement "*headRef=rest" do any thing to the variable rest? What does it keep pointing to 4?

Also, if I pass *headRef instead of **headRef (last line is not commented out), it would print the result

4
3
2

too.

Could anyone please explain to me what happened in the memory? Thanks a million.


回答1:


Before the recursive call to Reverse we have:

first---|  
        |  
        v  
        1->2->3->4->NULL
           ^
           |
           |
  rest------

After the recursive call to Reverse we have:

first---|
        |
        v
        1->2<-3<-4
           |     ^
           v     |
         NULL    |
  rest------------

Now we need to fix 2->NULL to 2->1 by first->next->next=first.

first---|
        |
        v
        1<-2<-3<-4
        |  ^     ^
        |--|     |
                 |
  rest------------

Now we need to fix 1->2 to 1->NULL by first->next=NULL.

first---|
        |
        v
  NULL<-1<-2<-3<-4
                 ^
                 |
                 |
  rest------------

Finally *headRef=rest so that *headRef will point to 4 instead of to 1.




回答2:


What happens here is as because the recursive call passes the address of rest to the local variable headRef, when each recursive call returns, the statement *headRef=rest already changes the address of rest pointer for the statements coming next in the execution flow.

For the linked list 1->2->3->4 :

Let us assume 1 is stored in address 100, 2 in address 200, 3 in address 300 and 4 in address 400.

PART 1: the call Reverse(&rest) [rest points to address 400]

first = 400 rest = NULL

as rest is NULL the execution returns to the point after Reverse(400) call

PART 2: Here first = 300 and rest = 400 after execution of first->next->next=first and first->next=NULL

we have *headRef=rest [rest points to 400]

but this headRef was passed an address of rest=300. So now already for the next step in execution, rest points to 400.

PART 3: Now execution returns to the point after Reverse(300) call

But during forward call [first was 200 and rest was 300] and during return [rest = 400]. HERE'S THE TRICK!!!

after execution of first->next->next=first and first->next=NULL

we have *headRef=rest [rest points to 400]

but this headRef was passed an address of rest=200. So now already for the next step in execution, rest points to 400.

PART 4: Now execution returns to the point after Reverse(200) call

But during forward call [first was 100 and rest was 200] and during return [rest = 400].

after execution of first->next->next=first and first->next=NULL

we have *headRef=rest [rest points to 400]

and as because this is the initial call, the function returns with *headRef having 400 value.

JOB DONE!



来源:https://stackoverflow.com/questions/12230648/recursively-reverse-a-linkedlist-code-in-stanford-csed-library-explanation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!