开发者

Linked list recursive reverse

I was looking at the code below from stanford library:

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 = *hea开发者_运维百科d_ref;
    rest  = first->next;

    /* List has only one node */
    if (rest == NULL)
       return;  

    /* put the first element on the end of the list */
    recursiveReverse(&rest);
    first->next->next  = first; 

    /* tricky step -- see the diagram */
    first->next  = NULL;         

    /* fix the head pointer */
    *head_ref = rest;
}

What I don't understand is in the last recursive step for e.g if list is 1-2-3-4 Now for the last recursive step first will be 1 and rest will be 2. So if you set *head_ref = rest .. that makes the head of the list 2 ?? Can someone please explain how after reversing the head of the list becomes 4 ??


Draw out a stack trace...

Intial - {1,2,3,4}
Head - 1
Rest = 2,3,4
Recurse(2,3,4)
Head = 2
Rest = 3,4
Recurse(3,4)
Head = 3 
Rest = 4
Recurse (4)
Head = 4
Rest = null //Base Case Reached!! Unwind.

So now we pick up 
Recurse(3,4)
Head = 3 
Rest = 4
// Return picks up here
first->next->next  = first; 
so list is:
3,4,3
// set head to null,
null ,4,3,
//Off with his head!
4,3
Return

Now we're here
Recurse(2,3,4)
Head = 2
Rest = 3,4
Previous return leaves state as:
Head = 2  //But Head -> next is still 3! -- We haven't changed that yet..
Rest = 4,3  
Head->next is 3, 
Head->next->next = 2 makes the list (actually a tree now)
4->3->2
   ^
   |
   2
And chop off the head leaving
4->3->2
and return.

Similarly, do the last step which will leave
4->3->2->1
      ^
      |
      1
and chop off the head, which removes the one. 


Consider the list:

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

Where first points to the first node and rest points to the node next to first.

Since the list is not empty and list does not contain one node we make recursive call to reverse to reverse the list pointed to by rest. This is how the list looks after reversing the rest of the list:

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

As seen rest now points to the reversed list which has 4 at the beginning and 2 at the end of list. The next pointer of node 2 is NULL.

Now we need to append the first node to the end of the reversed-rest list. To append anything to the end of the list we need to have access to the last node of the list. In this case we need to have access to the last node of the reversed-rest list. Look at the diagram, first -> next points to the last node reversed-rest list. Therefore first -> next -> next will be next pointer of the last node of the reversed-rest list. Now we need to make it point to first so we do:

first -> next -> next = first;

After this step the list looks like:

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

Now the next field of the last node of the list must be NULL. But it is not the case now. The next field of the last node ( node 1) is pointing to the node before it ( node 2). To fix this we do:

first -> next = NULL;

After this the list looks like:

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

As seen the list is now correctly reversed with rest pointing to the head of the reversed list.

We need to return the new head pointer so the that changes are reflected in the calling function. But this is a void function and head is passed as double pointer so changing the value of *head will make the calling function see the changed head:

*head = rest;


The rest isn’t 2, it’s 2 -> 3 -> 4, which gets reversed recursively. After that we set *head_ref to rest, which is now (recursively reversed!) 4 -> 3 -> 2.

The important point here is that although both first and rest have the same type, i.e. node*, they are conceptually fundamentally different: first points to one single element, while rest points to a linked list of elements. This linked list is reversed recursively before it gets assigned to *head_ref.


I recently wrote a recursive method for reversing a linked list in ruby. Here it is:

def reverse!( node_1 = @head, node_2 = @head.link )
    unless node_2.link 
        node_2.link = node_1
        @head = node_2
        return node_1
    else 
        return_node = reverse!(node_1.link, node_2.link)
        return_node.link = node_1
        node_1.link = nil
        return node_1
    end
    return self
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜